iCub-main
Loading...
Searching...
No Matches
controller.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 RobotCub Consortium, European Commission FP6 Project IST-004370
3 * Author: Ugo Pattacini, Alessandro Roncone
4 * email: ugo.pattacini@iit.it, alessandro.roncone@iit.it
5 * website: www.robotcub.org
6 * Permission is granted to copy, distribute, and/or modify this program
7 * under the terms of the GNU General Public License, version 2 or any
8 * later version published by the Free Software Foundation.
9 *
10 * A copy of the license can be found at
11 * http://www.robotcub.org/icub/license/gpl.txt
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details
17*/
18
19#include <limits>
20#include <cstdio>
21#include <sstream>
22
23#include <iCub/solver.h>
24#include <iCub/controller.h>
25
26
27/************************************************************************/
28Controller::Controller(PolyDriver *_drvTorso, PolyDriver *_drvHead, ExchangeData *_commData,
29 const double _neckTime, const double _eyesTime, const double _min_abs_vel,
30 const unsigned int _period) :
31 PeriodicThread((double)_period/1000.0), drvTorso(_drvTorso), drvHead(_drvHead),
32 commData(_commData), neckTime(_neckTime), eyesTime(_eyesTime),
33 min_abs_vel(_min_abs_vel), period(_period), Ts(_period/1000.0),
34 printAccTime(0.0)
35{
36 // Instantiate objects
41
42 // remove constraints on the links: logging purpose
43 imu->setAllConstraints(false);
44
45 // release links
49
50 // Get the chain objects
54
55 // add aligning matrices read from configuration file
56 getAlignHN(commData->rf_cameras,"ALIGN_KIN_LEFT",eyeL->asChain());
57 getAlignHN(commData->rf_cameras,"ALIGN_KIN_RIGHT",eyeR->asChain());
58
59 // overwrite aligning matrices iff specified through tweak values
61 {
62 getAlignHN(commData->rf_tweak,"ALIGN_KIN_LEFT",eyeL->asChain());
63 getAlignHN(commData->rf_tweak,"ALIGN_KIN_RIGHT",eyeR->asChain());
64 }
65
66 // read number of joints
67 if (drvTorso!=nullptr)
68 {
69 IEncoders *encTorso; drvTorso->view(encTorso);
70 encTorso->getAxes(&nJointsTorso);
71 }
72 else
74
75 IEncoders *encHead; drvHead->view(encHead);
76 encHead->getAxes(&nJointsHead);
77
78 drvHead->view(modHead);
79 drvHead->view(posHead);
80 drvHead->view(velHead);
81
82 // if requested check if position control is available
84 {
86 yInfo("### neck control - requested POSITION mode: IPositionDirect [%s] => %s mode selected",
87 commData->neckPosCtrlOn?"available":"not available",commData->neckPosCtrlOn?"POSITION":"VELOCITY");
88 }
89 else
90 yInfo("### neck control - requested VELOCITY mode => VELOCITY mode selected");
91
92 // joints bounds alignment
94
95 // read starting position
96 fbTorso.resize(nJointsTorso,0.0);
97 fbHead.resize(nJointsHead,0.0);
98
99 // exclude acceleration constraints by fixing
100 // thresholds at high values
101 Vector a_robHead(nJointsHead,std::numeric_limits<double>::max());
102 velHead->setRefAccelerations(a_robHead.data());
103
106
107 // find minimum allowed vergence
110
111 // reinforce vergence min bound
114
115 fbNeck=fbHead.subVector(0,2);
116 fbEyes=fbHead.subVector(3,5);
117 qdNeck.resize(3,0.0); qdEyes.resize(3,0.0);
118 vNeck.resize(3,0.0); vEyes.resize(3,0.0);
119 v.resize(nJointsHead,0.0);
120
121 // Set the task execution time
124
128 IntPlan=new Integrator(Ts,fbNeck,lim.submatrix(0,2,0,1));
129 IntStabilizer=new Integrator(Ts,zeros((int)vNeck.length()));
130
131 neckJoints.resize(3);
132 eyesJoints.resize(3);
133 neckJoints[0]=0;
134 neckJoints[1]=1;
135 neckJoints[2]=2;
136 eyesJoints[0]=3;
137 eyesJoints[1]=4;
138 eyesJoints[2]=5;
139
140 qd=fbHead;
141 q0=qd;
144
147 pathPerc=0.0;
148
149 unplugCtrlEyes=false;
150 ctrlInhibited=false;
151 motionDone=true;
152 reliableGyro=true;
153 stabilizeGaze=false;
154}
155
156
157/************************************************************************/
159{
160 delete neck;
161 delete eyeL;
162 delete eyeR;
163 delete imu;
164 delete mjCtrlNeck;
165 delete mjCtrlEyes;
166 delete IntState;
167 delete IntPlan;
168 delete IntStabilizer;
169}
170
171
172/************************************************************************/
174{
175 iKinChain cl(*chainEyeL), cr(*chainEyeR);
176 cl.setAng(zeros(cl.getDOF()));
177 cr.setAng(zeros(cl.getDOF()));
178
179 double minVer=startupMinVer;
180 double maxVer=lim(nJointsHead-1,1);
181 for (double ver=minVer; ver<maxVer; ver+=0.5*CTRL_DEG2RAD)
182 {
183 cl(cl.getDOF()-1).setAng(ver/2.0);
184 cr(cr.getDOF()-1).setAng(-ver/2.0);
185
186 Vector fp;
188 {
189 // impose homogeneous coordinates
190 fp.push_back(1.0);
191
192 // if the component along eye's z-axis is positive
193 // then this means that the fixation point is ok,
194 // being in front of the robot
195 Vector fpe=SE3inv(cl.getH())*fp;
196 if (fpe[2]>0.0)
197 {
198 minVer=ver;
199 break;
200 }
201 }
202 }
203
204 yInfo("### computed minimum allowed vergence = %g [deg]",minVer*CTRL_RAD2DEG);
206}
207
208
209/************************************************************************/
215
216
217/************************************************************************/
218void Controller::notifyEvent(const string &event, const double checkPoint)
219{
220 if (port_event.getOutputCount()>0)
221 {
222 Bottle &ev=port_event.prepare();
223 ev.clear();
224
225 ev.addString(event);
226 ev.addFloat64(q_stamp);
227 if (checkPoint>=0.0)
228 ev.addFloat64(checkPoint);
229
230 txInfo_event.update(q_stamp);
231 port_event.setEnvelope(txInfo_event);
232 port_event.writeStrict();
233 }
234}
235
236
237/************************************************************************/
239{
240 if (!motionOngoingEventsCurrent.empty())
241 {
242 double curCheckPoint=*motionOngoingEventsCurrent.begin();
243 if (pathPerc>=curCheckPoint)
244 {
245 notifyEvent("motion-ongoing",curCheckPoint);
246 motionOngoingEventsCurrent.erase(curCheckPoint);
247 }
248 }
249}
250
251
252/************************************************************************/
254{
255 while (!motionOngoingEventsCurrent.empty())
256 {
257 double curCheckPoint=*motionOngoingEventsCurrent.begin();
258 notifyEvent("motion-ongoing",curCheckPoint);
259 motionOngoingEventsCurrent.erase(curCheckPoint);
260 }
261}
262
263
264/************************************************************************/
265void Controller::stopLimb(const bool execStopPosition)
266{
268 {
269 if (execStopPosition)
270 posHead->stop((int)neckJoints.size(),neckJoints.data());
271
272 // note: vel==0.0 is always achievable
273 velHead->velocityMove((int)eyesJoints.size(),eyesJoints.data(),
274 Vector(eyesJoints.size(),0.0).data());
275 }
276 else
277 velHead->velocityMove(Vector(nJointsHead,0.0).data());
278
279 if (commData->debugInfoEnabled && (port_debug.getOutputCount()>0))
280 {
281 Bottle info;
282 int j=0;
283
285 {
286 if (execStopPosition)
287 {
288 for (auto neckJoint : neckJoints)
289 {
290 ostringstream ss;
291 ss<<"pos_"<<neckJoint;
292 info.addString(ss.str());
293 info.addString("stop");
294 }
295 }
296
297 j=eyesJoints[0];
298 }
299
300 for (int i=j; i<nJointsHead; i++)
301 {
302 ostringstream ss;
303 ss<<"vel_"<<i;
304 info.addString(ss.str());
305 info.addFloat64(0.0);
306 }
307
308 port_debug.prepare()=info;
309 txInfo_debug.update(q_stamp);
310 port_debug.setEnvelope(txInfo_debug);
311 port_debug.writeStrict();
312 }
313
314 commData->ctrlActive=false;
315 motionDone=true;
316 cv_eventLook.notify_all();
317}
318
319
320/************************************************************************/
322{
323 lock_guard<mutex> lg(mutexRun);
325}
326
327
328/************************************************************************/
330{
331 lock_guard<mutex> lg(mutexCtrl);
332 if (commData->ctrlActive)
333 {
334 q_stamp=Time::now();
335 ctrlInhibited=true;
336 stopLimb();
337 notifyEvent("motion-done");
338 }
339}
340
341
342/************************************************************************/
343void Controller::printIter(Vector &xd, Vector &fp, Vector &qd, Vector &q,
344 Vector &v, double printTime)
345{
346 if ((printAccTime+=Ts)>=printTime)
347 {
348 printAccTime=0.0;
349
350 printf("norm(e) = %g\n",norm(xd-fp));
351 printf("Target fix. point = %s\n",xd.toString().c_str());
352 printf("Actual fix. point = %s\n",fp.toString().c_str());
353 printf("Target Joints = %s\n",qd.toString().c_str());
354 printf("Actual Joints = %s\n",q.toString().c_str());
355 printf("Velocity = %s\n",v.toString().c_str());
356 printf("\n");
357 }
358}
359
360
361/************************************************************************/
363{
364 port_x.open(commData->localStemName+"/x:o");
365 port_q.open(commData->localStemName+"/q:o");
366 port_event.open(commData->localStemName+"/events:o");
367
369 port_debug.open(commData->localStemName+"/dbg:o");
370
371 yInfo("Starting Controller at %d ms",period);
372 q_stamp=Time::now();
373
374 return true;
375}
376
377
378/************************************************************************/
380{
381 stopLimb();
382 notifyEvent("closing");
383
384 port_x.interrupt();
385 port_x.close();
386
387 port_q.interrupt();
388 port_q.close();
389
390 port_event.interrupt();
391 port_event.close();
392
394 {
395 port_debug.interrupt();
396 port_debug.close();
397 }
398}
399
400
401/************************************************************************/
403{
404 if (s)
405 yInfo("Controller started successfully");
406 else
407 yError("Controller did not start!");
408}
409
410
411/************************************************************************/
412Vector Controller::computedxFP(const Matrix &H, const Vector &v,
413 const Vector &w, const Vector &x_FP)
414{
415 Matrix H_=H;
416 Vector w_=w;
417 w_.push_back(1.0);
418
419 H_(0,3)=x_FP[0]-H_(0,3);
420 H_(1,3)=x_FP[1]-H_(1,3);
421 H_(2,3)=x_FP[2]-H_(2,3);
422 Vector dx_FP_pos=v+(w_[0]*cross(H_,0,H_,3)+
423 w_[1]*cross(H_,1,H_,3)+
424 w_[2]*cross(H_,2,H_,3));
425
426 H_(0,3)=H_(1,3)=H_(2,3)=0.0;
427 Vector dx_FP_rot=H_*w_;
428 dx_FP_rot.pop_back();
429
430 return cat(dx_FP_pos,dx_FP_rot);
431}
432
433
434/************************************************************************/
435Vector Controller::computeNeckVelFromdxFP(const Vector &fp, const Vector &dfp)
436{
437 // convert fp from root to the neck reference frame
438 Vector fpR=fp;
439 fpR.push_back(1.0);
440 Vector fpE=SE3inv(chainNeck->getH())*fpR;
441
442 // compute the Jacobian of the head joints alone
443 // (by adding the new fixation point beforehand)
444 Matrix HN=eye(4,4);
445 HN(0,3)=fpE[0];
446 HN(1,3)=fpE[1];
447 HN(2,3)=fpE[2];
448
449 mutexChain.lock();
450 chainNeck->setHN(HN);
451 Matrix JN=chainNeck->GeoJacobian();
452 chainNeck->setHN(eye(4,4));
453 mutexChain.unlock();
454
455 // take only the last three rows of the Jacobian
456 // belonging to the head joints
457 Matrix JNp=JN.submatrix(3,5,3,5);
458
459 return pinv(JNp)*dfp.subVector(3,5);
460}
461
462
463/************************************************************************/
464Vector Controller::computeEyesVelFromdxFP(const Vector &dfp)
465{
466 Matrix eyesJ; Vector tmp;
469 return pinv(eyesJ)*dfp.subVector(0,2);
470 else
471 return zeros((int)vEyes.length());
472}
473
474
475/************************************************************************/
476void Controller::doSaccade(const Vector &ang, const Vector &vel)
477{
478 lock_guard<mutex> lg(mutexCtrl);
479 if (ctrlInhibited)
480 return;
481
483
484 // enforce joints bounds
485 Vector ang_(3);
486 ang_[0]=CTRL_RAD2DEG*sat(ang[0],lim(eyesJoints[0],0),lim(eyesJoints[0],1));
487 ang_[1]=CTRL_RAD2DEG*sat(ang[1],lim(eyesJoints[1],0),lim(eyesJoints[1],1));
488 ang_[2]=CTRL_RAD2DEG*sat(ang[2],lim(eyesJoints[2],0),lim(eyesJoints[2],1));
489
490 posHead->setRefSpeeds((int)eyesJoints.size(),eyesJoints.data(),vel.data());
491 posHead->positionMove((int)eyesJoints.size(),eyesJoints.data(),ang_.data());
492
493 if (commData->debugInfoEnabled && (port_debug.getOutputCount()>0))
494 {
495 Bottle info;
496 for (size_t i=0; i<ang_.length(); i++)
497 {
498 ostringstream ss;
499 ss<<"pos_"<<eyesJoints[i];
500 info.addString(ss.str());
501 info.addFloat64(ang_[i]);
502 }
503
504 port_debug.prepare()=info;
505 txInfo_debug.update(q_stamp);
506 port_debug.setEnvelope(txInfo_debug);
507 port_debug.writeStrict();
508 }
509
510 saccadeStartTime=Time::now();
512 unplugCtrlEyes=true;
513
514 notifyEvent("saccade-onset");
515}
516
517
518/************************************************************************/
519bool Controller::look(const Vector &x)
520{
521 lock_guard<mutex> lg(mutexLook);
522
523 mutexRun.lock();
524 bool ret=commData->port_xd->set_xd(x);
525 mutexRun.unlock();
526
527 if (ret)
528 {
529 unique_lock<mutex> lck(mtx_eventLook);
530 cv_eventLook.wait(lck);
531 }
532
533 return ret;
534}
535
536
537/************************************************************************/
539{
540 lock_guard<mutex> lg(mutexCtrl);
541 mjCtrlEyes->reset(zeros((int)fbEyes.length()));
542 unplugCtrlEyes=false;
543}
544
545
546/************************************************************************/
548{
549 vector<int> modes(nJointsHead);
550 modHead->getControlModes(modes.data());
551
552 jointsToSet.clear();
553 for (int i=0; i<(int)modes.size(); i++)
554 {
555 if ((modes[i]==VOCAB_CM_HW_FAULT) || (modes[i]==VOCAB_CM_IDLE))
556 return false;
557 else if (i<eyesJoints[0])
558 {
560 {
561 if (modes[i]!=VOCAB_CM_POSITION_DIRECT)
562 jointsToSet.push_back(i);
563 }
564 else if (modes[i]!=VOCAB_CM_VELOCITY)
565 jointsToSet.push_back(i);
566 }
567 else if (modes[i]!=VOCAB_CM_MIXED)
568 jointsToSet.push_back(i);
569 }
570
571 return true;
572}
573
574
575/************************************************************************/
577{
578 if (jointsToSet.empty())
579 return;
580
581 vector<int> modes;
582 for (auto i : jointsToSet)
583 {
584 if (i<eyesJoints[0])
585 {
587 modes.push_back(VOCAB_CM_POSITION_DIRECT);
588 else
589 modes.push_back(VOCAB_CM_VELOCITY);
590 }
591 else
592 modes.push_back(VOCAB_CM_MIXED);
593 }
594
595 modHead->setControlModes((int)jointsToSet.size(),jointsToSet.data(),modes.data());
596}
597
598
599/************************************************************************/
601{
603 {
604 if (stabilizeGaze!=f)
605 {
606 lock_guard<mutex> lg(mutexRun);
607 if (f)
608 {
609 if (!commData->ctrlActive)
610 {
612 IntStabilizer->reset(zeros((int)vNeck.length()));
613 }
614 notifyEvent("stabilization-on");
615 }
616 else
617 {
618 lock_guard<mutex> lg(mutexCtrl);
619 q_stamp=Time::now();
620 stopLimb();
621 notifyEvent("stabilization-off");
622 }
623
625 }
626
627 return true;
628 }
629 else
630 return false;
631}
632
633
634/************************************************************************/
636{
637 return stabilizeGaze;
638}
639
640
641/************************************************************************/
643{
644 lock_guard<mutex> lg(mutexRun);
645
646 mutexCtrl.lock();
647 bool jointsHealthy=areJointsHealthyAndSet();
648 mutexCtrl.unlock();
649
650 if (!jointsHealthy)
651 {
653 commData->port_xd->get_new()=false;
654 cv_eventLook.notify_all();
655 }
656
657 string event="none";
658
659 // verify if any saccade is still underway
660 mutexCtrl.lock();
661 if (commData->saccadeUnderway && (Time::now()-saccadeStartTime>=Ts))
662 {
663 bool done;
664 posHead->checkMotionDone((int)eyesJoints.size(),eyesJoints.data(),&done);
666
668 notifyEvent("saccade-done");
669 }
670 mutexCtrl.unlock();
671
672 // get data
673 double x_stamp;
674 Vector xd=commData->get_xd();
675 Vector x=commData->get_x(x_stamp);
676 qd=commData->get_qd();
677
678 // read feedbacks
679 q_stamp=Time::now();
681 {
682 yError("Communication timeout detected!");
683 notifyEvent("comm-timeout");
684 suspend();
685 return;
686 }
687
688 // update pose information
689 {
690 mutexChain.lock();
691 for (int i=0; i<nJointsTorso; i++)
692 {
693 chainNeck->setAng(i,fbTorso[i]);
694 chainEyeL->setAng(i,fbTorso[i]);
695 chainEyeR->setAng(i,fbTorso[i]);
696 }
697 for (int i=0; i<3; i++)
698 {
702 }
703
708
709 txInfo_pose.update(q_stamp);
710 mutexChain.unlock();
711 }
712
714
715 fbNeck=fbHead.subVector(0,2);
716 fbEyes=fbHead.subVector(3,5);
717
718 double errNeck=norm(qd.subVector(0,2)-fbNeck);
719 double errEyes=norm(qd.subVector(3,(unsigned int)qd.length()-1)-fbEyes);
720 bool swOffCond=(Time::now()-ctrlActiveRisingEdgeTime<GAZECTRL_SWOFFCOND_DISABLESLOT*getPeriod()) ? false :
724
725 // verify control switching conditions
726 if (commData->ctrlActive)
727 {
728 // manage new target while controller is active
729 if (commData->port_xd->get_new())
730 {
731 reliableGyro=true;
732
733 event="motion-onset";
734
735 mutexData.lock();
737 mutexData.unlock();
738
739 ctrlActiveRisingEdgeTime=Time::now();
740 commData->port_xd->get_new()=false;
741 }
742 // switch-off condition
743 else if (swOffCond)
744 {
746 {
747 if (!motionDone)
748 event="motion-done";
749 motionDone=true;
750 }
751 else
752 {
753 event="motion-done";
754 mutexCtrl.lock();
755 stopLimb(false);
756 mutexCtrl.unlock();
757 }
758 }
759 }
760 else if (jointsHealthy)
761 {
762 // inhibition is cleared upon new target arrival
763 if (ctrlInhibited)
765
766 // switch-on condition
768
769 // reset controllers
770 if (commData->ctrlActive)
771 {
772 ctrlActiveRisingEdgeTime=Time::now();
773 commData->port_xd->get_new()=false;
775
776 if (stabilizeGaze)
777 {
780 }
781 else
782 {
783 mjCtrlNeck->reset(zeros((int)fbNeck.length()));
784 mjCtrlEyes->reset(zeros((int)fbEyes.length()));
785 IntStabilizer->reset(zeros((int)vNeck.length()));
787 }
788
789 reliableGyro=true;
790
791 event="motion-onset";
792
793 mutexData.lock();
795 mutexData.unlock();
796 }
797 }
798
799 mutexCtrl.lock();
800 if (event=="motion-onset")
801 {
803 jointsToSet.clear();
804 motionDone=false;
805 q0=fbHead;
806 cv_eventLook.notify_all();
807 }
808 mutexCtrl.unlock();
809
811 {
812 mutexCtrl.lock();
814 mutexCtrl.unlock();
815 }
816
817 qdNeck=qd.subVector(0,2);
818 qdEyes=qd.subVector(3,5);
819
820 // compute current point [%] in the path
821 double dist=norm(qd-q0);
822 pathPerc=(dist>IKIN_ALMOST_ZERO)?norm(fbHead-q0)/dist:1.0;
823 pathPerc=sat(pathPerc,0.0,1.0);
824
825 if (commData->ctrlActive)
826 {
827 // control
829
830 if (unplugCtrlEyes)
831 {
832 if (Time::now()-saccadeStartTime>=Ts)
834 }
835 else
837
838 // stabilization
840 {
841 auto resGyro =commData->get_gyro();
842 Vector gyro{resGyro.first};
843 bool statusGyro = resGyro.second;
844
845 if (statusGyro) {
846 Vector dx=computedxFP(imu->getH(cat(fbTorso,fbNeck)),zeros((int)fbNeck.length()),gyro,x);
847 Vector imuNeck=computeNeckVelFromdxFP(x,dx);
848 if (reliableGyro)
849 {
851
852 // only if the speed is low and we are close to the target
854 reliableGyro=false;
855 }
856 // hysteresis
857 else if ((norm(imuNeck)>1.5*commData->gyro_noise_threshold) || (pathPerc<0.9))
858 {
859 IntStabilizer->reset(zeros((int)vNeck.length()));
860 reliableGyro=true;
861 }
862 }
863 }
864
866 }
867 else if (stabilizeGaze)
868 {
869 auto resGyro =commData->get_gyro();
870 Vector gyro{resGyro.first};
871 bool statusGyro = resGyro.second;
872 if (statusGyro) {
873 Vector dx = computedxFP(imu->getH(cat(fbTorso, fbNeck)), zeros((int) fbNeck.length()), gyro, x);
874 Vector imuNeck = computeNeckVelFromdxFP(x, dx);
875
878 }
880 }
881 else
882 {
883 vNeck=0.0;
884 vEyes=0.0;
885 }
886
887 v.setSubvector(0,vNeck);
888 v.setSubvector(3,vEyes);
889
890 // apply bang-bang just in case to compensate
891 // for unachievable low velocities
892 for (size_t i=0; i<v.length(); i++)
893 if ((v[i]!=0.0) && (v[i]>-min_abs_vel) && (v[i]<min_abs_vel))
894 v[i]=yarp::math::sign(qd[i]-fbHead[i])*min_abs_vel;
895
896 // convert to degrees
897 mutexData.lock();
901 mutexData.unlock();
902
903 // send commands to the robot
905 {
906 mutexCtrl.lock();
907
908 Vector posdeg;
910 {
911 posdeg=(CTRL_RAD2DEG)*IntPlan->get();
912 posNeck->setPositions((int)neckJoints.size(),neckJoints.data(),posdeg.data());
913 velHead->velocityMove((int)eyesJoints.size(),eyesJoints.data(),vdeg.subVector(3,5).data());
914 }
915 else
916 velHead->velocityMove(vdeg.data());
917
918 if (commData->debugInfoEnabled && (port_debug.getOutputCount()>0))
919 {
920 Bottle info;
921 int j=0;
922
924 {
925 for (size_t i=0; i<posdeg.length(); i++)
926 {
927 ostringstream ss;
928 ss<<"pos_"<<i;
929 info.addString(ss.str());
930 info.addFloat64(posdeg[i]);
931 }
932
933 j=eyesJoints[0];
934 }
935
936 for (size_t i=j; i<vdeg.length(); i++)
937 {
938 ostringstream ss;
939 ss<<"vel_"<<i;
940 info.addString(ss.str());
941 info.addFloat64(vdeg[i]);
942 }
943
944 port_debug.prepare()=info;
945 txInfo_debug.update(q_stamp);
946 port_debug.setEnvelope(txInfo_debug);
947 port_debug.writeStrict();
948 }
949
950 mutexCtrl.unlock();
951 }
952
953 // print info
954 if (commData->verbose)
955 printIter(xd,x,qddeg,qdeg,vdeg,1.0);
956
957 // send x,q through YARP ports
958 Vector q(nJointsTorso+nJointsHead);
959 int j;
960 for (j=0; j<nJointsTorso; j++)
961 q[j]=CTRL_RAD2DEG*fbTorso[j];
962 for (; (size_t)j<q.length(); j++)
963 q[j]=qdeg[j-nJointsTorso];
964
965 txInfo_x.update(x_stamp);
966 if (port_x.getOutputCount()>0)
967 {
968 port_x.prepare()=x;
969 port_x.setEnvelope(txInfo_x);
970 port_x.write();
971 }
972
973 txInfo_q.update(q_stamp);
974 if (port_q.getOutputCount()>0)
975 {
976 port_q.prepare()=q;
977 port_q.setEnvelope(txInfo_q);
978 port_q.write();
979 }
980
981 if (event=="motion-onset")
982 notifyEvent(event);
983
985
986 if (event=="motion-done")
987 {
989 notifyEvent(event);
990 }
991
992 // update joints angles
996 commData->set_v(v);
997}
998
999
1000/************************************************************************/
1002{
1003 lock_guard<mutex> lg(mutexCtrl);
1004 PeriodicThread::suspend();
1005 stopLimb();
1006 commData->saccadeUnderway=false;
1007 yInfo("Controller has been suspended!");
1008 notifyEvent("suspended");
1009}
1010
1011
1012/************************************************************************/
1014{
1016 fbNeck=fbHead.subVector(0,2);
1017 fbEyes=fbHead.subVector(3,5);
1018
1019 PeriodicThread::resume();
1020 yInfo("Controller has been resumed!");
1021 notifyEvent("resumed");
1022}
1023
1024
1025/************************************************************************/
1027{
1028 return neckTime;
1029}
1030
1031
1032/************************************************************************/
1034{
1035 return eyesTime;
1036}
1037
1038
1039/************************************************************************/
1040void Controller::setTneck(const double execTime)
1041{
1042 double lowerThresNeck=eyesTime+0.2;
1043 if (execTime<lowerThresNeck)
1044 {
1045 yWarning("neck execution time is under the lower bound!");
1046 yWarning("a new neck execution time of %g s is chosen",lowerThresNeck);
1047 neckTime=lowerThresNeck;
1048 }
1049 else
1050 neckTime=execTime;
1051}
1052
1053
1054/************************************************************************/
1055void Controller::setTeyes(const double execTime)
1056{
1057 double lowerThresEyes=10.0*Ts;
1058 if (execTime<lowerThresEyes)
1059 {
1060 yWarning("eyes execution time is under the lower bound!");
1061 yWarning("a new eyes execution time of %g s is chosen",lowerThresEyes);
1062 eyesTime=lowerThresEyes;
1063 }
1064 else
1065 eyesTime=execTime;
1066
1067 // to realign neck time
1069}
1070
1071
1072/************************************************************************/
1074{
1075 lock_guard<mutex> lg(mutexRun);
1076 return motionDone;
1077}
1078
1079
1080/************************************************************************/
1082{
1084 {
1085 if (f)
1086 look(commData->get_x());
1087
1088 lock_guard<mutex> lg(mutexRun);
1090 yInfo("tracking mode set to %s",
1091 commData->trackingModeOn?"on":"off");
1092 }
1093}
1094
1095
1096/************************************************************************/
1098{
1099 return commData->trackingModeOn;
1100}
1101
1102
1103/************************************************************************/
1104bool Controller::getDesired(Vector &des)
1105{
1106 lock_guard<mutex> lg(mutexData);
1107 des=qddeg;
1108 return true;
1109}
1110
1111
1112/************************************************************************/
1114{
1115 lock_guard<mutex> lg(mutexData);
1116 vel=vdeg;
1117 return true;
1118}
1119
1120
1121/************************************************************************/
1122bool Controller::getPose(const string &poseSel, Vector &x, Stamp &stamp)
1123{
1124 lock_guard<mutex> lg(mutexChain);
1125 if (poseSel=="left")
1126 {
1128 stamp=txInfo_pose;
1129 return true;
1130 }
1131 else if (poseSel=="right")
1132 {
1134 stamp=txInfo_pose;
1135 return true;
1136 }
1137 else if (poseSel=="head")
1138 {
1140 stamp=txInfo_pose;
1141 return true;
1142 }
1143 else
1144 return false;
1145}
1146
1147
1148/************************************************************************/
1149bool Controller::registerMotionOngoingEvent(const double checkPoint)
1150{
1151 lock_guard<mutex> lg(mutexData);
1152 if ((checkPoint>=0.0) && (checkPoint<=1.0))
1153 {
1154 motionOngoingEvents.insert(checkPoint);
1155 return true;
1156 }
1157 else
1158 return false;
1159}
1160
1161
1162/************************************************************************/
1163bool Controller::unregisterMotionOngoingEvent(const double checkPoint)
1164{
1165 lock_guard<mutex> lg(mutexData);
1166
1167 bool ret=false;
1168 if ((checkPoint>=0.0) && (checkPoint<=1.0))
1169 {
1170 auto itr=motionOngoingEvents.find(checkPoint);
1171 if (itr!=motionOngoingEvents.end())
1172 {
1173 motionOngoingEvents.erase(itr);
1174 ret=true;
1175 }
1176 }
1177
1178 return ret;
1179}
1180
1181
1182/************************************************************************/
1184{
1185 lock_guard<mutex> lg(mutexData);
1186
1187 Bottle events;
1188 for (auto motionOngoingEvent : motionOngoingEvents)
1189 events.addFloat64(motionOngoingEvent);
1190
1191 return events;
1192}
1193
1194
@ data
bool unregisterMotionOngoingEvent(const double checkPoint)
iCubInertialSensor * imu
Definition controller.h:57
mutex mtx_eventLook
Definition controller.h:87
void stopControlHelper()
iKinChain * chainNeck
Definition controller.h:58
virtual ~Controller()
void stopLimb(const bool execStopPosition=true)
double eyesTime
Definition controller.h:101
Vector vNeck
Definition controller.h:110
bool setGazeStabilization(const bool f)
void setJointsCtrlMode()
BufferedPort< Bottle > port_event
Definition controller.h:74
double saccadeStartTime
Definition controller.h:98
bool getPose(const string &poseSel, Vector &x, Stamp &stamp)
double getTeyes() const
mutex mutexRun
Definition controller.h:82
void afterStart(bool s) override
bool reliableGyro
Definition controller.h:93
iKinChain * chainEyeR
Definition controller.h:58
void threadRelease() override
Vector qdEyes
Definition controller.h:111
Vector computedxFP(const Matrix &H, const Vector &v, const Vector &w, const Vector &x_FP)
void printIter(Vector &xd, Vector &fp, Vector &qd, Vector &q, Vector &v, double printTime)
double printAccTime
Definition controller.h:99
PolyDriver * drvHead
Definition controller.h:59
vector< int > neckJoints
Definition controller.h:113
void stopControl()
int nJointsHead
Definition controller.h:96
mutex mutexChain
Definition controller.h:83
minJerkVelCtrl * mjCtrlNeck
Definition controller.h:66
unsigned int period
Definition controller.h:89
Matrix lim
Definition controller.h:108
double startupMinVer
Definition controller.h:104
iKinChain * chainEyeL
Definition controller.h:58
bool ctrlInhibited
Definition controller.h:91
PolyDriver * drvTorso
Definition controller.h:59
mutex mutexCtrl
Definition controller.h:84
Vector computeEyesVelFromdxFP(const Vector &dfp)
void setTeyes(const double execTime)
bool areJointsHealthyAndSet()
Vector fbHead
Definition controller.h:112
void motionOngoingEventsFlush()
vector< int > jointsToSet
Definition controller.h:114
multiset< double > motionOngoingEvents
Definition controller.h:116
bool look(const Vector &x)
Vector fbEyes
Definition controller.h:112
void notifyEvent(const string &event, const double checkPoint=-1.0)
minJerkVelCtrl * mjCtrlEyes
Definition controller.h:67
void minAllowedVergenceChanged() override
void setTneck(const double execTime)
bool getVelocity(Vector &vel)
int nJointsTorso
Definition controller.h:95
void doSaccade(const Vector &ang, const Vector &vel)
Stamp txInfo_event
Definition controller.h:79
bool threadInit() override
mutex mutexLook
Definition controller.h:86
Vector fbNeck
Definition controller.h:112
Vector qdNeck
Definition controller.h:111
bool isMotionDone()
ExchangeData * commData
Definition controller.h:64
Vector vEyes
Definition controller.h:110
Vector qddeg
Definition controller.h:109
Vector q0
Definition controller.h:111
bool getDesired(Vector &des)
void findMinimumAllowedVergence()
vector< int > eyesJoints
Definition controller.h:113
void resetCtrlEyes()
Vector qd
Definition controller.h:111
IPositionControl * posHead
Definition controller.h:61
Integrator * IntState
Definition controller.h:68
Stamp txInfo_pose
Definition controller.h:78
void setTrackingMode(const bool f)
bool getGazeStabilization() const
Stamp txInfo_debug
Definition controller.h:80
double ctrlActiveRisingEdgeTime
Definition controller.h:97
void motionOngoingEventsHandling()
Stamp txInfo_x
Definition controller.h:76
Vector qdeg
Definition controller.h:109
BufferedPort< Vector > port_q
Definition controller.h:73
Integrator * IntStabilizer
Definition controller.h:70
IPositionDirect * posNeck
Definition controller.h:63
Vector fbTorso
Definition controller.h:112
IVelocityControl * velHead
Definition controller.h:62
Vector vdeg
Definition controller.h:109
IControlMode * modHead
Definition controller.h:60
double q_stamp
Definition controller.h:105
Controller(PolyDriver *_drvTorso, PolyDriver *_drvHead, ExchangeData *_commData, const double _neckTime, const double _eyesTime, const double _min_abs_vel, const unsigned int _period)
BufferedPort< Bottle > port_debug
Definition controller.h:75
Stamp txInfo_q
Definition controller.h:77
bool stabilizeGaze
Definition controller.h:94
double min_abs_vel
Definition controller.h:103
BufferedPort< Vector > port_x
Definition controller.h:72
void run() override
double pathPerc
Definition controller.h:102
bool unplugCtrlEyes
Definition controller.h:90
mutex mutexData
Definition controller.h:85
double getTneck() const
double Ts
Definition controller.h:106
double neckTime
Definition controller.h:100
iCubHeadCenter * neck
Definition controller.h:56
Integrator * IntPlan
Definition controller.h:69
multiset< double > motionOngoingEventsCurrent
Definition controller.h:117
Vector computeNeckVelFromdxFP(const Vector &fp, const Vector &dfp)
bool getTrackingMode() const
bool motionDone
Definition controller.h:92
condition_variable cv_eventLook
Definition controller.h:88
Bottle listMotionOngoingEvents()
bool registerMotionOngoingEvent(const double checkPoint)
ResourceFinder rf_cameras
Definition utils.h:156
Vector get_xd()
Definition utils.cpp:264
Vector get_qd()
Definition utils.cpp:273
bool stabilizationOn
Definition utils.h:154
double stabilizationGain
Definition utils.h:142
bool trackingModeOn
Definition utils.h:148
std::pair< Vector, bool > get_gyro()
Definition utils.cpp:345
Vector get_x()
Definition utils.cpp:282
double gyro_noise_threshold
Definition utils.h:141
void set_q(const Vector &_q)
Definition utils.cpp:225
bool tweakOverwrite
Definition utils.h:151
Vector get_counterv()
Definition utils.cpp:328
ResourceFinder rf_tweak
Definition utils.h:157
bool ctrlActive
Definition utils.h:147
double minAllowedVergence
Definition utils.h:139
int neckSolveCnt
Definition utils.h:146
xdPort * port_xd
Definition utils.h:135
bool debugInfoEnabled
Definition utils.h:159
void set_v(const Vector &_v)
Definition utils.cpp:241
iKinLimbVersion head_version
Definition utils.h:143
bool neckPosCtrlOn
Definition utils.h:153
bool saccadeUnderway
Definition utils.h:149
bool verbose
Definition utils.h:150
string localStemName
Definition utils.h:137
void set_torso(const Vector &_torso)
Definition utils.cpp:233
iCubEye * eyeR
Definition utils.h:173
iCubEye * eyeL
Definition utils.h:172
A class for defining a saturated integrator based on Tustin formula: .
Definition pids.h:48
const yarp::sig::Vector & get() const
Returns the current output vector.
Definition pids.h:154
const yarp::sig::Vector & integrate(const yarp::sig::Vector &x)
Executes one-step integration of input vector.
Definition pids.cpp:115
void reset(const yarp::sig::Vector &y0)
Resets the internal state and sets the output vector to the given value.
Definition pids.cpp:128
void setLim(const yarp::sig::Matrix &_lim)
Sets the output vector constraints matrix.
Definition pids.cpp:104
Implements a minimum-jerk controller with velocity commands in the assumption that the plant can be m...
Definition minJerkCtrl.h:82
virtual void reset(const yarp::sig::Vector &u0)=0
Resets the controller to a given value.
virtual yarp::sig::Vector computeCmd(const double _T, const yarp::sig::Vector &e)=0
Computes the velocity command.
static bool computeFixationPointData(iKinChain &eyeL, iKinChain &eyeR, yarp::sig::Vector &fp)
Retrieves current fixation point given the current kinematics configuration of the eyes.
A class for defining the iCub Eye.
Definition iKinFwd.h:1385
A class for describing the kinematic of the straight line coming out from the point located between t...
Definition iKinFwd.h:1450
A class for defining the Inertia Sensor Kinematics of the iCub.
Definition iKinFwd.h:1476
A Base class for defining a Serial Link Chain.
Definition iKinFwd.h:354
yarp::sig::Matrix getH(const unsigned int i, const bool allLink=false)
Returns the rigid roto-translation matrix from the root reference frame to the ith frame in Denavit-H...
Definition iKinFwd.cpp:732
bool setHN(const yarp::sig::Matrix &_HN)
Sets HN, the rigid roto-translation matrix from the Nth frame to the end-effector.
Definition iKinFwd.cpp:580
yarp::sig::Matrix GeoJacobian(const unsigned int i)
Returns the geometric Jacobian of the ith link.
Definition iKinFwd.cpp:1012
bool releaseLink(const unsigned int i)
Releases the ith Link.
Definition iKinFwd.cpp:463
yarp::sig::Vector EndEffPose(const bool axisRep=true)
Returns the coordinates of end-effector.
Definition iKinFwd.cpp:850
yarp::sig::Vector setAng(const yarp::sig::Vector &q)
Sets the free joint angles to values of q[i].
unsigned int getDOF() const
Returns the current number of Chain's DOF.
Definition iKinFwd.h:556
void setAllConstraints(bool _constrained)
Sets the constraint status of all chain links.
Definition iKinFwd.cpp:498
std::string get_version() const
Return the version string.
Definition iKinFwd.cpp:1600
iKinChain * asChain()
Returns a pointer to the Limb seen as Chain object.
Definition iKinFwd.h:1012
bool set_xd(const Vector &_xd)
Definition utils.cpp:83
bool & get_new()
Definition utils.h:84
zeros(2, 2) eye(2
constexpr double GAZECTRL_MOTIONDONE_EYES_QTHRES
Definition controller.h:39
constexpr int32_t GAZECTRL_SWOFFCOND_DISABLESLOT
Definition controller.h:37
constexpr double GAZECTRL_CRITICVER_STABILIZATION
Definition controller.h:40
constexpr double GAZECTRL_MOTIONDONE_NECK_QTHRES
Definition controller.h:38
double norm(const yarp::sig::Matrix &M, int col)
Returns the norm of the vector given in the form: matrix(:,col).
yarp::sig::Vector cross(const yarp::sig::Matrix &A, int colA, const yarp::sig::Matrix &B, int colB)
Returns the cross product between two vectors given in the form: matrix(:,col).
#define IKIN_ALMOST_ZERO
Definition iKinHlp.h:27
bool done
Definition main.cpp:42
void copyJointsBounds(iKinChain *ch1, iKinChain *ch2)
Definition utils.cpp:602
bool getAlignHN(const ResourceFinder &rf, const string &type, iKinChain *chain, const bool verbose=false)
Definition utils.cpp:474
bool getFeedback(Vector &fbTorso, Vector &fbHead, PolyDriver *drvTorso, PolyDriver *drvHead, const ExchangeData *commData, double *timeStamp=nullptr)
Definition utils.cpp:633
Matrix alignJointsBounds(iKinChain *chain, PolyDriver *drvTorso, PolyDriver *drvHead, const ExchangeData *commData)
Definition utils.cpp:531
double sat(const double val, const double min, const double max)
Definition utils.h:183
constexpr double CTRL_RAD2DEG
180/PI.
Definition math.h:61
constexpr double CTRL_DEG2RAD
PI/180.
Definition math.h:66
static struct bpf_program fp