visual-tracking-control
VisualServoingServer.cpp
Go to the documentation of this file.
1 #include "VisualServoingServer.h"
2 
3 #include <iCub/ctrl/minJerkCtrl.h>
4 #include <opencv2/core/core.hpp>
5 #include <opencv2/imgproc/imgproc.hpp>
6 #include <yarp/math/Math.h>
7 #include <yarp/math/SVD.h>
8 #include <yarp/os/Network.h>
9 #include <yarp/os/Property.h>
10 #include <yarp/os/Time.h>
11 
12 using namespace yarp::dev;
13 using namespace yarp::math;
14 using namespace yarp::os;
15 using namespace yarp::sig;
16 using namespace iCub::ctrl;
17 
18 
19 /* Ctors and Dtors */
21 {
22  yInfo() << "*** Invoked VisualServoingServer ctor ***";
23  yInfo() << "*** VisualServoingServer constructed ***";
24 }
25 
26 
28 {
29  yInfo() << "*** Invoked VisualServoingServer dtor ***";
30  yInfo() << "*** VisualServoingServer destructed ***";
31 }
32 
33 
34 /* DeviceDriver overrides */
35 bool VisualServoingServer::open(Searchable &config)
36 {
37  verbosity_ = config.check("verbosity", Value(false)).asBool();
38  yInfo() << "|> Verbosity: " + ConstString(verbosity_? "ON" : "OFF");
39 
40  sim_ = config.check("simulate", Value(false)).asBool();
41  yInfo() << "|> Simulation: " + ConstString(sim_? "TRUE" : "FALSE");
42 
43 
44  yInfoVerbose("*** Configuring VisualServoingServer ***");
45 
46 
47  robot_name_ = config.check("robot", Value("icub")).asString();
48  if (robot_name_.empty())
49  {
50  yErrorVerbose("Robot name not provided!");
51  return false;
52  }
53  else
54  yInfoVerbose("|> Robot name: " + robot_name_);
55 
56 
57  if (!port_pose_left_in_.open("/visualservoing/pose/left:i"))
58  {
59  yErrorVerbose("Could not open /visualservoing/pose/left:i port!");
60  return false;
61  }
62  if (!port_pose_right_in_.open("/visualservoing/pose/right:i"))
63  {
64  yErrorVerbose("Could not open /visualservoing/pose/right:i port!");
65  return false;
66  }
67 
68 
69  if (!port_image_left_in_.open("/visualservoing/cam_left/img:i"))
70  {
71  yErrorVerbose("Could not open /visualservoing/cam_left/img:i port!");
72  return false;
73  }
74  if (!port_image_left_out_.open("/visualservoing/cam_left/img:o"))
75  {
76  yErrorVerbose("Could not open /visualservoing/cam_left/img:o port!");
77  return false;
78  }
79 
80 
81  if (!port_image_right_in_.open("/visualservoing/cam_right/img:i"))
82  {
83  yErrorVerbose("Could not open /visualservoing/cam_right/img:i port!");
84  return false;
85  }
86  if (!port_image_right_out_.open("/visualservoing/cam_right/img:o"))
87  {
88  yErrorVerbose("Could not open /visualservoing/cam_right/img:o port!");
89  return false;
90  }
91 
92 
93  if (!port_click_left_.open("/visualservoing/cam_left/click:i"))
94  {
95  yErrorVerbose("Could not open /visualservoing/cam_left/click:in port!");
96  return false;
97  }
98  if (!port_click_right_.open("/visualservoing/cam_right/click:i"))
99  {
100  yErrorVerbose("Could not open /visualservoing/cam_right/click:i port!");
101  return false;
102  }
103 
104 
105  if (!setGazeController()) return false;
106 
107  if (!setRightArmCartesianController()) return false;
108 
109 
110  Bottle btl_cam_info;
111  itf_gaze_->getInfo(btl_cam_info);
112  yInfoVerbose("[CAM]" + btl_cam_info.toString());
113  Bottle* cam_left_info = btl_cam_info.findGroup("camera_intrinsics_left").get(1).asList();
114  Bottle* cam_right_info = btl_cam_info.findGroup("camera_intrinsics_right").get(1).asList();
115 
116  double left_fx = cam_left_info->get(0).asDouble();
117  double left_cx = cam_left_info->get(2).asDouble();
118  double left_fy = cam_left_info->get(5).asDouble();
119  double left_cy = cam_left_info->get(6).asDouble();
120 
121  yInfoVerbose("[CAM] Left camera intrinsic parameters:");
122  yInfoVerbose("[CAM] - fx: " + std::to_string(left_fx));
123  yInfoVerbose("[CAM] - fy: " + std::to_string(left_fy));
124  yInfoVerbose("[CAM] - cx: " + std::to_string(left_cx));
125  yInfoVerbose("[CAM] - cy: " + std::to_string(left_cy));
126 
127  l_proj_ = zeros(3, 4);
128  l_proj_(0, 0) = left_fx;
129  l_proj_(0, 2) = left_cx;
130  l_proj_(1, 1) = left_fy;
131  l_proj_(1, 2) = left_cy;
132  l_proj_(2, 2) = 1.0;
133 
134  yInfoVerbose("Left projection matrix = [\n" + l_proj_.toString() + "\n]");
135 
136  double right_fx = cam_right_info->get(0).asDouble();
137  double right_cx = cam_right_info->get(2).asDouble();
138  double right_fy = cam_right_info->get(5).asDouble();
139  double right_cy = cam_right_info->get(6).asDouble();
140 
141  yInfoVerbose("[CAM] Right camera intrinsic paramenter:");
142  yInfoVerbose("[CAM] - fx: " + std::to_string(right_fx));
143  yInfoVerbose("[CAM] - fy: " + std::to_string(right_fy));
144  yInfoVerbose("[CAM] - cx: " + std::to_string(right_cx));
145  yInfoVerbose("[CAM] - cy: " + std::to_string(right_cy));
146 
147  r_proj_ = zeros(3, 4);
148  r_proj_(0, 0) = right_fx;
149  r_proj_(0, 2) = right_cx;
150  r_proj_(1, 1) = right_fy;
151  r_proj_(1, 2) = right_cy;
152  r_proj_(2, 2) = 1.0;
153 
154  yInfoVerbose("Right projection matrix = [\n" + r_proj_.toString() + "\n]");
155 
156 
157 
158  port_pose_px_l_.open("/visualservoing/cam_left/ctrl:o");
159  port_pose_px_r_.open("/visualservoing/cam_right/ctrl:o");
160 
161  port_kin_px_l_.open("/visualservoing/cam_left/kin:o");
162  port_kin_px_r_.open("/visualservoing/cam_right/kin:o");
163 
164  port_goal_px_l_.open("/visualservoing/cam_left/goal:o");
165  port_goal_px_r_.open("/visualservoing/cam_right/goal:o");
166 
167  port_pose_avg_.open("/visualservoing/pose/ctrl:o");
168  port_pose_kin_.open("/visualservoing/pose/kin:o");
169  port_pose_goal_.open("/visualservoing/pose/goal:o");
170 
171 
172  if (!setCommandPort())
173  {
174  yErrorVerbose("Could not open /visualservoing/cmd:i port!");
175  return false;
176  }
177 
178 
179  yInfoVerbose("*** VisualServoingServer configured! ***");
180 
181  return true;
182 }
183 
184 
186 {
187  yInfoVerbose("*** Interrupting VisualServoingServer ***");
188 
189  yInfoVerbose("Ensure controllers are stopped...");
190  itf_rightarm_cart_->stopControl();
191  itf_gaze_->stopControl();
192 
193  yInfoVerbose("...interrupting ports.");
194  port_pose_left_in_.interrupt();
195  port_pose_right_in_.interrupt();
196  port_image_left_in_.interrupt();
197  port_image_left_out_.interrupt();
198  port_click_left_.interrupt();
199  port_image_right_in_.interrupt();
200  port_image_right_out_.interrupt();
201  port_click_right_.interrupt();
202 
203  port_pose_px_l_.interrupt();
204  port_pose_px_r_.interrupt();
205  port_kin_px_l_.interrupt();
206  port_kin_px_r_.interrupt();
207  port_goal_px_l_.interrupt();
208  port_goal_px_r_.interrupt();
209  port_pose_avg_.interrupt();
210  port_pose_kin_.interrupt();
211  port_pose_goal_.interrupt();
212 
213  yInfoVerbose("*** Interrupting VisualServoingServer done! ***");
214 
215 
216  yInfoVerbose("*** Closing VisualServoingServer ***");
217 
218  yInfoVerbose("Closing ports...");
219  port_pose_left_in_.close();
220  port_pose_right_in_.close();
221  port_image_left_in_.close();
222  port_image_left_out_.close();
223  port_click_left_.close();
224  port_image_right_in_.close();
225  port_image_right_out_.close();
226  port_click_right_.close();
227 
228  port_pose_px_l_.close();
229  port_pose_px_r_.close();
230  port_kin_px_l_.close();
231  port_kin_px_r_.close();
232  port_goal_px_l_.close();
233  port_goal_px_r_.close();
234  port_pose_avg_.close();
235  port_pose_kin_.close();
236  port_pose_goal_.close();
237 
238  yInfoVerbose("...removing frames...");
239  itf_rightarm_cart_->removeTipFrame();
240 
241  yInfoVerbose("...closing drivers.");
242  if (rightarm_cartesian_driver_.isValid()) rightarm_cartesian_driver_.close();
243  if (gaze_driver_.isValid()) gaze_driver_.close();
244 
245  yInfoVerbose("*** Closing VisualServoingServer done! ***");
246 
247 
248  return true;
249 }
250 
251 
252 /* IVisualServoing overrides */
253 bool VisualServoingServer::initFacilities(const bool use_direct_kin)
254 {
255  if (use_direct_kin)
256  {
257  yInfoVerbose("Connecting to Cartesian controller right arm output state.");
258 
259  if (!Network::connect("/" + robot_name_ + "/cartesianController/right_arm/state:o", port_pose_left_in_.getName(), "tcp", !verbosity_))
260  return false;
261 
262  if (!Network::connect("/" + robot_name_ + "/cartesianController/right_arm/state:o", port_pose_right_in_.getName(), "tcp", !verbosity_))
263  return false;
264 
265  yInfoVerbose("Using direct kinematics information for visual servoing.");
266  }
267  else
268  {
269  yInfoVerbose("Connecting to external pose trackers command ports.");
270 
271  if (!Network::connect(port_rpc_tracker_left_.getName(), "/hand-tracking/left/cmd:i", "tcp", !verbosity_))
272  return false;
273 
274  if (!Network::connect(port_rpc_tracker_right_.getName(), "/hand-tracking/right/cmd:i", "tcp", !verbosity_))
275  return false;
276 
277 
278  yInfoVerbose("Sending commands to external pose trackers.");
279 
280  Bottle cmd;
281  cmd.addString("run_filter");
282 
283  Bottle response_left;
284  if (!port_rpc_tracker_left_.write(cmd, response_left))
285  return false;
286 
287  if (!response_left.get(0).asBool())
288  return false;
289 
290  yInfoVerbose("Left camera external pose tracker running.");
291 
292 
293  Bottle response_right;
294  if (!port_rpc_tracker_right_.write(cmd, response_right))
295  return false;
296 
297  if (!response_right.get(0).asBool())
298  return false;
299 
300  yInfoVerbose("Right camera external pose tracker running.");
301 
302 
303  yInfoVerbose("Using external pose trackers information for visual servoing.");
304 
305 
306  yInfoVerbose("Waiting for the filter to provide good estimates...");
307  yarp::os::Time::delay(10);
308  yInfoVerbose("...done!");
309 
310 
311  yInfoVerbose("Skipping state model propagation and correction to use only known exogenous robot inputs...");
312 
313  cmd.clear();
314  cmd.addString("skip_step");
315  cmd.addString("state");
316  cmd.addInt(1);
317 
318  response_left.clear();
319  if (!port_rpc_tracker_left_.write(cmd, response_left))
320  return false;
321 
322  if (!response_left.get(0).asBool())
323  return false;
324 
325  response_right.clear();
326  if (!port_rpc_tracker_right_.write(cmd, response_right))
327  return false;
328 
329  if (!response_right.get(0).asBool())
330  return false;
331 
332 
333  cmd.clear();
334  cmd.addString("skip_step");
335  cmd.addString("correction");
336  cmd.addInt(1);
337 
338  response_left.clear();
339  if (!port_rpc_tracker_left_.write(cmd, response_left))
340  return false;
341 
342  if (!response_left.get(0).asBool())
343  return false;
344 
345  response_right.clear();
346  if (!port_rpc_tracker_right_.write(cmd, response_right))
347  return false;
348 
349  yInfoVerbose("...done!");
350 
351 
352  yInfoVerbose("Connecting to external pose trackers output ports.");
353 
354  if (!Network::connect("/hand-tracking/left/result/estimates:o", port_pose_left_in_.getName(), "tcp", !verbosity_))
355  return false;
356 
357  if (!Network::connect("/hand-tracking/right/result/estimates:o", port_pose_right_in_.getName(), "tcp", !verbosity_))
358  return false;
359 
360  yInfoVerbose("Receiving end-effector pose from external trackers.");
361  }
362 
363  return true;
364 }
365 
366 
368 {
369  if (port_rpc_tracker_left_.getOutputCount() > 0 && port_rpc_tracker_right_.getOutputCount() > 0)
370  {
371  yInfoVerbose("Sending commands to external pose trackers.");
372 
373  Bottle cmd;
374  cmd.addString("rest_filter");
375 
376  Bottle response_left;
377  if (!port_rpc_tracker_left_.write(cmd, response_left))
378  return false;
379 
380  if (!response_left.get(0).asBool())
381  return false;
382 
383  yInfoVerbose("Left camera external pose tracker reset.");
384 
385 
386  Bottle response_right;
387  if (!port_rpc_tracker_right_.write(cmd, response_right))
388  return false;
389 
390  if (!response_right.get(0).asBool())
391  return false;
392 
393  yInfoVerbose("Right camera external pose tracker reset.");
394 
395  return true;
396  }
397  else
398  return false;
399 }
400 
401 
403 {
404  if (port_rpc_tracker_left_.getOutputCount() > 0 && port_rpc_tracker_right_.getOutputCount() > 0)
405  {
406  yInfoVerbose("Sending commands to external pose trackers.");
407 
408 
409  yInfoVerbose("Disable skipping state model propagation and correction...");
410 
411  Bottle cmd;
412  cmd.addString("skip_step");
413  cmd.addString("correction");
414  cmd.addInt(0);
415 
416  Bottle response_left;
417  if (!port_rpc_tracker_left_.write(cmd, response_left))
418  return false;
419 
420  if (!response_left.get(0).asBool())
421  return false;
422 
423  Bottle response_right;
424  if (!port_rpc_tracker_right_.write(cmd, response_right))
425  return false;
426 
427 
428  cmd.clear();
429  cmd.addString("skip_step");
430  cmd.addString("state");
431  cmd.addInt(0);
432 
433  response_left.clear();
434  if (!port_rpc_tracker_left_.write(cmd, response_left))
435  return false;
436 
437  if (!response_left.get(0).asBool())
438  return false;
439 
440  response_right.clear();
441  if (!port_rpc_tracker_right_.write(cmd, response_right))
442  return false;
443 
444  if (!response_right.get(0).asBool())
445  return false;
446 
447  yInfoVerbose("...done!");
448 
449 
450  cmd.clear();
451  cmd.addString("stop_filter");
452 
453  response_left.clear();
454  if (!port_rpc_tracker_left_.write(cmd, response_left))
455  return false;
456 
457  if (!response_left.get(0).asBool())
458  return false;
459 
460  yInfoVerbose("Left camera external pose tracker stopped.");
461 
462 
463  if (!Network::disconnect(port_rpc_tracker_left_.getName(), "/hand-tracking/left/cmd:i", !verbosity_))
464  return false;
465 
466 
467  response_right.clear();
468  if (!port_rpc_tracker_right_.write(cmd, response_right))
469  return false;
470 
471  if (!response_right.get(0).asBool())
472  return false;
473 
474  yInfoVerbose("Right camera external pose tracker stopped.");
475 
476 
477  if (!Network::disconnect(port_rpc_tracker_right_.getName(), "/hand-tracking/right/cmd:i", !verbosity_))
478  return false;
479 
480 
481  yInfoVerbose("Disconnecting from external pose trackers output ports.");
482 
483  if (!Network::disconnect("/hand-tracking/left/result/estimates:o", port_pose_left_in_.getName(), !verbosity_))
484  return false;
485 
486  if (!Network::disconnect("/hand-tracking/right/result/estimates:o", port_pose_right_in_.getName(), !verbosity_))
487  return false;
488 
489  yInfoVerbose("Disconnected from external trackers.");
490 
491 
492  return true;
493  }
494  else
495  return false;
496 }
497 
498 
499 bool VisualServoingServer::goToGoal(const Vector& vec_x, const Vector& vec_o)
500 {
501  yInfoVerbose("*** VisualServoingServer::goToGoal with pose goal invoked ***");
502 
503  std::vector<Vector> vec_px_l = getGoalPixelsFrom3DPose(vec_x, vec_o, CamSel::left);
504  if (vec_px_l.size() == 0)
505  return false;
506 
507  std::vector<Vector> vec_px_r = getGoalPixelsFrom3DPose(vec_x, vec_o, CamSel::right);
508  if (vec_px_r.size() == 0)
509  return false;
510 
511  setPoseGoal(vec_x, vec_o);
512  setPixelGoal(vec_px_l, vec_px_r);
513 
514  return start();
515 }
516 
517 
518 bool VisualServoingServer::goToGoal(const std::vector<Vector>& vec_px_l, const std::vector<Vector>& vec_px_r)
519 {
520  yInfoVerbose("*** VisualServoingServer::goToGoal with pixel goal invoked ***");
521 
522  yWarningVerbose("<!-- If you did not invoke either one of:");
523  yWarningVerbose("<!-- 1. get3DPositionGoalFrom3DPose()");
524  yWarningVerbose("<!-- 2. getGoalPixelsFrom3DPose");
525  yWarningVerbose("<!-- visual servoing will just not work, and the server may also close.");
526  yWarningVerbose("<!-- To the current implementation, this behaviour is intentional.");
527  yWarningVerbose("<!-- Upcoming releases will change the behaviour of this method.");
528 
529  setPixelGoal(vec_px_l, vec_px_r);
530 
531  return start();
532 }
533 
534 
535 bool VisualServoingServer::setModality(const std::string& mode)
536 {
537  if (mode == "position")
538  op_mode_ = OperatingMode::position;
539  else if (mode == "orientation")
540  op_mode_ = OperatingMode::orientation;
541  else if (mode == "pose")
542  op_mode_ = OperatingMode::pose;
543  else
544  return false;
545 
546  return true;
547 }
548 
549 
550 bool VisualServoingServer::setVisualServoControl(const std::string& control)
551 {
552  if (control == "decoupled")
553  vs_control_ = VisualServoControl::decoupled;
554  else if (control == "robust")
555  vs_control_ = VisualServoControl::robust;
556  else if (control == "cartesian")
557  vs_control_ = VisualServoControl::cartesian;
558  else
559  return false;
560 
561  return true;
562 }
563 
564 
565 bool VisualServoingServer::setControlPoint(const yarp::os::ConstString& point)
566 {
567  yWarningVerbose("*** Service setControlPoint is unimplemented. ***");
568 
569  return false;
570 }
571 
572 
574 {
575  yWarningVerbose("*** Service getVisualServoingInfo is unimplemented. ***");
576 
577  return false;
578 }
579 
580 
582 {
583  tol_px_ = tol;
584 
585  return true;
586 }
587 
588 
590 {
591  yInfoVerbose("");
592  yInfoVerbose("*** Checking visual servoing controller ***");
593  yInfoVerbose(" |> Controller: " + ConstString(vs_control_running_ ? "running." : "idle."));
594  yInfoVerbose(" |> Goal: " + ConstString(vs_goal_reached_ ? "" : "not ") + "reached.");
595  yInfoVerbose("");
596 
597  return vs_control_running_;
598 }
599 
600 
601 bool VisualServoingServer::waitVisualServoingDone(const double period, const double timeout)
602 {
603  yInfoVerbose("");
604  yInfoVerbose("*** Joining visual servoing control thread ***");
605  yInfoVerbose(" |> Controller: " + ConstString(vs_control_running_ ? "running." : "idle."));
606  yInfoVerbose(" |> Goal: " + ConstString(vs_goal_reached_ ? "" : "not ") + "reached.");
607  yInfoVerbose("");
608 
609  return join();
610 }
611 
612 
614 {
615  yInfoVerbose("");
616  yInfoVerbose("*** Stopping visual servoing controller ***");
617  yInfoVerbose(" |> Controller: " + ConstString(vs_control_running_ ? "running." : "idle."));
618  yInfoVerbose(" |> Goal: " + ConstString(vs_goal_reached_ ? "" : "not ") + "reached.");
619  yInfoVerbose("");
620 
621  return stop();
622 }
623 
624 
625 bool VisualServoingServer::setTranslationGain(const double K_x_1, const double K_x_2)
626 {
627  K_x_[0] = K_x_1;
628  K_x_[1] = K_x_2;
629 
630  return true;
631 }
632 
633 
635 {
636  max_x_dot_ = max_x_dot;
637 
638  return true;
639 }
640 
641 
643 {
644  K_x_tol_ = K_x_tol;
645 
646  return true;
647 }
648 
649 
650 bool VisualServoingServer::setOrientationGain(const double K_o_1, const double K_o_2)
651 {
652  K_o_[0] = K_o_1;
653  K_o_[1] = K_o_2;
654 
655  return true;
656 }
657 
658 
660 {
661  max_o_dot_ = max_o_dot;
662 
663  return true;
664 }
665 
666 
668 {
669  K_o_tol_ = K_o_tol;
670 
671  return true;
672 }
673 
674 
675 std::vector<Vector> VisualServoingServer::get3DGoalPositionsFrom3DPose(const Vector& x, const Vector& o)
676 {
677  if (x.length() != 3 || o.length() != 4)
678  return std::vector<Vector>();
679 
680 
681  Vector pose(7);
682  pose.setSubvector(0, x);
683  pose.setSubvector(3, o);
684 
685  yWarningVerbose("<!-- Invoking setPoseGoal() to set the goal pose for visual servoing.");
686  yWarningVerbose("<!-- Be warned that this specific invokation will be removed in upcoming releases.");
687  setPoseGoal(x, o);
688 
689  std::vector<Vector> vec_goal_points = getControlPointsFromPose(pose);
690 
691  return vec_goal_points;
692 }
693 
694 
695 std::vector<Vector> VisualServoingServer::getGoalPixelsFrom3DPose(const Vector& x, const Vector& o, const CamSel& cam)
696 {
697  if (x.length() != 3 || o.length() != 4)
698  return std::vector<Vector>();
699 
700 
701  Vector pose(7);
702  pose.setSubvector(0, x);
703  pose.setSubvector(3, o);
704 
705 // yWarningVerbose("<!-- Invoking setPoseGoal() to set the goal pose for visual servoing.");
706 // yWarningVerbose("<!-- Be warned that this specific invokation will be removed in upcoming releases.");
707  setPoseGoal(x, o);
708 
709  setCameraTransformations();
710 
711  std::vector<Vector> vec_goal_points = getPixelsFromPose(pose, cam);
712 
713  return vec_goal_points;
714 }
715 
716 
717 /* VisualServoingServerIDL overrides */
718 bool VisualServoingServer::storedInit(const std::string& label)
719 {
720  itf_rightarm_cart_->storeContext(&ctx_remote_cart_);
721  itf_rightarm_cart_->restoreContext(ctx_local_cart_);
722 
723  Vector xd = zeros(3);
724  Vector od = zeros(4);
725  Vector gaze_loc = zeros(3);
726 
727  if (label == "t170427")
728  {
729  /* -0.346 0.133 0.162 0.140 -0.989 0.026 2.693 */
730  xd[0] = -0.346;
731  xd[1] = 0.133;
732  xd[2] = 0.162;
733 
734  od[0] = 0.140;
735  od[1] = -0.989;
736  od[2] = 0.026;
737  od[3] = 2.693;
738 
739  /* -6.706 1.394 -3.618 */
740  gaze_loc[0] = -6.706;
741  gaze_loc[1] = 1.394;
742  gaze_loc[2] = -3.618;
743  }
744  else if (label == "t170517")
745  {
746  /* -0.300 0.088 0.080 -0.245 0.845 -0.473 2.896 */
747  xd[0] = -0.300;
748  xd[1] = 0.088;
749  xd[2] = 0.080;
750 
751  od[0] = -0.245;
752  od[1] = 0.845;
753  od[2] = -0.473;
754  od[3] = 2.896;
755 
756  /* -5.938 1.385 -4.724 */
757  gaze_loc[0] = -5.938;
758  gaze_loc[1] = 1.385;
759  gaze_loc[2] = -4.724;
760  }
761  else if (label == "t170713")
762  {
763  /* -0.288 0.15 0.118 0.131 -0.492 0.86 2.962 */
764  xd[0] = -0.288;
765  xd[1] = 0.15;
766  xd[2] = 0.118;
767 
768  od[0] = 0.131;
769  od[1] = -0.492;
770  od[2] = 0.86;
771  od[3] = 2.962;
772 
773  /* -5.938 1.385 -4.724 */
774  gaze_loc[0] = -5.938;
775  gaze_loc[1] = 1.385;
776  gaze_loc[2] = -4.724;
777  }
778  else if (label == "t170904")
779  {
780  /* -0.286 0.115 0.13 -0.26 0.479 -0.838 3.137 */
781  xd[0] = -0.286;
782  xd[1] = 0.115;
783  xd[2] = 0.13;
784 
785  od[0] = -0.26;
786  od[1] = 0.479;
787  od[2] = -0.838;
788  od[3] = 3.137;
789 
790  /* -5.938 1.385 -4.724 */
791  gaze_loc[0] = -5.938;
792  gaze_loc[1] = 1.385;
793  gaze_loc[2] = -4.724;
794  }
795  else if (label == "sfm300517")
796  {
797  /* -0.333 0.203 -0.053 0.094 0.937 -0.335 3.111 */
798  xd[0] = -0.333;
799  xd[1] = 0.203;
800  xd[2] = -0.053;
801 
802  od[0] = 0.094;
803  od[1] = 0.937;
804  od[2] = -0.335;
805  od[3] = 3.111;
806 
807  /* -0.589 0.252 -0.409 */
808  gaze_loc[0] = -0.589;
809  gaze_loc[1] = 0.252;
810  gaze_loc[2] = -0.409;
811 
812  itf_rightarm_cart_->setLimits(0, 25.0, 25.0);
813  }
814  else
815  return false;
816 
817  yInfoVerbose("Init position: " + xd.toString());
818  yInfoVerbose("Init orientation: " + od.toString());
819 
820 
821  unsetTorsoDOF();
822 
823  itf_rightarm_cart_->goToPoseSync(xd, od);
824  itf_rightarm_cart_->waitMotionDone(0.1, 10.0);
825  itf_rightarm_cart_->stopControl();
826 
827  itf_rightarm_cart_->removeTipFrame();
828 
829  setTorsoDOF();
830 
831 
832  yInfoVerbose("Fixation point: " + gaze_loc.toString());
833 
834  itf_gaze_->lookAtFixationPointSync(gaze_loc);
835  itf_gaze_->waitMotionDone(0.1, 10.0);
836  itf_gaze_->stopControl();
837 
838 
839  itf_rightarm_cart_->restoreContext(ctx_remote_cart_);
840 
841  return true;
842 }
843 
844 
845 /* Set a fixed goal in pixel coordinates */
846 bool VisualServoingServer::storedGoToGoal(const std::string& label)
847 {
848  if (label == "t170427")
849  {
850  /* -0.323 0.018 0.121 0.310 -0.873 0.374 3.008 */
851  goal_pose_[0] = -0.323;
852  goal_pose_[1] = 0.018;
853  goal_pose_[2] = 0.121;
854 
855  goal_pose_[3] = 0.310;
856  goal_pose_[4] = -0.873;
857  goal_pose_[5] = 0.374;
858  goal_pose_[6] = 3.008;
859  }
860  else if (label == "t170517")
861  {
862  /* -0.284 0.013 0.104 -0.370 0.799 -0.471 2.781 */
863  goal_pose_[0] = -0.284;
864  goal_pose_[1] = 0.013;
865  goal_pose_[2] = 0.104;
866 
867  goal_pose_[3] = -0.370;
868  goal_pose_[4] = 0.799;
869  goal_pose_[5] = -0.471;
870  goal_pose_[6] = 2.781;
871  }
872  else if (label == "t170711")
873  {
874  /* -0.356 0.024 -0.053 0.057 0.98 -0.189 2.525 */
875  goal_pose_[0] = -0.356;
876  goal_pose_[1] = 0.024;
877  goal_pose_[2] = -0.053;
878 
879  goal_pose_[3] = 0.057;
880  goal_pose_[4] = 0.980;
881  goal_pose_[5] = -0.189;
882  goal_pose_[6] = 2.525;
883  }
884  else if (label == "t170713")
885  {
886  /* -0.282 0.061 0.068 0.213 -0.94 0.265 2.911 */
887  goal_pose_[0] = -0.282;
888  goal_pose_[1] = 0.061;
889  goal_pose_[2] = 0.068;
890 
891  goal_pose_[3] = 0.213;
892  goal_pose_[4] = -0.94 ;
893  goal_pose_[5] = 0.265;
894  goal_pose_[6] = 2.911;
895  }
896  else if (label == "t170904")
897  {
898  /* -0.288 0.085 0.025 0.166 -0.98 0.101 3.031 */
899  goal_pose_[0] = -0.288;
900  goal_pose_[1] = 0.085;
901  goal_pose_[2] = 0.025;
902 
903  goal_pose_[3] = 0.166;
904  goal_pose_[4] = -0.98;
905  goal_pose_[5] = 0.101;
906  goal_pose_[6] = 3.031;
907  }
908  else
909  return false;
910 
911  yInfoVerbose("6D goal: " + goal_pose_.toString());
912 
913  setCameraTransformations();
914 
915  std::vector<Vector> l_px_from_pose = getPixelsFromPose(goal_pose_, CamSel::left);
916  std::vector<Vector> r_px_from_pose = getPixelsFromPose(goal_pose_, CamSel::right);
917 
918  setPixelGoal(l_px_from_pose, r_px_from_pose);
919 
920  return start();
921 }
922 
923 
924 /* Get 3D point from Structure From Motion clicking on the left camera image */
926 {
927  Bottle cmd;
928  Bottle rep;
929 
930  Bottle* click_left = port_click_left_.read(true);
931  Vector l_click = zeros(2);
932  l_click[0] = click_left->get(0).asDouble();
933  l_click[1] = click_left->get(1).asDouble();
934 
935  RpcClient port_sfm;
936  port_sfm.open("/visualservoing/tosfm");
937  Network::connect("/visualservoing/tosfm", "/SFM/rpc");
938 
939  cmd.clear();
940 
941  cmd.addInt(l_click[0]);
942  cmd.addInt(l_click[1]);
943 
944  Bottle reply_pos;
945  port_sfm.write(cmd, reply_pos);
946  if (reply_pos.size() == 5)
947  {
948  Matrix R_ee = zeros(3, 3);
949  R_ee(0, 0) = -1.0;
950 // R_ee(1, 1) = 1.0;
951  R_ee(1, 2) = -1.0;
952 // R_ee(2, 2) = -1.0;
953  R_ee(2, 1) = -1.0;
954  Vector ee_o = dcm2axis(R_ee);
955 
956  Vector sfm_pos = zeros(3);
957  sfm_pos[0] = reply_pos.get(0).asDouble();
958  sfm_pos[1] = reply_pos.get(1).asDouble();
959  sfm_pos[2] = reply_pos.get(2).asDouble();
960 
961  Vector p = zeros(7);
962  p.setSubvector(0, sfm_pos.subVector(0, 2));
963  p.setSubvector(3, ee_o.subVector(0, 3));
964 
965  goal_pose_ = p;
966  yInfoVerbose("6D goal: " + goal_pose_.toString());
967 
968  setCameraTransformations();
969 
970  std::vector<Vector> l_px_from_pose = getPixelsFromPose(goal_pose_, CamSel::left);
971  std::vector<Vector> r_px_from_pose = getPixelsFromPose(goal_pose_, CamSel::right);
972 
973  setPixelGoal(l_px_from_pose, r_px_from_pose);
974  }
975  else
976  return false;
977 
978  Network::disconnect("/visualservoing/tosfm", "/SFM/rpc");
979  port_sfm.close();
980 
981  return start();
982 }
983 
984 
985 /* Thread overrides */
987 {
988  yInfoVerbose("*** Thread::beforeStart invoked ***");
989 }
990 
991 
993 {
994  yInfoVerbose("*** Thread::threadInit invoked ***");
995 
996 
997  /* SETTING STATUS */
998  vs_control_running_ = true;
999  vs_goal_reached_ = false;
1000 
1001 
1002  /* RESTORING CARTESIAN AND GAZE CONTEXT */
1003  itf_rightarm_cart_->storeContext(&ctx_remote_cart_);
1004  itf_rightarm_cart_->restoreContext(ctx_local_cart_);
1005 
1006 
1007  /* SETTING BACKGROUND THREAD */
1008  yInfoVerbose("*** Launching background process UpdateVisualServoingParamters ***");
1009  is_stopping_backproc_update_vs_params = false;
1010  thr_background_update_params_ = new std::thread(&VisualServoingServer::backproc_UpdateVisualServoingParamters, this);
1011 
1012 
1013  yInfoVerbose("");
1014  yInfoVerbose("*** Running visual servoing! ***");
1015  yInfoVerbose("");
1016 
1017  return true;
1018 }
1019 
1020 
1022 {
1023  if (vs_control_ == VisualServoControl::decoupled)
1024  decoupledImageBasedVisualServoControl();
1025  else if (vs_control_ == VisualServoControl::robust)
1026  robustImageBasedVisualServoControl();
1027  else if (vs_control_ == VisualServoControl::cartesian)
1028  cartesianPositionBasedVisualServoControl();
1029 }
1030 
1031 
1033 {
1034  yInfoVerbose("*** Thread::afterStart invoked ***");
1035 
1036  if (success)
1037  {
1038  yInfoVerbose("Visual servoing controller status report:");
1039  yInfoVerbose(" |> Controller: " + ConstString(vs_control_running_ ? "running." : "idle."));
1040  yInfoVerbose(" |> Goal: " + ConstString(vs_goal_reached_ ? "" : "not") + "reached.");
1041  }
1042  else
1043  {
1044  yInfoVerbose("Visual servoing controller failed to start!");
1045  vs_control_running_ = false;
1046  vs_goal_reached_ = false;
1047  }
1048 }
1049 
1050 
1052 {
1053  yInfoVerbose("*** Thread::onStop invoked ***");
1054 }
1055 
1056 
1058 {
1059  yInfoVerbose("*** Thread::threadRelease invoked ***");
1060 
1061 
1062  /* ENSURE CONTROLLERS ARE STOPPED */
1063  itf_rightarm_cart_->stopControl();
1064  itf_gaze_->stopControl();
1065 
1066 
1067  /* STOPPING AND JOINING BACKGROUND THREAD */
1068  yInfoVerbose("*** Stopping background process UpdateVisualServoingParamters ***");
1069  is_stopping_backproc_update_vs_params = true;
1070  thr_background_update_params_->join();
1071  delete thr_background_update_params_;
1072 
1073 
1074  /* RESTORING REMOTE CARTESIAN AND GAZE CONTEXTS */
1075  itf_rightarm_cart_->restoreContext(ctx_remote_cart_);
1076 
1077 
1078  vs_control_running_ = false;
1079 
1080  yInfoVerbose("");
1081  yInfoVerbose("*** Visual servoing terminated! ***");
1082  yInfoVerbose("");
1083 }
1084 
1085 
1086 /* VisualServoingServerIDL overrides */
1087 bool VisualServoingServer::stored_init(const std::string& label)
1088 {
1089  return storedInit(label);
1090 }
1091 
1092 
1093 bool VisualServoingServer::stored_go_to_goal(const std::string& label)
1094 {
1095  return storedGoToGoal(label);
1096 }
1097 
1098 
1100 {
1101  return goToSFMGoal();
1102 }
1103 
1104 
1106 {
1107  yInfoVerbose("*** Quitting visual servoing server ***");
1108 
1109  bool is_stopping_controller = stopController();
1110  if (!is_stopping_controller)
1111  {
1112  yWarningVerbose("Could not stop visual servoing controller!");
1113  return false;
1114  }
1115 
1116  bool is_closing = close();
1117  if (!is_closing)
1118  {
1119  yWarningVerbose("Could not close visual servoing server!");
1120  return false;
1121  }
1122 
1123  return true;
1124 }
1125 
1126 
1127 bool VisualServoingServer::init_facilities(const bool use_direct_kin)
1128 {
1129  return initFacilities(use_direct_kin);
1130 }
1131 
1132 
1134 {
1135  return resetFacilities();
1136 }
1137 
1138 
1140 {
1141  return stopFacilities();
1142 }
1143 
1144 
1145 bool VisualServoingServer::go_to_px_goal(const std::vector<std::vector<double>>& vec_px_l, const std::vector<std::vector<double>>& vec_px_r)
1146 {
1147  if (vec_px_l.size() != 4 || vec_px_l.size() != 4)
1148  return false;
1149 
1150  std::vector<Vector> yvec_px_l;
1151  for (const std::vector<double>& vec : vec_px_l)
1152  {
1153  if (vec.size() != 2)
1154  return false;
1155 
1156  yvec_px_l.emplace_back(Vector(vec.size(), vec.data()));
1157  }
1158 
1159  std::vector<Vector> yvec_px_r;
1160  for (const std::vector<double>& vec : vec_px_r)
1161  {
1162  if (vec.size() != 2)
1163  return false;
1164 
1165  yvec_px_r.emplace_back(Vector(vec.size(), vec.data()));
1166  }
1167 
1168  return goToGoal(yvec_px_l, yvec_px_r);
1169 }
1170 
1171 
1172 bool VisualServoingServer::go_to_pose_goal(const std::vector<double>& vec_x, const std::vector<double>& vec_o)
1173 {
1174  if (vec_x.size() != 3 || vec_o.size() != 4)
1175  return false;
1176 
1177  Vector yvec_x(vec_x.size(), vec_x.data());
1178  Vector yvec_o(vec_o.size(), vec_o.data());
1179 
1180  return goToGoal(yvec_x, yvec_o);
1181 }
1182 
1183 
1184 bool VisualServoingServer::set_modality(const std::string& mode)
1185 {
1186  return setModality(mode);
1187 }
1188 
1189 
1190 bool VisualServoingServer::set_visual_servo_control(const std::string& control)
1191 {
1192  return setVisualServoControl(control);
1193 }
1194 
1195 
1196 bool VisualServoingServer::set_control_point(const std::string& point)
1197 {
1198  return setControlPoint(point);
1199 }
1200 
1201 
1203 {
1204  Bottle info;
1205  getVisualServoingInfo(info);
1206 
1207  std::vector<std::string> info_str;
1208  info_str.emplace_back(info.toString());
1209 
1210  return info_str;
1211 }
1212 
1213 
1215 {
1216  return setGoToGoalTolerance(tol);
1217 }
1218 
1219 
1221 {
1222  return checkVisualServoingController();
1223 }
1224 
1225 
1226 bool VisualServoingServer::wait_visual_servoing_done(const double period, const double timeout)
1227 {
1228  return waitVisualServoingDone(period, timeout);
1229 }
1230 
1231 
1233 {
1234  return stopController();
1235 }
1236 
1237 
1238 bool VisualServoingServer::set_translation_gain(const double K_x_1, const double K_x_2)
1239 {
1240  return setTranslationGain(K_x_1, K_x_2);
1241 }
1242 
1243 
1245 {
1246  return setMaxTranslationVelocity(max_x_dot);
1247 }
1248 
1249 
1251 {
1252  return setTranslationGainSwitchTolerance(K_x_tol);
1253 }
1254 
1255 
1256 bool VisualServoingServer::set_orientation_gain(const double K_o_1, const double K_o_2)
1257 {
1258  return setOrientationGain(K_o_1, K_o_2);
1259 }
1260 
1261 
1263 {
1264  return setMaxOrientationVelocity(max_o_dot);
1265 }
1266 
1267 
1269 {
1270  return setOrientationGainSwitchTolerance(K_o_tol);
1271 }
1272 
1273 
1274 std::vector<std::vector<double>> VisualServoingServer::get_3D_goal_positions_from_3D_pose(const std::vector<double>& x, const std::vector<double>& o)
1275 {
1276  if (x.size() != 3 || o.size() != 4)
1277  return std::vector<std::vector<double>>();
1278 
1279 
1280  Vector yx(x.size(), x.data());
1281  Vector yo(o.size(), o.data());
1282  std::vector<Vector> yvec_3d_goal_points = get3DGoalPositionsFrom3DPose(yx, yo);
1283 
1284  std::vector<std::vector<double>> vec_3d_goal_points;
1285  for (const Vector& yvec_3d_goal : yvec_3d_goal_points)
1286  vec_3d_goal_points.emplace_back(std::vector<double>(yvec_3d_goal.data(), yvec_3d_goal.data() + yvec_3d_goal.size()));
1287 
1288  return vec_3d_goal_points;
1289 }
1290 
1291 
1292 std::vector<std::vector<double>> VisualServoingServer::get_goal_pixels_from_3D_pose(const std::vector<double>& x, const std::vector<double>& o, const std::string& cam)
1293 {
1294  if (x.size() != 3 || o.size() != 4 || (cam != "left" && cam != "right"))
1295  return std::vector<std::vector<double>>();
1296 
1297 
1298  Vector yx(x.size(), x.data());
1299  Vector yo(o.size(), o.data());
1300  CamSel e_cam = cam == "left" ? CamSel::left : CamSel::right;
1301 
1302  std::vector<Vector> yvec_px_goal_points = getGoalPixelsFrom3DPose(yx, yo, e_cam);
1303  if (yvec_px_goal_points.size() == 0)
1304  return std::vector<std::vector<double>>();
1305 
1306  std::vector<std::vector<double>> vec_px_goal_points;
1307  for (const Vector& yvec_px_goal : yvec_px_goal_points)
1308  vec_px_goal_points.emplace_back(std::vector<double>(yvec_px_goal.data(), yvec_px_goal.data() + yvec_px_goal.size()));
1309 
1310  return vec_px_goal_points;
1311 }
1312 
1313 
1314 /* Private class methods */
1316 {
1317  /* VARIABLE DEFINITIONS */
1318  Vector* endeffector_pose;
1319  Vector eepose_copy_left(7);
1320  Vector eepose_copy_right(7);
1321  Vector eepose_averaged(7);
1322 
1323  std::vector<Vector> l_px_position;
1324  std::vector<Vector> l_px_orientation;
1325 
1326  std::vector<Vector> r_px_position;
1327  std::vector<Vector> r_px_orientation;
1328 
1329  Vector px_ee_cur_position = zeros(16);
1330  Matrix jacobian_position = zeros(16, 6);
1331  Vector px_ee_cur_orientation = zeros(16);
1332  Matrix jacobian_orientation = zeros(16, 6);
1333 
1334 
1335  /* GET THE INITIAL END-EFFECTOR POSE FOR THE LEFT EYE */
1336  endeffector_pose = port_pose_left_in_.read(true);
1337  eepose_copy_left = *endeffector_pose;
1338 
1339  yInfoVerbose("Got [" + eepose_copy_left.toString() + "] end-effector pose for the left eye.");
1340 
1341  /* GET THE INITIAL END-EFFECTOR POSE FOR THE RIGHT EYE */
1342  endeffector_pose = port_pose_right_in_.read(true);
1343  eepose_copy_right = *endeffector_pose;
1344 
1345  yInfoVerbose("Got [" + eepose_copy_right.toString() + "] end-effector pose for the right eye.");
1346 
1347  /* GET THE INITIAL END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
1348  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
1349  eepose_copy_left = eepose_averaged;
1350  eepose_copy_right = eepose_averaged;
1351 
1352  yInfoVerbose("Got [" + eepose_averaged.toString() + "] averaged end-effector pose.");
1353 
1354 
1355  while (!isStopping() && !vs_goal_reached_)
1356  {
1357  yInfoVerbose("Desired goal pixels = [" + px_des_.toString() + "]");
1358 
1359 
1360  /* EVALUATING CONTROL POINTS */
1361  l_px_position = getControlPixelsFromPose(eepose_copy_left, CamSel::left, PixelControlMode::x);
1362  l_px_orientation = getControlPixelsFromPose(eepose_copy_left, CamSel::left, PixelControlMode::o);
1363 
1364  r_px_position = getControlPixelsFromPose(eepose_copy_right, CamSel::right, PixelControlMode::x);
1365  r_px_orientation = getControlPixelsFromPose(eepose_copy_right, CamSel::right, PixelControlMode::o);
1366 
1367 
1368  /* POSITION: FEATURES AND JACOBIAN */
1369  getCurrentStereoFeaturesAndJacobian(l_px_position, r_px_position,
1370  px_ee_cur_position, jacobian_position);
1371 
1372  yInfoVerbose("Position controlled pixels = [" + px_ee_cur_position.toString() + "]");
1373  yInfoVerbose("Position image Jacobian = [\n" + jacobian_position.toString() + "]");
1374 
1375 
1376  /* ORIENTATION: FEATURES AND JACOBIAN */
1377  getCurrentStereoFeaturesAndJacobian(l_px_orientation, r_px_orientation,
1378  px_ee_cur_orientation, jacobian_orientation);
1379 
1380  yInfoVerbose("Orientation controlled pixels = [" + px_ee_cur_orientation.toString() + "]");
1381  yInfoVerbose("Orientation image Jacobian = [\n" + jacobian_orientation.toString() + "]");
1382 
1383 
1384  /* *** *** *** DEBUG OUTPUT - TO BE DELETED *** *** *** */
1385  std::vector<cv::Scalar> color;
1386  color.emplace_back(cv::Scalar(255, 0, 0));
1387  color.emplace_back(cv::Scalar( 0, 255, 0));
1388  color.emplace_back(cv::Scalar( 0, 0, 255));
1389  color.emplace_back(cv::Scalar(255, 127, 51));
1390 
1391 
1392  /* Left eye end-effector superimposition */
1393  ImageOf<PixelRgb>* l_imgin = port_image_left_in_.read(true);
1394  ImageOf<PixelRgb>& l_imgout = port_image_left_out_.prepare();
1395  l_imgout = *l_imgin;
1396  cv::Mat l_img = cv::cvarrToMat(l_imgout.getIplImage());
1397 
1398  /* Right eye end-effector superimposition */
1399  ImageOf<PixelRgb>* r_imgin = port_image_right_in_.read(true);
1400  ImageOf<PixelRgb>& r_imgout = port_image_right_out_.prepare();
1401  r_imgout = *r_imgin;
1402  cv::Mat r_img = cv::cvarrToMat(r_imgout.getIplImage());
1403 
1404 
1405  /* Plot points and lines */
1406  std::vector<Vector> l_px_pose = getPixelsFromPose(eepose_copy_left, CamSel::left);
1407  std::vector<Vector> r_px_pose = getPixelsFromPose(eepose_copy_right, CamSel::right);
1408 
1409  for (int i = 0; i < l_px_pose.size(); ++i)
1410  {
1411  const Vector& l_cur_px_p = l_px_pose[i];
1412  const Vector& l_pre_px_p = l_px_pose[(3 + i) % 4];
1413 
1414  const Vector& r_cur_px_p = r_px_pose[i];
1415  const Vector& r_pre_px_p = r_px_pose[(3 + i) % 4];
1416 
1417  const Vector& l_cur_px_g = l_px_goal_[i];
1418  const Vector& l_pre_px_g = l_px_goal_[(3 + i) % 4];
1419 
1420  const Vector& r_cur_px_g = r_px_goal_[i];
1421  const Vector& r_pre_px_g = r_px_goal_[(3 + i) % 4];
1422 
1423 
1424  cv::line(l_img, cv::Point(l_pre_px_p[0], l_pre_px_p[1]), cv::Point(l_cur_px_p[0], l_cur_px_p[1]), color[3], 4, cv::LineTypes::LINE_AA);
1425  cv::line(r_img, cv::Point(r_pre_px_p[0], r_pre_px_p[1]), cv::Point(r_cur_px_p[0], r_cur_px_p[1]), color[3], 4, cv::LineTypes::LINE_AA);
1426 
1427  cv::line(l_img, cv::Point(l_pre_px_g[0], l_pre_px_g[1]), cv::Point(l_cur_px_g[0], l_cur_px_g[1]), color[3], 4, cv::LineTypes::LINE_AA);
1428  cv::line(r_img, cv::Point(r_pre_px_g[0], r_pre_px_g[1]), cv::Point(r_cur_px_g[0], r_cur_px_g[1]), color[3], 4, cv::LineTypes::LINE_AA);
1429 
1430  if (i == 2 || i == 3)
1431  {
1432  cv::circle(l_img, cv::Point(l_cur_px_p[0], l_cur_px_p[1]), 4, color[i - 1], 4);
1433  cv::circle(r_img, cv::Point(r_cur_px_p[0], r_cur_px_p[1]), 4, color[i - 1], 4);
1434 
1435  cv::circle(l_img, cv::Point(l_cur_px_g[0], l_cur_px_g[1]), 4, color[i - 1], 4);
1436  cv::circle(r_img, cv::Point(r_cur_px_g[0], r_cur_px_g[1]), 4, color[i - 1], 4);
1437  }
1438  }
1439 
1440 
1441  Vector l_cur_px_ee = getPixelFromPoint(CamSel::left, cat(eepose_copy_left.subVector(0, 2), 1.0));
1442  Vector r_cur_px_ee = getPixelFromPoint(CamSel::right, cat(eepose_copy_right.subVector(0, 2), 1.0));
1443 
1444  cv::circle(l_img, cv::Point(l_cur_px_ee[0], l_cur_px_ee[1]), 4, color[0], 4);
1445  cv::circle(r_img, cv::Point(r_cur_px_ee[0], r_cur_px_ee[1]), 4, color[0], 4);
1446 
1447 
1448  Vector l_cur_px_g = getPixelFromPoint(CamSel::left, cat(goal_pose_.subVector(0, 2), 1.0));
1449  Vector r_cur_px_g = getPixelFromPoint(CamSel::right, cat(goal_pose_.subVector(0, 2), 1.0));
1450 
1451  cv::circle(l_img, cv::Point(l_cur_px_g[0], l_cur_px_g[1]), 4, color[0], 4);
1452  cv::circle(r_img, cv::Point(r_cur_px_g[0], r_cur_px_g[1]), 4, color[0], 4);
1453 
1454  port_image_left_out_.write();
1455  port_image_right_out_.write();
1456  /* *** *** *** *** *** *** *** *** *** *** *** *** *** */
1457 
1458 
1459  /* *** *** *** LOG - TO BE DELETED *** *** *** */
1460 
1461  Vector& pose_px_l = port_pose_px_l_.prepare();
1462  pose_px_l = stdVectorOfVectorsToVector(getControlPixelsFromPose(eepose_copy_left, CamSel::left, PixelControlMode::all));
1463  port_pose_px_l_.write();
1464 
1465  Vector& pose_px_r = port_pose_px_r_.prepare();
1466  pose_px_r = stdVectorOfVectorsToVector(getControlPixelsFromPose(eepose_copy_right, CamSel::right, PixelControlMode::all));
1467  port_pose_px_r_.write();
1468 
1469  Vector kin_x;
1470  Vector kin_o;
1471  itf_rightarm_cart_->getPose(kin_x, kin_o);
1472 
1473  Vector& pose_kin_px_l = port_kin_px_l_.prepare();
1474  pose_kin_px_l = stdVectorOfVectorsToVector(getControlPixelsFromPose(cat(kin_x, kin_o), CamSel::left, PixelControlMode::all));
1475  port_kin_px_l_.write();
1476 
1477  Vector& pose_kin_px_r = port_kin_px_r_.prepare();
1478  pose_kin_px_r = stdVectorOfVectorsToVector(getControlPixelsFromPose(cat(kin_x, kin_o), CamSel::right, PixelControlMode::all));
1479  port_kin_px_r_.write();
1480 
1481  Vector& goal_px_l_ = port_goal_px_l_.prepare();
1482  goal_px_l_ = stdVectorOfVectorsToVector(l_px_goal_);
1483  port_goal_px_l_.write();
1484 
1485  Vector& goal_px_r_ = port_goal_px_r_.prepare();
1486  goal_px_r_ = stdVectorOfVectorsToVector(r_px_goal_);
1487  port_goal_px_r_.write();
1488 
1489  Vector& pose_avg_ = port_pose_avg_.prepare();
1490  pose_avg_ = eepose_averaged;
1491  port_pose_avg_.write();
1492 
1493  Vector& pose_kin_ = port_pose_kin_.prepare();
1494  pose_kin_ = cat(kin_x, kin_o);
1495  port_pose_kin_.write();
1496 
1497  Vector& pose_goal_ = port_pose_goal_.prepare();
1498  pose_goal_ = goal_pose_;
1499  port_pose_goal_.write();
1500 
1501  /* *** *** *** *** *** *** *** *** *** *** *** */
1502 
1503 
1504  /* CHECK FOR GOAL */
1505  mtx_px_des_.lock();
1506 
1507  bool is_pos_done = checkVisualServoingStatus(px_ee_cur_position, tol_px_);
1508  bool is_orient_done = checkVisualServoingStatus(px_ee_cur_orientation, tol_px_);
1509 
1510  mtx_px_des_.unlock();
1511 
1512 
1513  if (op_mode_ == OperatingMode::position)
1514  vs_goal_reached_ = is_pos_done;
1515  else if (op_mode_ == OperatingMode::orientation)
1516  vs_goal_reached_ = is_orient_done;
1517  else if (op_mode_ == OperatingMode::pose)
1518  vs_goal_reached_ = is_pos_done && is_orient_done;
1519 
1520 
1521  if (vs_goal_reached_)
1522  {
1523  yInfoVerbose("");
1524  yInfoVerbose("*** Goal reached! ***");
1525  yInfoVerbose("Desired goal pixels = " + px_des_.toString());
1526  yInfoVerbose("Current position controlled pixels = " + px_ee_cur_position.toString());
1527  yInfoVerbose("Current orientation controlled pixels = " + px_ee_cur_orientation.toString());
1528  yInfoVerbose("*** ------------- ***");
1529  yInfoVerbose("");
1530  }
1531  else
1532  {
1533  /* EVALUATING ERRORS */
1534  mtx_px_des_.lock();
1535 
1536  Vector e_position = px_des_ - px_ee_cur_position;
1537  Matrix inv_jacobian_position = pinv(jacobian_position);
1538 
1539  Vector e_orientation = px_des_ - px_ee_cur_orientation;
1540  Matrix inv_jacobian_orientation = pinv(jacobian_orientation);
1541 
1542  yInfoVerbose("Position error in pixels = [" + e_position.toString() + "]");
1543  yInfoVerbose("Orientation error in pixels = [" + e_orientation.toString() + "]");
1544 
1545  mtx_px_des_.unlock();
1546 
1547 
1548  /* EVALUATING CONTROL VELOCITIES */
1549  mtx_H_eye_cam_.lock();
1550 
1551  Vector vel_x = zeros(3);
1552  Vector vel_o = zeros(3);
1553  for (int i = 0; i < inv_jacobian_position.cols(); ++i)
1554  {
1555  Vector delta_vel_position = inv_jacobian_position.getCol(i) * e_position(i);
1556  Vector delta_vel_orientation = inv_jacobian_orientation.getCol(i) * e_orientation(i);
1557 
1558  if (i == 1 || i == 3 || i == 5 || i == 7 || i == 9 || i == 11 || i == 13 || i == 15)
1559  {
1560  vel_x += r_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel_position.subVector(0, 2);
1561  vel_o += r_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel_orientation.subVector(3, 5);
1562  }
1563  else
1564  {
1565  vel_x += l_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel_position.subVector(0, 2);
1566  vel_o += l_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel_orientation.subVector(3, 5);
1567  }
1568  }
1569 
1570  mtx_H_eye_cam_.unlock();
1571 
1572  double ang = norm(vel_o);
1573  vel_o /= ang;
1574  vel_o.push_back(ang);
1575 
1576  yInfoVerbose("Translational velocity = [" + vel_x.toString() + "]");
1577  yInfoVerbose("Orientation velocity = [" + vel_o.toString() + "]");
1578 
1579 
1580  /* ENFORCE TRANSLATIONAL VELOCITY BOUNDS */
1581  for (size_t i = 0; i < vel_x.length(); ++i)
1582  {
1583  if (!std::isnan(vel_x[i]) && !std::isinf(vel_x[i]))
1584  vel_x[i] = sign(vel_x[i]) * std::min(max_x_dot_, std::fabs(vel_x[i]));
1585  else
1586  {
1587  vel_x = Vector(3, 0.0);
1588  break;
1589  }
1590  }
1591  yInfoVerbose("Bounded translational velocity = [" + vel_x.toString() + "]");
1592 
1593 
1594  /* ENFORCE ROTATIONAL VELOCITY BOUNDS */
1595  if (!std::isnan(vel_o[0]) && !std::isinf(vel_x[0]) &&
1596  !std::isnan(vel_o[1]) && !std::isinf(vel_x[1]) &&
1597  !std::isnan(vel_o[2]) && !std::isinf(vel_x[2]) &&
1598  !std::isnan(vel_o[3]) && !std::isinf(vel_x[3]))
1599  vel_o[3] = sign(vel_o[3]) * std::min(max_o_dot_, std::fabs(vel_o[3]));
1600  else
1601  vel_o = Vector(4, 0.0);
1602  yInfoVerbose("Bounded orientation velocity = [" + vel_o.toString() + "]");
1603 
1604 
1605  /* VISUAL CONTROL LAW */
1606  if (!checkVisualServoingStatus(px_ee_cur_position, K_x_tol_))
1607  {
1608  vel_x *= K_x_[0];
1609  if (K_x_hysteresis_)
1610  {
1611  K_x_hysteresis_ = false;
1612 
1613  K_x_tol_ -= 5.0;
1614  }
1615  }
1616  else
1617  {
1618  vel_x *= K_x_[1];
1619  if (!K_x_hysteresis_)
1620  {
1621  K_x_hysteresis_ = true;
1622 
1623  K_x_tol_ += 5.0;
1624  }
1625  }
1626 
1627  if (!checkVisualServoingStatus(px_ee_cur_orientation, K_o_tol_))
1628  {
1629  vel_o(3) *= K_o_[0];
1630  if (K_o_hysteresis_)
1631  {
1632  K_o_hysteresis_ = false;
1633 
1634  K_o_tol_ -= 5.0;
1635  }
1636  }
1637  else
1638  {
1639  vel_o(3) *= K_o_[1];
1640  if (!K_o_hysteresis_)
1641  {
1642  K_o_hysteresis_ = true;
1643 
1644  K_o_tol_ += 5.0;
1645  }
1646  }
1647 
1648 
1649  if (!sim_)
1650  {
1651  /* COMMAND END-EFFECTOR WITH THE CARTESIAN CONTROLLER */
1652  if (op_mode_ == OperatingMode::position)
1653  itf_rightarm_cart_->setTaskVelocities(vel_x, Vector(4, 0.0));
1654  else if (op_mode_ == OperatingMode::orientation)
1655  itf_rightarm_cart_->setTaskVelocities(Vector(3, 0.0), vel_o);
1656  else if (op_mode_ == OperatingMode::pose)
1657  itf_rightarm_cart_->setTaskVelocities(vel_x, vel_o);
1658 
1659 
1660  /* WAIT FOR SOME MOTION */
1661  Time::delay(Ts_);
1662 
1663 
1664  /* UPDATE END-EFFECTOR POSE FOR THE LEFT EYE */
1665  endeffector_pose = port_pose_left_in_.read(true);
1666  eepose_copy_left = *endeffector_pose;
1667 
1668  /* UPDATE END-EFFECTOR POSE FOR THE RIGHT EYE */
1669  endeffector_pose = port_pose_right_in_.read(true);
1670  eepose_copy_right = *endeffector_pose;
1671 
1672  /* UPDATE END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
1673  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
1674  eepose_copy_left = eepose_averaged;
1675  eepose_copy_right = eepose_averaged;
1676  }
1677  else
1678  {
1679  /* SIMULATE END-EFFECTOR COMMAND AND UPDATE ITS POSE */
1680  Matrix l_R = axis2dcm(eepose_copy_left.subVector(3, 6));
1681  Matrix r_R = axis2dcm(eepose_copy_right.subVector(3, 6));
1682 
1683 
1684  vel_o[3] *= Ts_;
1685  l_R = axis2dcm(vel_o) * l_R;
1686  r_R = axis2dcm(vel_o) * r_R;
1687 
1688 
1689  Vector l_new_o = dcm2axis(l_R);
1690  Vector r_new_o = dcm2axis(r_R);
1691 
1692 
1693  if (op_mode_ == OperatingMode::position)
1694  {
1695  eepose_copy_left.setSubvector(0, eepose_copy_left.subVector(0, 2) + vel_x * Ts_);
1696  eepose_copy_right.setSubvector(0, eepose_copy_right.subVector(0, 2) + vel_x * Ts_);
1697  }
1698  else if (op_mode_ == OperatingMode::orientation)
1699  {
1700  eepose_copy_left.setSubvector(3, l_new_o);
1701  eepose_copy_right.setSubvector(3, r_new_o);
1702  }
1703  else if (op_mode_ == OperatingMode::pose)
1704  {
1705  eepose_copy_left.setSubvector(0, eepose_copy_left.subVector(0, 2) + vel_x * Ts_);
1706  eepose_copy_right.setSubvector(0, eepose_copy_right.subVector(0, 2) + vel_x * Ts_);
1707  eepose_copy_left.setSubvector(3, l_new_o);
1708  eepose_copy_right.setSubvector(3, r_new_o);
1709  }
1710  }
1711  }
1712  }
1713 }
1714 
1715 
1717 {
1718  /* VARIABLE DEFINITIONS */
1719  Vector* endeffector_pose;
1720  Vector eepose_copy_left(7);
1721  Vector eepose_copy_right(7);
1722  Vector eepose_averaged(7);
1723 
1724  std::vector<Vector> l_px_pose;
1725  std::vector<Vector> r_px_pose;
1726 
1727  Vector px_ee_cur_pose = zeros(16);
1728  Matrix jacobian_pose = zeros(16, 6);
1729  Vector px_ee_cur_goal = zeros(16);
1730  Matrix jacobian_goal = zeros(16, 6);
1731 
1732 
1733  /* GET THE INITIAL END-EFFECTOR POSE FOR THE LEFT EYE */
1734  endeffector_pose = port_pose_left_in_.read(true);
1735  eepose_copy_left = *endeffector_pose;
1736 
1737  yInfoVerbose("Got [" + eepose_copy_left.toString() + "] end-effector pose for the left eye.");
1738 
1739  /* GET THE INITIAL END-EFFECTOR POSE FOR THE RIGHT EYE */
1740  endeffector_pose = port_pose_right_in_.read(true);
1741  eepose_copy_right = *endeffector_pose;
1742 
1743  /* GET THE INITIAL END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
1744  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
1745  eepose_copy_left = eepose_averaged;
1746  eepose_copy_right = eepose_averaged;
1747 
1748  yInfoVerbose("Got [" + eepose_copy_right.toString() + "] end-effector pose for the right eye.");
1749 
1750  while (!isStopping() && !vs_goal_reached_)
1751  {
1752  yInfoVerbose("Desired goal pixels = [" + px_des_.toString() + "]");
1753 
1754 
1755  /* EVALUATING CONTROL POINTS */
1756  l_px_pose = getControlPixelsFromPose(eepose_copy_left, CamSel::left, PixelControlMode::all);
1757  r_px_pose = getControlPixelsFromPose(eepose_copy_right, CamSel::right, PixelControlMode::all);
1758 
1759 
1760  /* POSE: FEATURES AND JACOBIAN */
1761  getCurrentStereoFeaturesAndJacobian(l_px_pose, r_px_pose,
1762  px_ee_cur_pose, jacobian_pose);
1763 
1764  yInfoVerbose("Pose controlled pixels = [" + px_ee_cur_pose.toString() + "]");
1765  yInfoVerbose("Pose image Jacobian = [\n" + jacobian_pose.toString() + "]");
1766 
1767  /* GOAL: FEATURES AND JACOBIAN */
1768  getCurrentStereoFeaturesAndJacobian(l_px_goal_, r_px_goal_,
1769  px_ee_cur_goal, jacobian_goal);
1770 
1771  yInfoVerbose("Goal 'controlled' pixels = [" + px_ee_cur_goal.toString() + "]");
1772  yInfoVerbose("Desired goal pixels = [" + px_des_.toString() + "]");
1773  yInfoVerbose("Goal image Jacobian = [\n" + jacobian_goal.toString() + "]");
1774 
1775 
1776  /* *** *** *** DEBUG OUTPUT - TO BE DELETED *** *** *** */
1777  std::vector<cv::Scalar> color;
1778  color.emplace_back(cv::Scalar(255, 0, 0));
1779  color.emplace_back(cv::Scalar( 0, 255, 0));
1780  color.emplace_back(cv::Scalar( 0, 0, 255));
1781  color.emplace_back(cv::Scalar(255, 127, 51));
1782 
1783 
1784  /* Left eye end-effector superimposition */
1785  ImageOf<PixelRgb>* l_imgin = port_image_left_in_.read(true);
1786  ImageOf<PixelRgb>& l_imgout = port_image_left_out_.prepare();
1787  l_imgout = *l_imgin;
1788  cv::Mat l_img = cv::cvarrToMat(l_imgout.getIplImage());
1789 
1790  /* Right eye end-effector superimposition */
1791  ImageOf<PixelRgb>* r_imgin = port_image_right_in_.read(true);
1792  ImageOf<PixelRgb>& r_imgout = port_image_right_out_.prepare();
1793  r_imgout = *r_imgin;
1794  cv::Mat r_img = cv::cvarrToMat(r_imgout.getIplImage());
1795 
1796 
1797  /* Plot points and lines */
1798  for (int i = 0; i < l_px_pose.size(); ++i)
1799  {
1800  const Vector& l_cur_px_p = l_px_pose[i];
1801  const Vector& l_pre_px_p = l_px_pose[(3 + i) % 4];
1802 
1803  const Vector& r_cur_px_p = r_px_pose[i];
1804  const Vector& r_pre_px_p = r_px_pose[(3 + i) % 4];
1805 
1806  const Vector& l_cur_px_g = l_px_goal_[i];
1807  const Vector& l_pre_px_g = l_px_goal_[(3 + i) % 4];
1808 
1809  const Vector& r_cur_px_g = r_px_goal_[i];
1810  const Vector& r_pre_px_g = r_px_goal_[(3 + i) % 4];
1811 
1812 
1813  cv::line(l_img, cv::Point(l_pre_px_p[0], l_pre_px_p[1]), cv::Point(l_cur_px_p[0], l_cur_px_p[1]), color[3], 4, cv::LineTypes::LINE_AA);
1814  cv::line(r_img, cv::Point(r_pre_px_p[0], r_pre_px_p[1]), cv::Point(r_cur_px_p[0], r_cur_px_p[1]), color[3], 4, cv::LineTypes::LINE_AA);
1815 
1816  cv::line(l_img, cv::Point(l_pre_px_g[0], l_pre_px_g[1]), cv::Point(l_cur_px_g[0], l_cur_px_g[1]), color[3], 4, cv::LineTypes::LINE_AA);
1817  cv::line(r_img, cv::Point(r_pre_px_g[0], r_pre_px_g[1]), cv::Point(r_cur_px_g[0], r_cur_px_g[1]), color[3], 4, cv::LineTypes::LINE_AA);
1818 
1819  if (i == 2 || i == 3)
1820  {
1821  cv::circle(l_img, cv::Point(l_cur_px_p[0], l_cur_px_p[1]), 4, color[i - 1], 4);
1822  cv::circle(r_img, cv::Point(r_cur_px_p[0], r_cur_px_p[1]), 4, color[i - 1], 4);
1823 
1824  cv::circle(l_img, cv::Point(l_cur_px_g[0], l_cur_px_g[1]), 4, color[i - 1], 4);
1825  cv::circle(r_img, cv::Point(r_cur_px_g[0], r_cur_px_g[1]), 4, color[i - 1], 4);
1826  }
1827  }
1828 
1829 
1830  Vector l_cur_px_ee = getPixelFromPoint(CamSel::left, cat(eepose_copy_left.subVector(0, 2), 1.0));
1831  Vector r_cur_px_ee = getPixelFromPoint(CamSel::right, cat(eepose_copy_right.subVector(0, 2), 1.0));
1832 
1833  cv::circle(l_img, cv::Point(l_cur_px_ee[0], l_cur_px_ee[1]), 4, color[0], 4);
1834  cv::circle(r_img, cv::Point(r_cur_px_ee[0], r_cur_px_ee[1]), 4, color[0], 4);
1835 
1836 
1837  Vector l_cur_px_g = getPixelFromPoint(CamSel::left, cat(goal_pose_.subVector(0, 2), 1.0));
1838  Vector r_cur_px_g = getPixelFromPoint(CamSel::right, cat(goal_pose_.subVector(0, 2), 1.0));
1839 
1840  cv::circle(l_img, cv::Point(l_cur_px_g[0], l_cur_px_g[1]), 4, color[0], 4);
1841  cv::circle(r_img, cv::Point(r_cur_px_g[0], r_cur_px_g[1]), 4, color[0], 4);
1842 
1843  port_image_left_out_.write();
1844  port_image_right_out_.write();
1845  /* *** *** *** *** *** *** *** *** *** *** *** *** *** */
1846 
1847  /* *** *** *** LOG - TO BE DELETED *** *** *** */
1848 
1849  Vector& pose_px_l = port_pose_px_l_.prepare();
1850  pose_px_l = stdVectorOfVectorsToVector(getControlPixelsFromPose(eepose_copy_left, CamSel::left, PixelControlMode::all));
1851  port_pose_px_l_.write();
1852 
1853  Vector& pose_px_r = port_pose_px_r_.prepare();
1854  pose_px_r = stdVectorOfVectorsToVector(getControlPixelsFromPose(eepose_copy_right, CamSel::right, PixelControlMode::all));
1855  port_pose_px_r_.write();
1856 
1857  Vector kin_x;
1858  Vector kin_o;
1859  itf_rightarm_cart_->getPose(kin_x, kin_o);
1860 
1861  Vector& pose_kin_px_l = port_kin_px_l_.prepare();
1862  pose_kin_px_l = stdVectorOfVectorsToVector(getControlPixelsFromPose(cat(kin_x, kin_o), CamSel::left, PixelControlMode::all));
1863  port_kin_px_l_.write();
1864 
1865  Vector& pose_kin_px_r = port_kin_px_r_.prepare();
1866  pose_kin_px_r = stdVectorOfVectorsToVector(getControlPixelsFromPose(cat(kin_x, kin_o), CamSel::right, PixelControlMode::all));
1867  port_kin_px_r_.write();
1868 
1869  Vector& goal_px_l_ = port_goal_px_l_.prepare();
1870  goal_px_l_ = stdVectorOfVectorsToVector(l_px_goal_);
1871  port_goal_px_l_.write();
1872 
1873  Vector& goal_px_r_ = port_goal_px_r_.prepare();
1874  goal_px_r_ = stdVectorOfVectorsToVector(r_px_goal_);
1875  port_goal_px_r_.write();
1876 
1877  Vector& pose_avg_ = port_pose_avg_.prepare();
1878  pose_avg_ = eepose_averaged;
1879  port_pose_avg_.write();
1880 
1881  Vector& pose_kin_ = port_pose_kin_.prepare();
1882  pose_kin_ = cat(kin_x, kin_o);
1883  port_pose_kin_.write();
1884 
1885  Vector& pose_goal_ = port_pose_goal_.prepare();
1886  pose_goal_ = goal_pose_;
1887  port_pose_goal_.write();
1888 
1889  /* *** *** *** *** *** *** *** *** *** *** *** */
1890 
1891 
1892  /* CHECK FOR GOAL */
1893  mtx_px_des_.lock();
1894 
1895  vs_goal_reached_ = checkVisualServoingStatus(px_ee_cur_pose, tol_px_);
1896 
1897  mtx_px_des_.unlock();
1898 
1899 
1900  if (vs_goal_reached_)
1901  {
1902  yInfoVerbose("");
1903  yInfoVerbose("*** Goal reached! ***");
1904  yInfoVerbose("Desired goal pixels = " + px_des_.toString());
1905  yInfoVerbose("Current position controlled pixels = " + px_ee_cur_pose.toString());
1906  yInfoVerbose("*** ------------- ***");
1907  yInfoVerbose("");
1908  }
1909  else
1910  {
1911  /* EVALUATING ERRORS */
1912  mtx_px_des_.lock();
1913 
1914  Vector e = px_des_ - px_ee_cur_pose;
1915  Matrix inv_jacobian = pinv(0.5 * (jacobian_pose + jacobian_goal));
1916 
1917  yInfoVerbose("Position error in pixels = [" + e.toString() + "]");
1918 
1919  mtx_px_des_.unlock();
1920 
1921 
1922  /* EVALUATING CONTROL VELOCITIES */
1923  mtx_H_eye_cam_.lock();
1924 
1925  Vector vel_x = zeros(3);
1926  Vector vel_o = zeros(3);
1927  for (int i = 0; i < inv_jacobian.cols(); ++i)
1928  {
1929  Vector delta_vel = inv_jacobian.getCol(i) * e(i);
1930 
1931  if (i == 1 || i == 3 || i == 5 || i == 7 || i == 9 || i == 11 || i == 13 || i == 15)
1932  {
1933  vel_x += r_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel.subVector(0, 2);
1934  vel_o += r_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel.subVector(3, 5);
1935  }
1936  else
1937  {
1938  vel_x += l_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel.subVector(0, 2);
1939  vel_o += l_H_eye_to_r_.submatrix(0, 2, 0, 2) * delta_vel.subVector(3, 5);
1940  }
1941  }
1942 
1943  mtx_H_eye_cam_.unlock();
1944 
1945  double ang = norm(vel_o);
1946  vel_o /= ang;
1947  vel_o.push_back(ang);
1948 
1949  yInfoVerbose("Translational velocity = [" + vel_x.toString() + "]");
1950  yInfoVerbose("Orientation velocity = [" + vel_o.toString() + "]");
1951 
1952 
1953  /* ENFORCE TRANSLATIONAL VELOCITY BOUNDS */
1954  for (size_t i = 0; i < vel_x.length(); ++i)
1955  {
1956  if (!std::isnan(vel_x[i]) && !std::isinf(vel_x[i]))
1957  vel_x[i] = sign(vel_x[i]) * std::min(max_x_dot_, std::fabs(vel_x[i]));
1958  else
1959  {
1960  vel_x = Vector(3, 0.0);
1961  break;
1962  }
1963  }
1964  yInfoVerbose("Bounded translational velocity = [" + vel_x.toString() + "]");
1965 
1966 
1967  /* ENFORCE ROTATIONAL VELOCITY BOUNDS */
1968  if (!std::isnan(vel_o[0]) && !std::isinf(vel_x[0]) &&
1969  !std::isnan(vel_o[1]) && !std::isinf(vel_x[1]) &&
1970  !std::isnan(vel_o[2]) && !std::isinf(vel_x[2]) &&
1971  !std::isnan(vel_o[3]) && !std::isinf(vel_x[3]))
1972  vel_o[3] = sign(vel_o[3]) * std::min(max_o_dot_, std::fabs(vel_o[3]));
1973  else
1974  vel_o = Vector(4, 0.0);
1975  yInfoVerbose("Bounded orientation velocity = [" + vel_o.toString() + "]");
1976 
1977 
1978  /* VISUAL CONTROL LAW */
1979  if (!checkVisualServoingStatus(px_ee_cur_pose, K_x_tol_))
1980  {
1981  vel_x *= K_x_[0];
1982  if (K_x_hysteresis_)
1983  {
1984  K_x_hysteresis_ = false;
1985 
1986  K_x_tol_ -= 5.0;
1987  }
1988  }
1989  else
1990  {
1991  vel_x *= K_x_[1];
1992  if (!K_x_hysteresis_)
1993  {
1994  K_x_hysteresis_ = true;
1995 
1996  K_x_tol_ += 5.0;
1997  }
1998  }
1999 
2000  if (!checkVisualServoingStatus(px_ee_cur_goal, K_o_tol_))
2001  {
2002  vel_o(3) *= K_o_[0];
2003  if (K_o_hysteresis_)
2004  {
2005  K_o_hysteresis_ = false;
2006 
2007  K_o_tol_ -= 5.0;
2008  }
2009  }
2010  else
2011  {
2012  vel_o(3) *= K_o_[1];
2013  if (!K_o_hysteresis_)
2014  {
2015  K_o_hysteresis_ = true;
2016 
2017  K_o_tol_ += 5.0;
2018  }
2019  }
2020 
2021 
2022  if (!sim_)
2023  {
2024  /* COMMAND END-EFFECTOR WITH THE CARTESIAN CONTROLLER */
2025  itf_rightarm_cart_->setTaskVelocities(vel_x, vel_o);
2026 
2027 
2028  /* WAIT FOR SOME MOTION */
2029  Time::delay(Ts_);
2030 
2031 
2032  /* UPDATE END-EFFECTOR POSE FOR THE LEFT EYE */
2033  endeffector_pose = port_pose_left_in_.read(true);
2034  eepose_copy_left = *endeffector_pose;
2035 
2036  /* UPDATE END-EFFECTOR POSE FOR THE RIGHT EYE */
2037  endeffector_pose = port_pose_right_in_.read(true);
2038  eepose_copy_right = *endeffector_pose;
2039 
2040  /* UPDATE END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
2041  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
2042  eepose_copy_left = eepose_averaged;
2043  eepose_copy_right = eepose_averaged;
2044  }
2045  else
2046  {
2047  Matrix l_R = axis2dcm(eepose_copy_left.subVector(3, 6));
2048  Matrix r_R = axis2dcm(eepose_copy_right.subVector(3, 6));
2049 
2050 
2051  vel_o[3] *= Ts_;
2052  l_R = axis2dcm(vel_o) * l_R;
2053  r_R = axis2dcm(vel_o) * r_R;
2054 
2055 
2056  Vector l_new_o = dcm2axis(l_R);
2057  Vector r_new_o = dcm2axis(r_R);
2058 
2059 
2060  /* SIMULATE END-EFFECTOR COMMAND AND UPDATE ITS POSE */
2061  eepose_copy_left.setSubvector(0, eepose_copy_left.subVector(0, 2) + vel_x * Ts_);
2062  eepose_copy_right.setSubvector(0, eepose_copy_right.subVector(0, 2) + vel_x * Ts_);
2063  eepose_copy_left.setSubvector(3, l_new_o);
2064  eepose_copy_right.setSubvector(3, r_new_o);
2065  }
2066  }
2067  }
2068 }
2069 
2070 
2072 {
2073  /* VARIABLE DEFINITIONS */
2074  Vector* endeffector_pose;
2075  Vector eepose_copy_left(7);
2076  Vector eepose_copy_right(7);
2077  Vector eepose_averaged(7);
2078 
2079  /* GET THE INITIAL END-EFFECTOR POSE FOR THE LEFT EYE */
2080  endeffector_pose = port_pose_left_in_.read(true);
2081  eepose_copy_left = *endeffector_pose;
2082 
2083  yInfoVerbose("Got [" + eepose_copy_left.toString() + "] end-effector pose for the left eye.");
2084 
2085  /* GET THE INITIAL END-EFFECTOR POSE FOR THE RIGHT EYE */
2086  endeffector_pose = port_pose_right_in_.read(true);
2087  eepose_copy_right = *endeffector_pose;
2088 
2089  yInfoVerbose("Got [" + eepose_copy_right.toString() + "] end-effector pose for the right eye.");
2090 
2091  /* GET THE INITIAL END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
2092  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
2093  eepose_copy_left = eepose_averaged;
2094  eepose_copy_right = eepose_averaged;
2095 
2096  yInfoVerbose("Averaged end-effector pose: [" + eepose_averaged.toString() + "].");
2097 
2098 
2099  while (!isStopping() && !vs_goal_reached_)
2100  {
2101  yInfoVerbose("Desired goal pose = [" + goal_pose_.toString() + "]");
2102 
2103 
2104  /* *** *** *** DEBUG OUTPUT - TO BE DELETED *** *** *** */
2105  std::vector<cv::Scalar> color;
2106  color.emplace_back(cv::Scalar(255, 0, 0));
2107  color.emplace_back(cv::Scalar( 0, 255, 0));
2108  color.emplace_back(cv::Scalar( 0, 0, 255));
2109  color.emplace_back(cv::Scalar(255, 127, 51));
2110 
2111 
2112  /* Left eye end-effector superimposition */
2113  ImageOf<PixelRgb>* l_imgin = port_image_left_in_.read(true);
2114  ImageOf<PixelRgb>& l_imgout = port_image_left_out_.prepare();
2115  l_imgout = *l_imgin;
2116  cv::Mat l_img = cv::cvarrToMat(l_imgout.getIplImage());
2117 
2118  /* Right eye end-effector superimposition */
2119  ImageOf<PixelRgb>* r_imgin = port_image_right_in_.read(true);
2120  ImageOf<PixelRgb>& r_imgout = port_image_right_out_.prepare();
2121  r_imgout = *r_imgin;
2122  cv::Mat r_img = cv::cvarrToMat(r_imgout.getIplImage());
2123 
2124 
2125  /* Plot points and lines */
2126  Vector l_position_ee = getPixelFromPoint(CamSel::left, cat(eepose_averaged.subVector(0, 2), 1.0));
2127  Vector r_position_ee = getPixelFromPoint(CamSel::right, cat(eepose_averaged.subVector(0, 2), 1.0));
2128 
2129  Matrix H_ee_to_root = axis2dcm(eepose_averaged.subVector(3, 6));
2130  H_ee_to_root.setCol(3, cat(eepose_averaged.subVector(0, 2), 1.0));
2131 
2132  Vector versor_x_ee = H_ee_to_root * cat(0.03, 0, 0, 1.0);
2133  Vector versor_y_ee = H_ee_to_root * cat( 0, 0.03, 0, 1.0);
2134  Vector versor_z_ee = H_ee_to_root * cat( 0, 0, 0.03, 1.0);
2135 
2136  Vector l_versor_x_ee = getPixelFromPoint(CamSel::left, versor_x_ee);
2137  Vector l_versor_y_ee = getPixelFromPoint(CamSel::left, versor_y_ee);
2138  Vector l_versor_z_ee = getPixelFromPoint(CamSel::left, versor_z_ee);
2139 
2140  Vector r_versor_x_ee = getPixelFromPoint(CamSel::right, versor_x_ee);
2141  Vector r_versor_y_ee = getPixelFromPoint(CamSel::right, versor_y_ee);
2142  Vector r_versor_z_ee = getPixelFromPoint(CamSel::right, versor_z_ee);
2143 
2144  cv::circle(l_img, cv::Point(l_position_ee[0], l_position_ee[1]), 4, color[3], 4);
2145  cv::line (l_img, cv::Point(l_position_ee[0], l_position_ee[1]), cv::Point(l_versor_x_ee[0], l_versor_x_ee[1]), color[0], 4, cv::LineTypes::LINE_AA);
2146  cv::line (l_img, cv::Point(l_position_ee[0], l_position_ee[1]), cv::Point(l_versor_y_ee[0], l_versor_y_ee[1]), color[1], 4, cv::LineTypes::LINE_AA);
2147  cv::line (l_img, cv::Point(l_position_ee[0], l_position_ee[1]), cv::Point(l_versor_z_ee[0], l_versor_z_ee[1]), color[2], 4, cv::LineTypes::LINE_AA);
2148 
2149  cv::circle(r_img, cv::Point(r_position_ee[0], r_position_ee[1]), 4, color[3], 4);
2150  cv::line (r_img, cv::Point(r_position_ee[0], r_position_ee[1]), cv::Point(r_versor_x_ee[0], r_versor_x_ee[1]), color[0], 4, cv::LineTypes::LINE_AA);
2151  cv::line (r_img, cv::Point(r_position_ee[0], r_position_ee[1]), cv::Point(r_versor_y_ee[0], r_versor_y_ee[1]), color[1], 4, cv::LineTypes::LINE_AA);
2152  cv::line (r_img, cv::Point(r_position_ee[0], r_position_ee[1]), cv::Point(r_versor_z_ee[0], r_versor_z_ee[1]), color[2], 4, cv::LineTypes::LINE_AA);
2153 
2154 
2155  Vector l_position_g = getPixelFromPoint(CamSel::left, cat(goal_pose_.subVector(0, 2), 1.0));
2156  Vector r_position_g = getPixelFromPoint(CamSel::right, cat(goal_pose_.subVector(0, 2), 1.0));
2157 
2158  Matrix H_goal_to_root = axis2dcm(goal_pose_.subVector(3, 6));
2159  H_goal_to_root.setCol(3, cat(goal_pose_.subVector(0, 2), 1.0));
2160 
2161  Vector versor_x_g = H_goal_to_root * cat(0.03, 0, 0, 1.0);
2162  Vector versor_y_g = H_goal_to_root * cat( 0, 0.03, 0, 1.0);
2163  Vector versor_z_g = H_goal_to_root * cat( 0, 0, 0.03, 1.0);
2164 
2165  Vector l_versor_x_g = getPixelFromPoint(CamSel::left, versor_x_g);
2166  Vector l_versor_y_g = getPixelFromPoint(CamSel::left, versor_y_g);
2167  Vector l_versor_z_g = getPixelFromPoint(CamSel::left, versor_z_g);
2168 
2169  Vector r_versor_x_g = getPixelFromPoint(CamSel::right, versor_x_g);
2170  Vector r_versor_y_g = getPixelFromPoint(CamSel::right, versor_y_g);
2171  Vector r_versor_z_g = getPixelFromPoint(CamSel::right, versor_z_g);
2172 
2173  cv::circle(l_img, cv::Point(l_position_g[0], l_position_g[1]), 4, color[3], 4);
2174  cv::line (l_img, cv::Point(l_position_g[0], l_position_g[1]), cv::Point(l_versor_x_g[0], l_versor_x_g[1]), color[0], 4, cv::LineTypes::LINE_AA);
2175  cv::line (l_img, cv::Point(l_position_g[0], l_position_g[1]), cv::Point(l_versor_y_g[0], l_versor_y_g[1]), color[1], 4, cv::LineTypes::LINE_AA);
2176  cv::line (l_img, cv::Point(l_position_g[0], l_position_g[1]), cv::Point(l_versor_z_g[0], l_versor_z_g[1]), color[2], 4, cv::LineTypes::LINE_AA);
2177 
2178  cv::circle(r_img, cv::Point(r_position_g[0], r_position_g[1]), 4, color[3], 4);
2179  cv::line (r_img, cv::Point(r_position_g[0], r_position_g[1]), cv::Point(r_versor_x_g[0], r_versor_x_g[1]), color[0], 4, cv::LineTypes::LINE_AA);
2180  cv::line (r_img, cv::Point(r_position_g[0], r_position_g[1]), cv::Point(r_versor_y_g[0], r_versor_y_g[1]), color[1], 4, cv::LineTypes::LINE_AA);
2181  cv::line (r_img, cv::Point(r_position_g[0], r_position_g[1]), cv::Point(r_versor_z_g[0], r_versor_z_g[1]), color[2], 4, cv::LineTypes::LINE_AA);
2182 
2183 
2184  port_image_left_out_.write();
2185  port_image_right_out_.write();
2186  /* *** *** *** *** *** *** *** *** *** *** *** *** *** */
2187 
2188  /* *** *** *** LOG - TO BE DELETED *** *** *** */
2189 
2190  Vector& pose_avg_ = port_pose_avg_.prepare();
2191  pose_avg_ = eepose_averaged;
2192  port_pose_avg_.write();
2193 
2194  Vector kin_x;
2195  Vector kin_o;
2196  itf_rightarm_cart_->getPose(kin_x, kin_o);
2197 
2198  Vector& pose_kin_ = port_pose_kin_.prepare();
2199  pose_kin_ = cat(kin_x, kin_o);
2200  port_pose_kin_.write();
2201 
2202  Vector& pose_goal_ = port_pose_goal_.prepare();
2203  pose_goal_ = goal_pose_;
2204  port_pose_goal_.write();
2205 
2206  /* *** *** *** *** *** *** *** *** *** *** *** */
2207 
2208  /* CHECK FOR GOAL */
2209  mtx_px_des_.lock();
2210 
2211  vs_goal_reached_ = checkVisualServoingStatus(eepose_averaged, tol_position_, tol_orientation_, tol_angle_);
2212 
2213  mtx_px_des_.unlock();
2214 
2215 
2216  if (vs_goal_reached_)
2217  {
2218  yInfoVerbose("");
2219  yInfoVerbose("*** Goal reached! ***");
2220  yInfoVerbose("Desired goal pose = " + goal_pose_.toString());
2221  yInfoVerbose("Reached pose = " + eepose_averaged.toString());
2222  yInfoVerbose("*** ------------- ***");
2223  yInfoVerbose("");
2224  }
2225  else
2226  {
2227  /* EVALUATING ERRORS */
2228  mtx_px_des_.lock();
2229 
2230  Vector e_pos = goal_pose_.subVector(0, 2) - eepose_averaged.subVector(0, 2);
2231  Vector e_orientation = dcm2axis(axis2dcm(goal_pose_.subVector(3, 6)) * axis2dcm(eepose_averaged.subVector(3, 6)).transposed());
2232 
2233  yInfoVerbose("Position error = [" + e_pos.toString() + "]");
2234  yInfoVerbose("Orientation error = [" + e_orientation.toString() + "]");
2235 
2236  mtx_px_des_.unlock();
2237 
2238 
2239  /* EVALUATING CONTROL VELOCITIES */
2240  Vector vel_o = cat(e_orientation.subVector(0, 2), e_orientation(3));
2241  Vector vel_x = e_pos;
2242 
2243  yInfoVerbose("Translational velocity = [" + vel_x.toString() + "]");
2244  yInfoVerbose("Orientation velocity = [" + vel_o.toString() + "]");
2245 
2246 
2247  /* ENFORCE TRANSLATIONAL VELOCITY BOUNDS */
2248  for (size_t i = 0; i < vel_x.length(); ++i)
2249  {
2250  if (!std::isnan(vel_x[i]) && !std::isinf(vel_x[i]))
2251  vel_x[i] = sign(vel_x[i]) * std::min(max_x_dot_, std::fabs(vel_x[i]));
2252  else
2253  {
2254  vel_x = Vector(3, 0.0);
2255  break;
2256  }
2257  }
2258  yInfoVerbose("Bounded translational velocity = [" + vel_x.toString() + "]");
2259 
2260 
2261  /* ENFORCE ROTATIONAL VELOCITY BOUNDS */
2262  if (!std::isnan(vel_o[0]) && !std::isinf(vel_x[0]) &&
2263  !std::isnan(vel_o[1]) && !std::isinf(vel_x[1]) &&
2264  !std::isnan(vel_o[2]) && !std::isinf(vel_x[2]) &&
2265  !std::isnan(vel_o[3]) && !std::isinf(vel_x[3]))
2266  vel_o[3] = sign(vel_o[3]) * std::min(max_o_dot_, std::fabs(vel_o[3]));
2267  else
2268  vel_o = Vector(4, 0.0);
2269  yInfoVerbose("Bounded orientation velocity = [" + vel_o.toString() + "]");
2270 
2271 
2272  /* VISUAL CONTROL LAW */
2273  if (!checkVisualServoingStatus(eepose_averaged, K_position_tol_, K_orientation_tol_, K_angle_tol_))
2274  {
2275  vel_x *= K_x_[0];
2276  vel_o(3) *= K_o_[0];
2277  if (K_pose_hysteresis_)
2278  {
2279  K_pose_hysteresis_ = false;
2280 
2281  K_position_tol_ -= 0.02;
2282  K_orientation_tol_ -= (2.0 * M_PI / 180.0);
2283  }
2284  }
2285  else
2286  {
2287  vel_x *= K_x_[1];
2288  vel_o(3) *= K_o_[1];
2289  if (!K_pose_hysteresis_)
2290  {
2291  K_pose_hysteresis_ = true;
2292 
2293  K_position_tol_ += 0.02;
2294  K_orientation_tol_ += (2.0 * M_PI / 180.0);
2295  }
2296  }
2297 
2298 
2299  if (!sim_)
2300  {
2301  /* COMMAND END-EFFECTOR WITH THE CARTESIAN CONTROLLER */
2302  itf_rightarm_cart_->setTaskVelocities(vel_x, vel_o);
2303 
2304 
2305  /* WAIT FOR SOME MOTION */
2306  Time::delay(Ts_);
2307 
2308 
2309  /* UPDATE END-EFFECTOR POSE FOR THE LEFT EYE */
2310  endeffector_pose = port_pose_left_in_.read(true);
2311  eepose_copy_left = *endeffector_pose;
2312 
2313  /* UPDATE END-EFFECTOR POSE FOR THE RIGHT EYE */
2314  endeffector_pose = port_pose_right_in_.read(true);
2315  eepose_copy_right = *endeffector_pose;
2316 
2317  /* UPDATE END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
2318  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
2319  eepose_copy_left = eepose_averaged;
2320  eepose_copy_right = eepose_averaged;
2321  }
2322  else
2323  {
2324  Matrix l_R = axis2dcm(eepose_copy_left.subVector(3, 6));
2325  Matrix r_R = axis2dcm(eepose_copy_right.subVector(3, 6));
2326 
2327 
2328  vel_o[3] *= Ts_;
2329  l_R = axis2dcm(vel_o) * l_R;
2330  r_R = axis2dcm(vel_o) * r_R;
2331 
2332 
2333  Vector l_new_o = dcm2axis(l_R);
2334  Vector r_new_o = dcm2axis(r_R);
2335 
2336 
2337  /* SIMULATE END-EFFECTOR COMMAND AND UPDATE ITS POSE */
2338  eepose_copy_left.setSubvector(0, eepose_copy_left.subVector(0, 2) + vel_x * Ts_);
2339  eepose_copy_right.setSubvector(0, eepose_copy_right.subVector(0, 2) + vel_x * Ts_);
2340  eepose_copy_left.setSubvector(3, l_new_o);
2341  eepose_copy_right.setSubvector(3, r_new_o);
2342 
2343  /* SIMULARE END-EFFECTOR POSE AVERAGE TO BE CONTROLLED BY THE VISUAL SERVO CONTROL */
2344  eepose_averaged = averagePose(eepose_copy_left, eepose_copy_right);
2345  eepose_copy_left = eepose_averaged;
2346  eepose_copy_right = eepose_averaged;
2347  }
2348  }
2349  }
2350 }
2351 
2352 
2354 {
2355  Property rightarm_cartesian_options;
2356  rightarm_cartesian_options.put("device", "cartesiancontrollerclient");
2357  rightarm_cartesian_options.put("local", "/visualservoing/cart_right_arm");
2358  rightarm_cartesian_options.put("remote", "/" + robot_name_ + "/cartesianController/right_arm");
2359 
2360  rightarm_cartesian_driver_.open(rightarm_cartesian_options);
2361  if (rightarm_cartesian_driver_.isValid())
2362  {
2363  rightarm_cartesian_driver_.view(itf_rightarm_cart_);
2364  if (!itf_rightarm_cart_)
2365  {
2366  yErrorVerbose("Error getting ICartesianControl interface!");
2367  return false;
2368  }
2369  yInfoVerbose("cartesiancontrollerclient succefully opened.");
2370  }
2371  else
2372  {
2373  yErrorVerbose("Error opening cartesiancontrollerclient device!");
2374  return false;
2375  }
2376 
2377 
2378  if (!itf_rightarm_cart_->storeContext(&ctx_remote_cart_))
2379  {
2380  yErrorVerbose("Error storing remote ICartesianControl context!");
2381  return false;
2382  }
2383  yInfoVerbose("Remote ICartesianControl context stored.");
2384 
2385 
2386  if (!itf_rightarm_cart_->setTrajTime(traj_time_))
2387  {
2388  yErrorVerbose("Error setting ICartesianControl trajectory time!");
2389  return false;
2390  }
2391  yInfoVerbose("Succesfully set ICartesianControl trajectory time.");
2392 
2393 
2394  if (!itf_rightarm_cart_->setInTargetTol(0.01))
2395  {
2396  yErrorVerbose("Error setting ICartesianControl target tolerance!");
2397  return false;
2398  }
2399  yInfoVerbose("Succesfully set ICartesianControl target tolerance.");
2400 
2401 
2402  if (!setTorsoDOF())
2403  {
2404  yErrorVerbose("Unable to change torso DOF!");
2405  return false;
2406  }
2407  yInfoVerbose("Succesfully changed torso DOF.");
2408 
2409 
2410  if (!itf_rightarm_cart_->storeContext(&ctx_local_cart_))
2411  {
2412  yErrorVerbose("Error storing local ICartesianControl context!");
2413  return false;
2414  }
2415  yInfoVerbose("Local ICartesianControl context stored.");
2416 
2417 
2418  if (!itf_rightarm_cart_->restoreContext(ctx_remote_cart_))
2419  {
2420  yErrorVerbose("Error restoring remote ICartesianControl context!");
2421  return false;
2422  }
2423  yInfoVerbose("Remote ICartesianControl context restored.");
2424 
2425 
2426  return true;
2427 }
2428 
2429 
2431 {
2432  Property gaze_option;
2433  gaze_option.put("device", "gazecontrollerclient");
2434  gaze_option.put("local", "/visualservoing/gaze");
2435  gaze_option.put("remote", "/iKinGazeCtrl");
2436 
2437  gaze_driver_.open(gaze_option);
2438  if (gaze_driver_.isValid())
2439  {
2440  gaze_driver_.view(itf_gaze_);
2441  if (!itf_gaze_)
2442  {
2443  yErrorVerbose("Error getting IGazeControl interface!");
2444  return false;
2445  }
2446  }
2447  else
2448  {
2449  yErrorVerbose("Gaze control device not available!");
2450  return false;
2451  }
2452 
2453  return true;
2454 }
2455 
2456 
2458 {
2459  yInfoVerbose("Opening RPC command port.");
2460 
2461  if (!port_rpc_command_.open("/visualservoing/cmd:i"))
2462  {
2463  yErrorVerbose("Cannot open the RPC server command port!");
2464  return false;
2465  }
2466  if (!yarp().attachAsServer(port_rpc_command_))
2467  {
2468  yErrorVerbose("Cannot attach the RPC server command port!");
2469  return false;
2470  }
2471 
2472 
2473  if (!port_rpc_tracker_left_.open("/visualservoing/toTracker/left/cmd:o"))
2474  {
2475  yErrorVerbose("Cannot open the RPC command port to left camera tracker!");
2476  return false;
2477  }
2478  if (!port_rpc_tracker_right_.open("/visualservoing/toTracker/right/cmd:o"))
2479  {
2480  yErrorVerbose("Cannot open the RPC command port to right camera tracker!");
2481  return false;
2482  }
2483 
2484 
2485  yInfoVerbose("RPC command port opened and attached. Ready to recieve commands.");
2486 
2487  return true;
2488 }
2489 
2490 
2492 {
2493  Vector curDOF;
2494  itf_rightarm_cart_->getDOF(curDOF);
2495  yInfoVerbose("Old DOF: [" + curDOF.toString(0) + "].");
2496 
2497  yInfoVerbose("Setting iCub to use torso DOF.");
2498 
2499  Vector newDOF(curDOF);
2500  newDOF[0] = 1;
2501  newDOF[1] = 0;
2502  newDOF[2] = 1;
2503  if (!itf_rightarm_cart_->setDOF(newDOF, curDOF))
2504  return false;
2505 
2506  yInfoVerbose("New DOF: Yaw " + ConstString(curDOF[0] == 0 ? "blocked, " : "actuated, ") +
2507  "Roll " + ConstString(curDOF[1] == 0 ? "blocked, " : "actuated, ") +
2508  "Pitch " + ConstString(curDOF[2] == 0 ? "blocked." : "actuated." ));
2509 
2510  return true;
2511 }
2512 
2513 
2515 {
2516  Vector curDOF;
2517  itf_rightarm_cart_->getDOF(curDOF);
2518  yInfoVerbose("Old DOF: [" + curDOF.toString(0) + "].");
2519 
2520  yInfoVerbose("Setting iCub to block torso DOF.");
2521 
2522  Vector newDOF(curDOF);
2523  newDOF[0] = 0;
2524  newDOF[1] = 0;
2525  newDOF[2] = 0;
2526  if (!itf_rightarm_cart_->setDOF(newDOF, curDOF))
2527  return false;
2528 
2529  yInfoVerbose("New DOF: Yaw " + ConstString(curDOF[0] == 0 ? "blocked, " : "actuated, ") +
2530  "Roll " + ConstString(curDOF[1] == 0 ? "blocked, " : "actuated, ") +
2531  "Pitch " + ConstString(curDOF[2] == 0 ? "blocked." : "actuated." ));
2532 
2533  return true;
2534 }
2535 
2536 
2537 std::vector<Vector> VisualServoingServer::getPixelsFromPose(const Vector& pose, const CamSel& cam)
2538 {
2539  yAssert(pose.length() == 7);
2540  yAssert(cam == CamSel::left || cam == CamSel::right);
2541 
2542 
2543  std::vector<Vector> pt_from_pose = getControlPointsFromPose(pose);
2544 
2545  std::vector<Vector> px_from_pose;
2546  for (const Vector& v : pt_from_pose)
2547  px_from_pose.emplace_back(getPixelFromPoint(cam, v));
2548 
2549  return px_from_pose;
2550 }
2551 
2552 
2553 std::vector<Vector> VisualServoingServer::getControlPixelsFromPose(const Vector& pose, const CamSel& cam, const PixelControlMode& mode)
2554 {
2555  yAssert(pose.length() == 7);
2556  yAssert(cam == CamSel::left || cam == CamSel::right);
2557  yAssert(mode == PixelControlMode::all || mode == PixelControlMode::x || mode == PixelControlMode::o);
2558 
2559 
2560  Vector control_pose = pose;
2561  if (mode == PixelControlMode::x)
2562  control_pose.setSubvector(3, goal_pose_.subVector(3, 6));
2563  else if (mode == PixelControlMode::o)
2564  control_pose.setSubvector(0, goal_pose_.subVector(0, 2));
2565 
2566  std::vector<Vector> control_pt_from_pose = getControlPointsFromPose(control_pose);
2567 
2568  std::vector<Vector> control_px_from_pose;
2569  for (const Vector& v : control_pt_from_pose)
2570  control_px_from_pose.emplace_back(getControlPixelFromPoint(cam, v));
2571 
2572  return control_px_from_pose;
2573 }
2574 
2575 
2576 std::vector<Vector> VisualServoingServer::getControlPointsFromPose(const Vector& pose)
2577 {
2578  Vector ee_x = pose.subVector(0, 2);
2579  ee_x.push_back(1.0);
2580 
2581  Vector ee_o = pose.subVector(3, 6);
2582 
2583 
2584  Matrix H_ee_to_root = axis2dcm(ee_o);
2585  H_ee_to_root.setCol(3, ee_x);
2586 
2587 
2588  Vector p = zeros(4);
2589  std::vector<Vector> control_pt_from_pose;
2590 
2591  p(0) = 0;
2592  p(1) = -0.015;
2593  p(2) = 0;
2594  p(3) = 1.0;
2595  control_pt_from_pose.emplace_back(H_ee_to_root * p);
2596 
2597  p(0) = 0;
2598  p(1) = 0.015;
2599  p(2) = 0;
2600  p(3) = 1.0;
2601  control_pt_from_pose.emplace_back(H_ee_to_root * p);
2602 
2603  p(0) = -0.035;
2604  p(1) = 0.015;
2605  p(2) = 0;
2606  p(3) = 1.0;
2607  control_pt_from_pose.emplace_back(H_ee_to_root * p);
2608 
2609  p(0) = -0.035;
2610  p(1) = -0.015;
2611  p(2) = 0;
2612  p(3) = 1.0;
2613  control_pt_from_pose.emplace_back(H_ee_to_root * p);
2614 
2615 
2616  return control_pt_from_pose;
2617 }
2618 
2619 
2620 Vector VisualServoingServer::getPixelFromPoint(const CamSel& cam, const Vector& p) const
2621 {
2622  return getControlPixelFromPoint(cam, p).subVector(0, 1);
2623 }
2624 
2625 
2626 Vector VisualServoingServer::getControlPixelFromPoint(const CamSel& cam, const Vector& p) const
2627 {
2628  yAssert(cam == CamSel::left || cam == CamSel::right);
2629  yAssert(p.size() == 4);
2630 
2631 
2632  Vector px;
2633 
2634  if (cam == CamSel::left)
2635  px = l_H_r_to_cam_ * p;
2636  else if (cam == CamSel::right)
2637  px = r_H_r_to_cam_ * p;
2638 
2639  px[0] /= px[2];
2640  px[1] /= px[2];
2641 
2642  return px;
2643 }
2644 
2645 
2646 void VisualServoingServer::getCurrentStereoFeaturesAndJacobian(const std::vector<Vector>& left_px, const std::vector<Vector>& right_px,
2647  Vector& features, Matrix& jacobian)
2648 {
2649  yAssert(left_px.size() == right_px.size());
2650 
2651  if (features.length() != 16)
2652  features.resize(16);
2653 
2654  if (jacobian.rows() != 16 || jacobian.cols() != 6)
2655  jacobian.resize(16, 6);
2656 
2657 
2658  auto iter_left_px = left_px.cbegin();
2659  auto iter_right_px = right_px.cbegin();
2660  unsigned int offset = 0;
2661  while (iter_left_px != left_px.cend() && iter_right_px != right_px.cend())
2662  {
2663  const Vector& l_v = (*iter_left_px);
2664  const Vector& r_v = (*iter_right_px);
2665 
2666  /* FEATURES */
2667  features[4 * offset ] = l_v[0]; /* l_u_xi */
2668  features[4 * offset + 1] = r_v[0]; /* r_u_xi */
2669  features[4 * offset + 2] = l_v[1]; /* l_v_xi */
2670  features[4 * offset + 3] = r_v[1]; /* r_v_xi */
2671 
2672  /* JACOBIAN */
2673  jacobian.setRow(4 * offset, getJacobianU(CamSel::left, l_v));
2674  jacobian.setRow(4 * offset + 1, getJacobianU(CamSel::right, r_v));
2675  jacobian.setRow(4 * offset + 2, getJacobianV(CamSel::left, l_v));
2676  jacobian.setRow(4 * offset + 3, getJacobianV(CamSel::right, r_v));
2677 
2678  ++iter_left_px;
2679  ++iter_right_px;
2680  ++offset;
2681  }
2682 }
2683 
2684 
2685 Vector VisualServoingServer::getJacobianU(const CamSel& cam, const Vector& px)
2686 {
2687  Vector jacobian = zeros(6);
2688 
2689  if (cam == CamSel::left)
2690  {
2691  jacobian(0) = l_proj_(0, 0) / px(2);
2692  jacobian(2) = - (px(0) - l_proj_(0, 2)) / px(2);
2693  jacobian(3) = - ((px(0) - l_proj_(0, 2)) * (px(1) - l_proj_(1, 2))) / l_proj_(1, 1);
2694  jacobian(4) = (pow(l_proj_(0, 0), 2.0) + pow(px(0) - l_proj_(0, 2), 2.0)) / l_proj_(0, 0);
2695  jacobian(5) = - l_proj_(0, 0) / l_proj_(1, 1) * (px(1) - l_proj_(1, 2));
2696  }
2697  else if (cam == CamSel::right)
2698  {
2699  jacobian(0) = r_proj_(0, 0) / px(2);
2700  jacobian(2) = - (px(0) - r_proj_(0, 2)) / px(2);
2701  jacobian(3) = - ((px(0) - r_proj_(0, 2)) * (px(1) - r_proj_(1, 2))) / r_proj_(1, 1);
2702  jacobian(4) = (pow(r_proj_(0, 0), 2.0) + pow(px(0) - r_proj_(0, 2), 2.0)) / r_proj_(0, 0);
2703  jacobian(5) = - r_proj_(0, 0) / r_proj_(1, 1) * (px(1) - r_proj_(1, 2));
2704  }
2705 
2706  return jacobian;
2707 }
2708 
2709 
2710 Vector VisualServoingServer::getJacobianV(const CamSel& cam, const Vector& px)
2711 {
2712  Vector jacobian = zeros(6);
2713 
2714  if (cam == CamSel::left)
2715  {
2716  jacobian(1) = l_proj_(1, 1) / px(2);
2717  jacobian(2) = - (px(1) - l_proj_(1, 2)) / px(2);
2718  jacobian(3) = - (pow(l_proj_(1, 1), 2.0) + pow(px(1) - l_proj_(1, 2), 2.0)) / l_proj_(1, 1);
2719  jacobian(4) = ((px(0) - l_proj_(0, 2)) * (px(1) - l_proj_(1, 2))) / l_proj_(0, 0);
2720  jacobian(5) = l_proj_(1, 1) / l_proj_(0, 0) * (px(0) - l_proj_(0, 2));
2721  }
2722  else if (cam == CamSel::right)
2723  {
2724  jacobian(1) = r_proj_(1, 1) / px(2);
2725  jacobian(2) = - (px(1) - r_proj_(1, 2)) / px(2);
2726  jacobian(3) = - (pow(r_proj_(1, 1), 2.0) + pow(px(1) - r_proj_(1, 2), 2.0)) / r_proj_(1, 1);
2727  jacobian(4) = ((px(0) - r_proj_(0, 2)) * (px(1) - r_proj_(1, 2))) / r_proj_(0, 0);
2728  jacobian(5) = r_proj_(1, 1) / r_proj_(0, 0) * (px(0) - r_proj_(0, 2));
2729  }
2730 
2731  return jacobian;
2732 }
2733 
2734 
2736 {
2737  std::lock_guard<std::mutex> lock(mtx_H_eye_cam_);
2738 
2739  Vector left_eye_x;
2740  Vector left_eye_o;
2741  if (!itf_gaze_->getLeftEyePose(left_eye_x, left_eye_o))
2742  return false;
2743 
2744  Vector right_eye_x;
2745  Vector right_eye_o;
2746  if (!itf_gaze_->getRightEyePose(right_eye_x, right_eye_o))
2747  return false;
2748 
2749 
2750  l_H_eye_to_r_ = axis2dcm(left_eye_o);
2751  left_eye_x.push_back(1.0);
2752  l_H_eye_to_r_.setCol(3, left_eye_x);
2753  Matrix l_H_r_to_eye = SE3inv(l_H_eye_to_r_);
2754 
2755  r_H_eye_to_r_ = axis2dcm(right_eye_o);
2756  right_eye_x.push_back(1.0);
2757  r_H_eye_to_r_.setCol(3, right_eye_x);
2758  Matrix r_H_r_to_eye = SE3inv(r_H_eye_to_r_);
2759 
2760  l_H_r_to_cam_ = l_proj_ * l_H_r_to_eye;
2761  r_H_r_to_cam_ = r_proj_ * r_H_r_to_eye;
2762 
2763  return true;
2764 }
2765 
2766 
2767 bool VisualServoingServer::setPoseGoal(const yarp::sig::Vector& goal_x, const yarp::sig::Vector& goal_o)
2768 {
2769  goal_pose_.setSubvector(0, goal_x);
2770  goal_pose_.setSubvector(3, goal_o);
2771 
2772  return true;
2773 }
2774 
2775 
2776 bool VisualServoingServer::setPixelGoal(const std::vector<Vector>& l_px_goal, const std::vector<Vector>& r_px_goal)
2777 {
2778  std::lock_guard<std::mutex> lock(mtx_px_des_);
2779 
2780 
2781  l_px_goal_ = l_px_goal;
2782  r_px_goal_ = r_px_goal;
2783 
2784  for (unsigned int i = 0; i < l_px_goal_.size(); ++i)
2785  {
2786  px_des_[4 * i ] = l_px_goal_[i][0]; /* l_u_xi */
2787  px_des_[4 * i + 1] = r_px_goal_[i][0]; /* r_u_xi */
2788  px_des_[4 * i + 2] = l_px_goal_[i][1]; /* l_v_xi */
2789  px_des_[4 * i + 3] = r_px_goal_[i][1]; /* r_v_xi */
2790  }
2791 
2792  return true;
2793 }
2794 
2795 
2797 {
2798  yInfoVerbose("*** Started background process UpdateVisualServoingParamters ***");
2799 
2800  while (!is_stopping_backproc_update_vs_params)
2801  {
2802  Vector vec_x = goal_pose_.subVector(0, 2);
2803  Vector vec_o = goal_pose_.subVector(3, 6);
2804 
2805  std::vector<Vector> vec_px_l = getGoalPixelsFrom3DPose(vec_x, vec_o, CamSel::left);
2806  std::vector<Vector> vec_px_r = getGoalPixelsFrom3DPose(vec_x, vec_o, CamSel::right);
2807 
2808  if (vec_px_l.size() != 0 && vec_px_r.size() != 0)
2809  setPixelGoal(vec_px_l, vec_px_r);
2810  else
2811  yErrorVerbose("[BACKPROC] Could not update goal pixels from 3D pose.");
2812  }
2813 
2814  yInfoVerbose("*** Stopped background process UpdateVisualServoingParamters ***");
2815 }
2816 
2817 
2818 Vector VisualServoingServer::averagePose(const Vector& l_pose, const Vector& r_pose) const
2819 {
2820  Vector pose_out = zeros(7);
2821 
2822  pose_out.setSubvector(0, 0.5 * l_pose.subVector(0, 2) + 0.5 * r_pose.subVector(0, 2));
2823 
2824  pose_out.setSubvector(3, 0.5 * l_pose.subVector(3, 5) + 0.5 * r_pose.subVector(3, 5));
2825  pose_out.setSubvector(3, pose_out.subVector(3, 5) / norm(pose_out.subVector(3, 5)));
2826 
2827  float s_ang = 0.5 * std::sin(l_pose(6)) + 0.5 * std::sin(r_pose(6));
2828  float c_ang = 0.5 * std::cos(l_pose(6)) + 0.5 * std::cos(r_pose(6));
2829  pose_out(6) = std::atan2(s_ang, c_ang);
2830 
2831  return pose_out;
2832 }
2833 
2834 
2835 bool VisualServoingServer::checkVisualServoingStatus(const Vector& px_cur, const double tol)
2836 {
2837  yAssert(px_cur.size() == 16);
2838  yAssert(tol > 0);
2839 
2840  return ((std::abs(px_des_(0) - px_cur(0)) < tol) && (std::abs(px_des_(1) - px_cur(1)) < tol) && (std::abs(px_des_(2) - px_cur(2)) < tol) && (std::abs(px_des_(3) - px_cur(3)) < tol) &&
2841  (std::abs(px_des_(4) - px_cur(4)) < tol) && (std::abs(px_des_(5) - px_cur(5)) < tol) && (std::abs(px_des_(6) - px_cur(6)) < tol) && (std::abs(px_des_(7) - px_cur(7)) < tol) &&
2842  (std::abs(px_des_(8) - px_cur(8)) < tol) && (std::abs(px_des_(9) - px_cur(9)) < tol) && (std::abs(px_des_(10) - px_cur(10)) < tol) && (std::abs(px_des_(11) - px_cur(11)) < tol) &&
2843  (std::abs(px_des_(12) - px_cur(12)) < tol) && (std::abs(px_des_(13) - px_cur(13)) < tol) && (std::abs(px_des_(14) - px_cur(14)) < tol) && (std::abs(px_des_(15) - px_cur(15)) < tol));
2844 }
2845 
2846 
2847 bool VisualServoingServer::checkVisualServoingStatus(const Vector& pose_cur, const double tol_position, const double tol_orientation, const double tol_angle)
2848 {
2849  bool reached_position = (norm(pose_cur.subVector(0, 2) - goal_pose_.subVector(0, 2)) < tol_position);
2850 
2851  bool reached_axis = std::abs(std::acos(dot(pose_cur.subVector(3, 5), goal_pose_.subVector(3, 5)))) < tol_orientation;
2852 
2853  double ang = pose_cur(6) - goal_pose_(6);
2854  if (ang > M_PI) ang -= 2.0 * M_PI;
2855  else if (ang <= -M_PI) ang += 2.0 * M_PI;
2856 
2857  bool reached_angle = std::abs(ang) < tol_angle;
2858 
2859  return reached_position && reached_axis && reached_angle;
2860 }
2861 
2862 
2863 Vector VisualServoingServer::stdVectorOfVectorsToVector(const std::vector<Vector>& vectors)
2864 {
2865  Vector v;
2866 
2867  for (const Vector& yv : vectors)
2868  {
2869  v.push_back(yv[0]);
2870  v.push_back(yv[1]);
2871  }
2872 
2873  return v;
2874 }
bool checkVisualServoingStatus(const yarp::sig::Vector &px_cur, const double tol)
bool set_translation_gain(const double K_x_1, const double K_x_2) override
Set the translation gains of the visual servoing control algorithm.
bool set_max_translation_velocity(const double max_x_dot) override
Set the maximum translation velocity of the visual servoing control algorithm (same for each axis)...
bool initFacilities(const bool use_direct_kin) override
bool check_visual_servoing_controller() override
Check once whether the visual servoing controller is running or not.
bool setOrientationGain(const double K_x_1=1.5, const double K_x_2=0.375) override
bool stop_facilities() override
Stop and disconnect support modules and connections used for visual servoing.
std::vector< yarp::sig::Vector > get3DGoalPositionsFrom3DPose(const yarp::sig::Vector &x, const yarp::sig::Vector &o) override
void getCurrentStereoFeaturesAndJacobian(const std::vector< yarp::sig::Vector > &left_px, const std::vector< yarp::sig::Vector > &right_px, yarp::sig::Vector &features, yarp::sig::Matrix &jacobian)
bool getVisualServoingInfo(yarp::os::Bottle &info) override
bool set_orientation_gain(const double K_o_1, const double K_o_2) override
Set the orientation gains of the visual servoing control algorithm.
yarp::sig::Vector getJacobianU(const CamSel &cam, const yarp::sig::Vector &px)
bool setVisualServoControl(const std::string &control) override
bool storedInit(const std::string &label) override
bool reset_facilities() override
Reset support modules and connections to perform the current initialized visual servoing task...
bool set_modality(const std::string &mode) override
Set visual servoing operating mode between:
yarp::sig::Vector stdVectorOfVectorsToVector(const std::vector< yarp::sig::Vector > &vectors)
void afterStart(bool success) override
bool setOrientationGainSwitchTolerance(const double K_o_tol=30.0) override
bool waitVisualServoingDone(const double period=0.1, const double timeout=0.0) override
bool stored_init(const std::string &label) override
Initialize the robot to an initial position.
bool set_go_to_goal_tolerance(const double tol) override
Set visual servoing goal tolerance.
std::vector< std::string > get_visual_servoing_info() override
Return useful information for visual servoing.
bool stored_go_to_goal(const std::string &label) override
Set the robot visual servoing goal.
bool checkVisualServoingController() override
bool setPoseGoal(const yarp::sig::Vector &goal_x, const yarp::sig::Vector &goal_o)
bool set_translation_gain_switch_tolerance(const double K_x_tol) override
Set the tolerance, in pixels, at which the translation control law swithces its gain value...
bool set_orientation_gain_switch_tolerance(const double K_o_tol) override
Set the tolerance, in pixels, at which the orientation control law swithces its gain value...
std::vector< yarp::sig::Vector > getGoalPixelsFrom3DPose(const yarp::sig::Vector &x, const yarp::sig::Vector &o, const CamSel &cam) override
bool setTranslationGainSwitchTolerance(const double K_x_tol=30.0) override
yarp::sig::Vector getJacobianV(const CamSel &cam, const yarp::sig::Vector &px)
bool stop_controller() override
Ask for an immediate stop of the visual servoing controller.
std::vector< std::vector< double > > get_3D_goal_positions_from_3D_pose(const std::vector< double > &x, const std::vector< double > &o) override
Helper function: extract four Cartesian points lying on the plane defined by the frame o in the posit...
yarp::sig::Vector getControlPixelFromPoint(const CamSel &cam, const yarp::sig::Vector &p) const
std::vector< yarp::sig::Vector > getPixelsFromPose(const yarp::sig::Vector &pose, const CamSel &cam)
std::vector< std::vector< double > > get_goal_pixels_from_3D_pose(const std::vector< double > &x, const std::vector< double > &o, const std::string &cam) override
Helper function: extract four 2D pixel points lying on the plane defined by the frame o in the positi...
bool setGoToGoalTolerance(const double tol=15.0) override
bool setTranslationGain(const double K_x_1=1.0, const double K_x_2=0.25) override
bool setPixelGoal(const std::vector< yarp::sig::Vector > &l_px_goal, const std::vector< yarp::sig::Vector > &r_px_goal)
bool set_visual_servo_control(const std::string &control) override
Set visual servo control law between:
std::vector< yarp::sig::Vector > getControlPixelsFromPose(const yarp::sig::Vector &pose, const CamSel &cam, const PixelControlMode &mode)
bool go_to_pose_goal(const std::vector< double > &vec_x, const std::vector< double > &vec_o) override
Set the goal point (3D for the position + 4D axis-angle for the orientation) and start visual servoin...
bool setModality(const std::string &mode) override
bool init_facilities(const bool use_direct_kin) override
Initialize support modules and connections to perform a visual servoing task.
bool goToGoal(const yarp::sig::Vector &vec_x, const yarp::sig::Vector &vec_o) override
bool go_to_px_goal(const std::vector< std::vector< double >> &vec_px_l, const std::vector< std::vector< double >> &vec_px_r) override
yarp::sig::Vector getPixelFromPoint(const CamSel &cam, const yarp::sig::Vector &p) const
bool setControlPoint(const yarp::os::ConstString &point) override
bool quit() override
Gently close the visual servoing device, deallocating resources.
bool wait_visual_servoing_done(const double period, const double timeout) override
Wait until visual servoing reaches the goal.
yarp::sig::Vector averagePose(const yarp::sig::Vector &l_pose, const yarp::sig::Vector &r_pose) const
bool get_goal_from_sfm() override
Get goal point from SFM module.
bool storedGoToGoal(const std::string &label) override
bool setMaxOrientationVelocity(const double max_o_dot) override
bool set_control_point(const std::string &point) override
Set the point controlled during visual servoing.
bool set_max_orientation_velocity(const double max_o_dot) override
Set the maximum angular velocity of the axis-angle velocity vector of the visual servoing control alg...
bool open(yarp::os::Searchable &config) override
std::vector< yarp::sig::Vector > getControlPointsFromPose(const yarp::sig::Vector &pose)
bool setMaxTranslationVelocity(const double max_x_dot) override