iCub-main
ServerCartesianController.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
4  * email: ugo.pattacini@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 // -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
20 // Developed by Ugo Pattacini
21 
22 #include <sstream>
23 #include <limits>
24 #include <algorithm>
25 
28 
29 #include <yarp/math/Math.h>
30 
31 #include <iCub/iKin/iKinVocabs.h>
32 
33 #define CARTCTRL_SERVER_VER "2.0"
34 #define CARTCTRL_DEFAULT_PER 0.01 // [s]
35 #define CARTCTRL_DEFAULT_TASKVEL_PERFACTOR 4
36 #define CARTCTRL_DEFAULT_TOL 1e-2
37 #define CARTCTRL_DEFAULT_TRAJTIME 2.0 // [s]
38 #define CARTCTRL_DEFAULT_POSCTRL "on"
39 #define CARTCTRL_DEFAULT_MULJNTCTRL "on"
40 #define CARTCTRL_CONNECT_SOLVER_PING 1.0 // [s]
41 
42 using namespace std;
43 using namespace yarp::os;
44 using namespace yarp::dev;
45 using namespace yarp::sig;
46 using namespace yarp::math;
47 using namespace iCub::ctrl;
48 using namespace iCub::iKin;
49 
50 
51 /************************************************************************/
53 {
54  this->server=server;
55 }
56 
57 
58 /************************************************************************/
59 bool CartesianCtrlRpcProcessor::read(ConnectionReader &connection)
60 {
61  Bottle cmd, reply;
62  if (!cmd.read(connection))
63  return false;
64 
65  if (server->respond(cmd,reply))
66  if (ConnectionWriter *writer=connection.getWriter())
67  reply.write(*writer);
68 
69  return true;
70 }
71 
72 
73 /************************************************************************/
75 {
76  this->server=server;
77  useCallback();
78 }
79 
80 
81 /************************************************************************/
82 void CartesianCtrlCommandPort::onRead(Bottle &command)
83 {
84  if (command.size())
85  {
86  if ((command.get(0).asVocab32()==IKINCARTCTRL_VOCAB_CMD_GO) && (command.size()>3))
87  {
88  int pose=command.get(1).asVocab32();
89  double t=command.get(2).asFloat64();
90  Bottle *v=command.get(3).asList();
91 
93  {
94  Vector xd(3);
95  Vector od(v->size()-xd.length());
96 
97  for (size_t i=0; i<xd.length(); i++)
98  xd[i]=v->get(i).asFloat64();
99 
100  for (size_t i=0; i<od.length(); i++)
101  od[i]=v->get(xd.length()+i).asFloat64();
102 
103  server->goToPose(xd,od,t);
104  }
105  else if (pose==IKINCARTCTRL_VOCAB_VAL_POSE_XYZ)
106  {
107  Vector xd(v->size());
108 
109  for (int i=0; i<v->size(); i++)
110  xd[i]=v->get(i).asFloat64();
111 
112  server->goToPosition(xd,t);
113  }
114  }
115  else if ((command.get(0).asVocab32()==IKINCARTCTRL_VOCAB_CMD_TASKVEL) && (command.size()>1))
116  {
117  Bottle *v=command.get(1).asList();
118 
119  Vector xdot(3);
120  Vector odot(v->size()-xdot.length());
121 
122  for (size_t i=0; i<xdot.length(); i++)
123  xdot[i]=v->get(i).asFloat64();
124 
125  for (size_t i=0; i<odot.length(); i++)
126  odot[i]=v->get(xdot.length()+i).asFloat64();
127 
128  server->setTaskVelocities(xdot,odot);
129  }
130  }
131 }
132 
133 
134 /************************************************************************/
136  const Vector &x0)
137 {
138  yAssert(x0.length()>=7);
139  I=new Integrator(Ts,x0.subVector(0,2));
140  R=axis2dcm(x0.subVector(3,6));
141 }
142 
143 
144 /************************************************************************/
145 void TaskRefVelTargetGenerator::reset(const Vector &x0)
146 {
147  yAssert(x0.length()>=7);
148  I->reset(x0.subVector(0,2));
149  R=axis2dcm(x0.subVector(3,6));
150 }
151 
152 
153 /************************************************************************/
154 Vector TaskRefVelTargetGenerator::integrate(const Vector &vel)
155 {
156  yAssert(vel.length()>=7);
157  Vector w=vel.subVector(3,6);
158  w[3]*=I->getTs();
159  R=axis2dcm(w)*R;
160  return cat(I->integrate(vel.subVector(0,2)),dcm2axis(R));
161 }
162 
163 
164 /************************************************************************/
166 {
167  delete I;
168 }
169 
170 
171 /************************************************************************/
173  PeriodicThread(CARTCTRL_DEFAULT_PER)
174 {
175  init();
176 }
177 
178 
179 /************************************************************************/
181  PeriodicThread(CARTCTRL_DEFAULT_PER)
182 {
183  init();
184  open(config);
185 }
186 
187 
188 /************************************************************************/
190 {
191  // initialization
192  limbState=limbPlan=NULL;
193  chainState=chainPlan=NULL;
194  ctrl=NULL;
195  taskRefVelTargetGen=NULL;
196 
197  portCmd =NULL;
198  rpcProcessor=NULL;
199 
200  attached =false;
201  connected =false;
202  closed =true;
203  trackingMode =false;
204  executingTraj=false;
205  taskVelModeOn=false;
206  motionDone =true;
207  useReferences=false;
208  jointsHealthy=true;
209 
210  connectCnt=0;
212  maxPartJoints=0;
215  pathPerc=0.0;
216 
217  txToken=0.0;
218  rxToken=0.0;
221  skipSlvRes=false;
222  syncEventEnabled=false;
223 
224  contextIdCnt=0;
225 }
226 
227 
228 /************************************************************************/
230 {
233  portRpc.setReader(*rpcProcessor);
234 
235  string prefixName="/";
236  prefixName=prefixName+ctrlName;
237 
238  portSlvIn.open(prefixName+"/"+slvName+"/in");
239  portSlvOut.open(prefixName+"/"+slvName+"/out");
240  portSlvRpc.open(prefixName+"/"+slvName+"/rpc");
241  portCmd->open(prefixName+"/command:i");
242  portState.open(prefixName+"/state:o");
243  portEvent.open(prefixName+"/events:o");
244  portRpc.open(prefixName+"/rpc:i");
245 
246  if (debugInfoEnabled)
247  portDebugInfo.open(prefixName+"/dbg:o");
248 }
249 
250 
251 /************************************************************************/
253 {
254  // close this first since the
255  // callback does quite a lot
256  if (portCmd!=NULL)
257  {
258  portCmd->disableCallback();
259  portCmd->interrupt();
260  portCmd->close();
261  delete portCmd;
262  }
263 
264  portSlvIn.interrupt();
265  portSlvOut.interrupt();
266  portSlvRpc.interrupt();
267  portState.interrupt();
268  portEvent.interrupt();
269  portRpc.interrupt();
270 
271  portSlvIn.close();
272  portSlvOut.close();
273  portSlvRpc.close();
274  portState.close();
275  portEvent.close();
276  portRpc.close();
277 
278  if (debugInfoEnabled)
279  {
280  portDebugInfo.interrupt();
281  portDebugInfo.close();
282  }
283 
284  delete rpcProcessor;
285  connected=false;
286 }
287 
288 
289 /************************************************************************/
290 bool ServerCartesianController::respond(const Bottle &command, Bottle &reply)
291 {
292  if (command.size())
293  switch (command.get(0).asVocab32())
294  {
295  //-----------------
297  {
298  stopControl();
299  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
300  break;
301  }
302 
303  //-----------------
305  {
306  if (command.size()>3)
307  {
308  int pose=command.get(1).asVocab32();
309  double t=command.get(2).asFloat64();
310  Bottle *v=command.get(3).asList();
311  Vector xd(v->size());
312 
313  for (int i=0; i<v->size(); i++)
314  xd[i]=v->get(i).asFloat64();
315 
316  bool ret=false;
317 
319  {
320  lock_guard<mutex> lck(mtx);
321  taskVelModeOn=false;
322  ret=goTo(IKINCTRL_POSE_FULL,xd,t,true);
323  }
324  else if (pose==IKINCARTCTRL_VOCAB_VAL_POSE_XYZ)
325  {
326  lock_guard<mutex> lck(mtx);
327  taskVelModeOn=false;
328  ret=goTo(IKINCTRL_POSE_XYZ,xd,t,true);
329  }
330 
331  if (ret)
332  {
333  // wait for the solver
334  syncEventEnabled=true;
335  unique_lock<mutex> lck(mtx_syncEvent);
336  cv_syncEvent.wait(lck);
337 
338  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
339  }
340  else
341  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
342  }
343  else
344  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
345 
346  break;
347  }
348 
349  //-----------------
351  {
352  // just behave as a relay
353  Bottle slvCommand=command;
354 
355  if (!portSlvRpc.write(slvCommand,reply))
356  {
357  yError("%s: unable to get reply from solver!",ctrlName.c_str());
358  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
359  }
360 
361  break;
362  }
363 
364  //-----------------
366  {
367  int id;
368  if (storeContext(&id))
369  {
370  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
371  reply.addInt32(id);
372  }
373  else
374  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
375 
376  break;
377  }
378 
379  //-----------------
381  {
382  if (command.size()>1)
383  {
384  int id=command.get(1).asInt32();
385  if (restoreContext(id))
386  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
387  else
388  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
389  }
390 
391  break;
392  }
393 
394  //-----------------
396  {
397  if (command.size()>1)
398  {
399  Bottle *ids=command.get(1).asList();
400  if (deleteContexts(ids))
401  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
402  else
403  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
404  }
405 
406  break;
407  }
408 
409  //-----------------
411  {
412  if (command.size()>1)
413  switch (command.get(1).asVocab32())
414  {
415  //-----------------
417  {
418  bool flag;
419  if (getTrackingMode(&flag))
420  {
421  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
422 
423  if (flag)
424  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_MODE_TRACK);
425  else
426  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_MODE_SINGLE);
427  }
428  else
429  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
430 
431  break;
432  }
433 
434  //-----------------
436  {
437  bool flag;
438  if (getReferenceMode(&flag))
439  {
440  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
441 
442  if (flag)
443  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_TRUE);
444  else
445  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_FALSE);
446  }
447  else
448  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
449 
450  break;
451  }
452 
453  //-----------------
455  {
456  string priority;
457  if (getPosePriority(priority))
458  {
459  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
460  reply.addString(priority);
461  }
462  else
463  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
464 
465  break;
466  }
467 
468  //-----------------
470  {
471  double time;
472  if (getTrajTime(&time))
473  {
474  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
475  reply.addFloat64(time);
476  }
477  else
478  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
479 
480  break;
481  }
482 
483  //-----------------
485  {
486  double tol;
487  if (getInTargetTol(&tol))
488  {
489  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
490  reply.addFloat64(tol);
491  }
492  else
493  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
494 
495  break;
496  }
497 
498  //-----------------
500  {
501  bool flag;
502  if (checkMotionDone(&flag))
503  {
504  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
505 
506  if (flag)
507  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_TRUE);
508  else
509  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_FALSE);
510  }
511  else
512  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
513 
514  break;
515  }
516 
517  //-----------------
519  {
520  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
521 
522  if (connected)
523  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_TRUE);
524  else
525  reply.addVocab32(IKINCARTCTRL_VOCAB_VAL_FALSE);
526 
527  break;
528  }
529 
530  //-----------------
532  {
533  if (command.size()>2)
534  {
535  int axis=command.get(2).asInt32();
536  double min, max;
537 
538  if (getLimits(axis,&min,&max))
539  {
540  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
541  reply.addFloat64(min);
542  reply.addFloat64(max);
543  }
544  else
545  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
546  }
547  else
548  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
549 
550  break;
551  }
552 
553  //-----------------
555  {
556  Vector curDof;
557  if (getDOF(curDof))
558  {
559  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
560  Bottle &dofPart=reply.addList();
561 
562  for (size_t i=0; i<curDof.length(); i++)
563  dofPart.addInt32((int)curDof[i]);
564  }
565  else
566  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
567 
568  break;
569  }
570 
571  //-----------------
573  {
574  Vector curRestPos;
575  if (getRestPos(curRestPos))
576  {
577  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
578  reply.addList().read(curRestPos);
579  }
580  else
581  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
582 
583  break;
584  }
585 
586  //-----------------
588  {
589  Vector curRestWeights;
590  if (getRestWeights(curRestWeights))
591  {
592  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
593  reply.addList().read(curRestWeights);
594  }
595  else
596  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
597 
598  break;
599  }
600 
601  //-----------------
603  {
604  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
605 
606  Vector q(chainState->getN());
607  int cnt=0;
608 
609  for (unsigned int i=0; i<chainState->getN(); i++)
610  {
611  if ((*chainState)[i].isBlocked())
612  q[i]=CTRL_RAD2DEG*chainState->getAng(i);
613  else
614  q[i]=CTRL_RAD2DEG*qdes[cnt++];
615  }
616 
619 
620  break;
621  }
622 
623  //-----------------
625  {
626  Vector qdot;
627  if (getJointsVelocities(qdot))
628  {
629  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
630  reply.addList().read(qdot);
631  }
632  else
633  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
634 
635  break;
636  }
637 
638  //-----------------
640  {
641  Vector xdot, odot;
642  if (getTaskVelocities(xdot,odot))
643  {
644  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
645  Bottle &xdotPart=reply.addList();
646 
647  for (size_t i=0; i<xdot.length(); i++)
648  xdotPart.addFloat64(xdot[i]);
649 
650  for (size_t i=0; i<odot.length(); i++)
651  xdotPart.addFloat64(odot[i]);
652  }
653  else
654  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
655 
656  break;
657  }
658 
659  //-----------------
661  {
662  if (command.size()>2)
663  {
664  int axis=command.get(2).asInt32();
665  Vector x,o;
666  Stamp stamp;
667 
668  if (getPose(axis,x,o,&stamp))
669  {
670  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
671  Bottle &posePart=reply.addList();
672 
673  for (size_t i=0; i<x.length(); i++)
674  posePart.addFloat64(x[i]);
675 
676  for (size_t i=0; i<o.length(); i++)
677  posePart.addFloat64(o[i]);
678 
679  Bottle &stampPart=reply.addList();
680  stampPart.addInt32(stamp.getCount());
681  stampPart.addFloat64(stamp.getTime());
682  }
683  else
684  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
685  }
686  else
687  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
688 
689  break;
690  }
691 
692  //-----------------
694  {
695  Vector x,o;
696  if (getTipFrame(x,o))
697  {
698  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
699  Bottle &tipPart=reply.addList();
700 
701  for (size_t i=0; i<x.length(); i++)
702  tipPart.addFloat64(x[i]);
703 
704  for (size_t i=0; i<o.length(); i++)
705  tipPart.addFloat64(o[i]);
706  }
707  else
708  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
709 
710  break;
711  }
712 
713  //-----------------
715  {
716  Bottle info;
717  if (getInfo(info))
718  {
719  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
720  reply.addList()=info;
721  }
722  else
723  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
724 
725  break;
726  }
727 
728  //-----------------
730  {
731  Bottle options;
732  if (tweakGet(options))
733  {
734  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
735  reply.addList()=options;
736  }
737  else
738  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
739 
740  break;
741  }
742 
743  //-----------------
744  default:
745  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
746  }
747  else
748  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
749 
750  break;
751  }
752 
753  //-----------------
755  {
756  if (command.size()>2)
757  switch (command.get(1).asVocab32())
758  {
759  //-----------------
761  {
762  int mode=command.get(2).asVocab32();
763  bool ret=false;
764 
766  ret=setTrackingMode(true);
767  else if (mode==IKINCARTCTRL_VOCAB_VAL_MODE_SINGLE)
768  ret=setTrackingMode(false);
769 
770  if (ret)
771  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
772  else
773  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
774 
775  break;
776  }
777 
778  //-----------------
780  {
781  int mode=command.get(2).asVocab32();
782  bool ret=false;
783 
784  if (mode==IKINCARTCTRL_VOCAB_VAL_TRUE)
785  ret=setReferenceMode(true);
786  else if (mode==IKINCARTCTRL_VOCAB_VAL_FALSE)
787  ret=setReferenceMode(false);
788 
789  if (ret)
790  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
791  else
792  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
793 
794  break;
795  }
796 
797  //-----------------
799  {
800  string priority=command.get(2).asString();
801  if (setPosePriority(priority))
802  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
803  else
804  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
805 
806  break;
807  }
808 
809  //-----------------
811  {
812  if (setTrajTime(command.get(2).asFloat64()))
813  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
814  else
815  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
816 
817  break;
818  }
819 
820  //-----------------
822  {
823  if (setInTargetTol(command.get(2).asFloat64()))
824  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
825  else
826  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
827 
828  break;
829  }
830 
831  //-----------------
833  {
834  if (command.size()>4)
835  {
836  int axis=command.get(2).asInt32();
837  double min=command.get(3).asFloat64();
838  double max=command.get(4).asFloat64();
839 
840  if (setLimits(axis,min,max))
841  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
842  else
843  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
844  }
845  else
846  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
847 
848  break;
849  }
850 
851  //-----------------
853  {
854  if (Bottle *b=command.get(2).asList())
855  {
856  Vector newDof(b->size());
857  Vector curDof;
858 
859  for (int i=0; i<b->size(); i++)
860  newDof[i]=b->get(i).asFloat64();
861 
862  if (setDOF(newDof,curDof))
863  {
864  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
865  Bottle &dofPart=reply.addList();
866 
867  for (size_t i=0; i<curDof.length(); i++)
868  dofPart.addInt32((int)curDof[i]);
869  }
870  else
871  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
872  }
873  else
874  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
875 
876  break;
877  }
878 
879  //-----------------
881  {
882  if (Bottle *b=command.get(2).asList())
883  {
884  Vector newRestPos(b->size());
885  Vector curRestPos;
886 
887  for (int i=0; i<b->size(); i++)
888  newRestPos[i]=b->get(i).asFloat64();
889 
890  if (setRestPos(newRestPos,curRestPos))
891  {
892  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
893  reply.addList().read(curRestPos);
894  }
895  else
896  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
897  }
898  else
899  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
900 
901  break;
902  }
903 
904  //-----------------
906  {
907  if (Bottle *b=command.get(2).asList())
908  {
909  Vector newRestWeights(b->size());
910  Vector curRestWeights;
911 
912  for (int i=0; i<b->size(); i++)
913  newRestWeights[i]=b->get(i).asFloat64();
914 
915  if (setRestWeights(newRestWeights,curRestWeights))
916  {
917  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
918  reply.addList().read(curRestWeights);
919  }
920  else
921  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
922  }
923  else
924  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
925 
926  break;
927  }
928 
929  //-----------------
931  {
932  if (Bottle *b=command.get(2).asList())
933  {
934  if (b->size()>=7)
935  {
936  Vector x(3);
937  Vector o(b->size()-x.length());
938 
939  for (size_t i=0; i<x.length(); i++)
940  x[i]=b->get(i).asFloat64();
941 
942  for (size_t i=0; i<o.length(); i++)
943  o[i]=b->get(i+x.length()).asFloat64();
944 
945  if (attachTipFrame(x,o))
946  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
947  else
948  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
949  }
950  else
951  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
952  }
953  else
954  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
955 
956  break;
957  }
958 
959  //-----------------
961  {
962  if (Bottle *options=command.get(2).asList())
963  {
964  if (tweakSet(*options))
965  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_ACK);
966  else
967  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
968  }
969  else
970  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
971 
972  break;
973  }
974 
975  //-----------------
976  default:
977  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
978  }
979  else
980  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
981 
982  break;
983  }
984 
985  //-----------------
987  {
988  if (command.size()>2)
989  switch (command.get(1).asVocab32())
990  {
991  //-----------------
993  {
994  int mode=command.get(2).asVocab32();
996  (command.size()>3))
997  {
998  double checkPoint=command.get(3).asFloat64();
999  if (registerMotionOngoingEvent(checkPoint))
1000  {
1001  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
1002  break;
1003  }
1004  }
1005 
1006  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
1007  break;
1008  }
1009 
1010  //-----------------
1012  {
1013  int mode=command.get(2).asVocab32();
1015  (command.size()>3))
1016  {
1017  double checkPoint=command.get(3).asFloat64();
1018  if (unregisterMotionOngoingEvent(checkPoint))
1019  {
1020  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
1021  break;
1022  }
1023  }
1024 
1025  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
1026  break;
1027  }
1028 
1029  //-----------------
1031  {
1032  int mode=command.get(2).asVocab32();
1034  {
1035  reply.addVocab32(IKINSLV_VOCAB_REP_ACK);
1036  reply.addList()=listMotionOngoingEvents();
1037  }
1038  else
1039  reply.addVocab32(IKINSLV_VOCAB_REP_NACK);
1040 
1041  break;
1042  }
1043 
1044  //-----------------
1045  default:
1046  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
1047  }
1048  else
1049  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
1050 
1051  break;
1052  }
1053 
1054  //-----------------
1055  default:
1056  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
1057  }
1058  else
1059  reply.addVocab32(IKINCARTCTRL_VOCAB_REP_NACK);
1060 
1061  return true;
1062 }
1063 
1064 
1065 /************************************************************************/
1067 {
1068  double min, max;
1069  int cnt=0;
1070 
1071  yInfo("%s: aligning joints bounds ...",ctrlName.c_str());
1072  for (size_t i=0; i<lDsc.size(); i++)
1073  {
1074  yInfo("part #%lu: %s",(unsigned long)i,lDsc[i].key.c_str());
1075  for (int j=0; j<lJnt[i]; j++)
1076  {
1077  if (!lLim[i]->getLimits(lRmp[i][j],&min,&max))
1078  {
1079  yError("joint #%d: failed getting limits!",cnt);
1080  return false;
1081  }
1082 
1083  yInfo("joint #%d: [%g, %g] deg",cnt,min,max);
1084  (*chainState)[cnt].setMin(CTRL_DEG2RAD*min);
1085  (*chainState)[cnt].setMax(CTRL_DEG2RAD*max);
1086  (*chainPlan)[cnt].setMin(CTRL_DEG2RAD*min);
1087  (*chainPlan)[cnt].setMax(CTRL_DEG2RAD*max);
1088  cnt++;
1089  }
1090  }
1091 
1092  return true;
1093 }
1094 
1095 
1096 /************************************************************************/
1098 {
1099  Vector fbTmp(maxPartJoints);
1100  Vector stamps(maxPartJoints);
1101  int chainCnt=0;
1102  int _fbCnt=0;
1103  double timeStamp=-1.0;
1104 
1105  for (int i=0; i<numDrv; i++)
1106  {
1107  bool ok;
1108 
1109  if (useReferences)
1110  ok=lPid[i]->getPidReferences(VOCAB_PIDTYPE_POSITION,fbTmp.data());
1111  else if (encTimedEnabled)
1112  {
1113  ok=lEnt[i]->getEncodersTimed(fbTmp.data(),stamps.data());
1114  timeStamp=std::max(timeStamp,findMax(stamps.subVector(0,lJnt[i]-1)));
1115  }
1116  else
1117  ok=lEnc[i]->getEncoders(fbTmp.data());
1118 
1119  if (ok)
1120  {
1121  for (int j=0; j<lJnt[i]; j++)
1122  {
1123  double tmp=CTRL_DEG2RAD*fbTmp[lRmp[i][j]];
1124 
1125  if ((*chainState)[chainCnt].isBlocked())
1126  {
1127  chainState->setBlockingValue(chainCnt,tmp);
1128  chainPlan->setBlockingValue(chainCnt,tmp);
1129  }
1130  else
1131  _fb[_fbCnt++]=tmp;
1132 
1133  chainCnt++;
1134  }
1135  }
1136  else for (int j=0; j<lJnt[i]; j++)
1137  {
1138  if (!(*chainState)[chainCnt++].isBlocked())
1139  _fbCnt++;
1140  }
1141  }
1142 
1143  return timeStamp;
1144 }
1145 
1146 
1147 /************************************************************************/
1149 {
1150  // guard
1151  if (chainState==NULL)
1152  return;
1153 
1155 
1156  // destroy old controller
1157  delete ctrl;
1158 
1159  // update quantities
1160  fb.resize(chainState->getDOF());
1161  getFeedback(fb);
1162  chainState->setAng(fb);
1163  chainPlan->setAng(fb);
1164  velCmd.resize(chainState->getDOF(),0.0);
1166  qdes=chainState->getAng();
1167  q0=qdes;
1168 
1169  // instantiate new controller
1170  if (posDirectEnabled)
1171  ctrl=new MultiRefMinJerkCtrl(*chainPlan,ctrlPose,getPeriod());
1172  else if (plantModelProperties.check("plant_compensator",Value("off")).asString()=="on")
1173  {
1174  ctrl=new MultiRefMinJerkCtrl(*chainState,ctrlPose,getPeriod(),true);
1176  }
1177  else
1178  ctrl=new MultiRefMinJerkCtrl(*chainState,ctrlPose,getPeriod());
1179 
1180  // set tolerance
1182 
1183  // set task execution time
1185 
1186  // configure the Smith Predictor
1187  if (!posDirectEnabled)
1189 }
1190 
1191 
1192 /************************************************************************/
1194 {
1195  if (Bottle *b1=portSlvIn.read(false))
1196  {
1197  bool tokened=getTokenOption(*b1,&rxToken);
1198 
1199  // token shall be not greater than the trasmitted one
1200  if (tokened && (rxToken>txToken))
1201  {
1202  yWarning("%s: skipped message from solver due to invalid token (rx=%g)>(thr=%g)",
1203  ctrlName.c_str(),rxToken,txToken);
1204 
1205  return false;
1206  }
1207 
1208  // if we stopped the controller then we skip
1209  // any message with token smaller than the threshold
1210  if (skipSlvRes)
1211  {
1212  if (tokened && !trackingMode && (rxToken<=txTokenLatchedStopControl))
1213  {
1214  yWarning("%s: skipped message from solver since controller has been stopped (rx=%g)<=(thr=%g)",
1216 
1217  return false;
1218  }
1219  else
1220  skipSlvRes=false;
1221  }
1222 
1223  bool isNew=false;
1224  Vector _xdes, _qdes;
1225 
1226  if (b1->check(Vocab32::decode(IKINSLV_VOCAB_OPT_X)))
1227  {
1228  Bottle *b2=getEndEffectorPoseOption(*b1);
1229  int l1=(int)b2->size();
1230  int l2=7;
1231  int len=l1<l2 ? l1 : l2;
1232  _xdes.resize(len);
1233 
1234  for (int i=0; i<len; i++)
1235  _xdes[i]=b2->get(i).asFloat64();
1236 
1237  if (!(_xdes==xdes))
1238  isNew=true;
1239  }
1240 
1241  if (b1->check(Vocab32::decode(IKINSLV_VOCAB_OPT_Q)))
1242  {
1243  Bottle *b2=getJointsOption(*b1);
1244  int l1=(int)b2->size();
1245  int l2=chainState->getDOF();
1246  int len=l1<l2 ? l1 : l2;
1247  _qdes.resize(len);
1248 
1249  for (int i=0; i<len; i++)
1250  _qdes[i]=CTRL_DEG2RAD*b2->get(i).asFloat64();
1251 
1252  if (_qdes.length()!=ctrl->get_dim())
1253  {
1254  yWarning("%s: skipped message from solver since does not match the controller dimension (qdes=%d)!=(ctrl=%d)",
1255  ctrlName.c_str(),(int)_qdes.length(),ctrl->get_dim());
1256 
1257  return false;
1258  }
1259  else if (!(_qdes==qdes))
1260  isNew=true;
1261  }
1262 
1263  // update target
1264  if (isNew)
1265  {
1266  xdes=_xdes;
1267  qdes=_qdes;
1268  }
1269 
1270  // wake up rpc
1271  if (tokened && syncEventEnabled && (rxToken>=txTokenLatchedGoToRpc))
1272  {
1273  syncEventEnabled=false;
1274  cv_syncEvent.notify_all();
1275  }
1276 
1277  return isNew;
1278  }
1279  else
1280  return false;
1281 }
1282 
1283 
1284 /************************************************************************/
1286 {
1287  vector<int> modes(maxPartJoints);
1288  int chainCnt=0;
1289 
1290  jointsToSet.clear();
1291  for (int i=0; (i<numDrv) && ctrlModeAvailable; i++)
1292  {
1293  lMod[i]->getControlModes(modes.data());
1294  for (int j=0; j<lJnt[i]; j++)
1295  {
1296  if (!(*chainState)[chainCnt].isBlocked())
1297  {
1298  int mode=modes[lRmp[i][j]];
1299  if ((mode==VOCAB_CM_HW_FAULT) || (mode==VOCAB_CM_IDLE))
1300  return false;
1301  else if (posDirectEnabled)
1302  {
1303  if (mode!=VOCAB_CM_POSITION_DIRECT)
1304  jointsToSet.push_back(chainCnt);
1305  }
1306  else if (mode!=VOCAB_CM_VELOCITY)
1307  jointsToSet.push_back(chainCnt);
1308  }
1309 
1310  chainCnt++;
1311  }
1312  }
1313 
1314  return true;
1315 }
1316 
1317 
1318 /************************************************************************/
1319 void ServerCartesianController::setJointsCtrlMode(const vector<int> &jointsToSet)
1320 {
1321  if (jointsToSet.size()==0)
1322  return;
1323 
1324  int chainCnt=0;
1325  int k=0;
1326 
1327  for (int i=0; i<numDrv; i++)
1328  {
1329  vector<int> joints;
1330  vector<int> modes;
1331  for (int j=0; j<lJnt[i]; j++)
1332  {
1333  if (chainCnt==jointsToSet[k])
1334  {
1335  joints.push_back(lRmp[i][j]);
1336  modes.push_back(posDirectEnabled?VOCAB_CM_POSITION_DIRECT:
1337  VOCAB_CM_VELOCITY);
1338  k++;
1339  }
1340 
1341  chainCnt++;
1342  }
1343 
1344  if (joints.size()>0)
1345  lMod[i]->setControlModes((int)joints.size(),joints.data(),modes.data());
1346  }
1347 }
1348 
1349 
1350 /************************************************************************/
1352 {
1353  Bottle info;
1354  vector<int> joints;
1355  Vector refs;
1356  int cnt=0;
1357  int j=0;
1358  int k=0;
1359 
1360  info.addString("position");
1361  info.addString("multiple");
1362 
1363  Vector q=CTRL_RAD2DEG*ctrl->get_q();
1365  for (unsigned int i=0; i<chainState->getN(); i++)
1366  {
1367  if (!(*chainState)[i].isBlocked())
1368  {
1369  int joint=lRmp[j][k];
1370  double ref=q[cnt];
1371 
1372  joints.push_back(joint);
1373  refs.push_back(ref);
1374 
1375  ostringstream ss;
1376  ss<<lDsc[j].key<<"_"<<joint;
1377  info.addString(ss.str());
1378  info.addFloat64(ref);
1379 
1380  cnt++;
1381  }
1382 
1383  if (++k>=lJnt[j])
1384  {
1385  if (joints.size()>0)
1386  lPos[j]->setPositions((int)joints.size(),joints.data(),refs.data());
1387 
1388  joints.clear();
1389  refs.clear();
1390  j++;
1391  k=0;
1392  }
1393  }
1394 
1395  return info;
1396 }
1397 
1398 
1399 /************************************************************************/
1401 {
1402  Bottle info;
1403  vector<int> joints;
1404  Vector vels;
1405  int cnt=0;
1406  int j=0;
1407  int k=0;
1408 
1409  info.addString("velocity");
1410  info.addString("multiple");
1411 
1412  Vector v=CTRL_RAD2DEG*ctrl->get_qdot();
1413  for (unsigned int i=0; i<chainState->getN(); i++)
1414  {
1415  if (!(*chainState)[i].isBlocked())
1416  {
1417  int joint=lRmp[j][k];
1418  double vel=v[cnt];
1419  double thres=lDsc[j].minAbsVels[k];
1420 
1421  // apply bang-bang control to compensate for unachievable low velocities
1422  if ((vel!=0.0) && (fabs(vel)<thres))
1423  vel=yarp::math::sign(qdes[cnt]-fb[cnt])*thres;
1424 
1425  joints.push_back(joint);
1426  vels.push_back(vel);
1427 
1428  ostringstream ss;
1429  ss<<lDsc[j].key<<"_"<<joint;
1430  info.addString(ss.str());
1431  info.addFloat64(vel);
1432 
1433  velCmd[cnt]=vel;
1434  cnt++;
1435  }
1436 
1437  if (++k>=lJnt[j])
1438  {
1439  if (joints.size()>0)
1440  lVel[j]->velocityMove((int)joints.size(),joints.data(),vels.data());
1441 
1442  joints.clear();
1443  vels.clear();
1444  j++;
1445  k=0;
1446  }
1447  }
1448 
1449  return info;
1450 }
1451 
1452 
1453 /************************************************************************/
1455 {
1456  Bottle info;
1457  int cnt=0;
1458  int j=0;
1459  int k=0;
1460 
1461  info.addString("position");
1462  info.addString("single");
1463 
1464  Vector q=CTRL_RAD2DEG*ctrl->get_q();
1466  for (unsigned int i=0; i<chainState->getN(); i++)
1467  {
1468  if (!(*chainState)[i].isBlocked())
1469  {
1470  int joint=lRmp[j][k];
1471  double ref=q[cnt];
1472  lPos[j]->setPosition(joint,ref);
1473 
1474  ostringstream ss;
1475  ss<<lDsc[j].key<<"_"<<joint;
1476  info.addString(ss.str());
1477  info.addFloat64(ref);
1478 
1479  cnt++;
1480  }
1481 
1482  if (++k>=lJnt[j])
1483  {
1484  j++;
1485  k=0;
1486  }
1487  }
1488 
1489  return info;
1490 }
1491 
1492 
1493 /************************************************************************/
1495 {
1496  Bottle info;
1497  int cnt=0;
1498  int j=0;
1499  int k=0;
1500 
1501  info.addString("velocity");
1502  info.addString("single");
1503 
1504  Vector v=CTRL_RAD2DEG*ctrl->get_qdot();
1505  for (unsigned int i=0; i<chainState->getN(); i++)
1506  {
1507  if (!(*chainState)[i].isBlocked())
1508  {
1509  int joint=lRmp[j][k];
1510  double vel=v[cnt];
1511  double thres=lDsc[j].minAbsVels[k];
1512 
1513  // apply bang-bang control to compensate for unachievable low velocities
1514  if ((vel!=0.0) && (fabs(vel)<thres))
1515  vel=yarp::math::sign(qdes[cnt]-fb[cnt])*thres;
1516 
1517  lVel[j]->velocityMove(joint,vel);
1518 
1519  ostringstream ss;
1520  ss<<lDsc[j].key<<"_"<<joint;
1521  info.addString(ss.str());
1522  info.addFloat64(vel);
1523 
1524  velCmd[cnt]=vel;
1525  cnt++;
1526  }
1527 
1528  if (++k>=lJnt[j])
1529  {
1530  j++;
1531  k=0;
1532  }
1533  }
1534 
1535  return info;
1536 }
1537 
1538 
1539 /************************************************************************/
1540 void ServerCartesianController::stopLimb(const bool execStopPosition)
1541 {
1542  if (!posDirectEnabled || execStopPosition)
1543  {
1544  Bottle info;
1545  info.addString(posDirectEnabled?"position":"velocity");
1546  info.addString("single");
1547 
1548  int j=0; int k=0;
1549  for (unsigned int i=0; i<chainState->getN(); i++)
1550  {
1551  if (!(*chainState)[i].isBlocked())
1552  {
1553  int joint=lRmp[j][k];
1554  ostringstream ss;
1555  ss<<lDsc[j].key<<"_"<<joint;
1556  info.addString(ss.str());
1557 
1558  if (posDirectEnabled)
1559  {
1560  lStp[j]->stop(joint);
1561  info.addString("stop");
1562  }
1563  else
1564  {
1565  // vel==0.0 is always achievable
1566  lVel[j]->velocityMove(joint,0.0);
1567  info.addFloat64(0.0);
1568  }
1569  }
1570 
1571  if (++k>=lJnt[j])
1572  {
1573  j++;
1574  k=0;
1575  }
1576  }
1577 
1578  if (debugInfoEnabled && (portDebugInfo.getOutputCount()>0))
1579  {
1580  portDebugInfo.prepare()=info;
1581  debugInfo.update(txInfo.getTime());
1582  portDebugInfo.setEnvelope(debugInfo);
1583  portDebugInfo.writeStrict();
1584  }
1585  }
1586 
1587  velCmd=0.0;
1588  xdot_set=0.0;
1589 }
1590 
1591 
1592 /************************************************************************/
1594 {
1595  yInfo("Starting %s at %d ms",ctrlName.c_str(),(int)(1000.0*getPeriod()));
1596  return true;
1597 }
1598 
1599 
1600 /************************************************************************/
1602 {
1603  if (s)
1604  yInfo("%s started successfully",ctrlName.c_str());
1605  else
1606  yError("%s did not start!",ctrlName.c_str());
1607 }
1608 
1609 
1610 /************************************************************************/
1612 {
1613  if (connected)
1614  {
1615  lock_guard<mutex> lck(mtx);
1616 
1617  // read the feedback
1618  double stamp=getFeedback(fb);
1619 
1620  // update the stamp anyway
1621  if (stamp>=0.0)
1622  txInfo.update(stamp);
1623  else
1624  txInfo.update();
1625 
1626  vector<int> jointsToSet;
1628  if (!jointsHealthy)
1630 
1631  string event="none";
1632 
1633  // iff in position then update just chainState
1634  // and make the chainPlan evolve freely without
1635  // constraining it with the feedback
1636  if (posDirectEnabled)
1637  chainState->setAng(fb);
1638  else
1639  ctrl->set_q(fb);
1640 
1641  // manage the virtual target yielded by a
1642  // request for a task-space reference velocity
1644  {
1645  Vector xdot_set_int=taskRefVelTargetGen->integrate(xdot_set);
1646  goTo(IKINCTRL_POSE_FULL,xdot_set_int,0.0);
1648  }
1649 
1650  // get the current target pose
1651  if (getNewTarget())
1652  {
1653  if (jointsHealthy)
1654  {
1655  setJointsCtrlMode(jointsToSet);
1656  if (!executingTraj)
1657  {
1658  ctrl->restart(fb);
1660  }
1661 
1662  // onset of new trajectory
1663  executingTraj=true;
1664  event="motion-onset";
1665 
1667  q0=fb;
1668  }
1669  }
1670 
1671  // compute current point [%] in the path
1672  double dist=norm(qdes-q0);
1673  pathPerc=(dist>1e-6)?norm(fb-q0)/dist:1.0;
1674  pathPerc=std::min(std::max(pathPerc,0.0),1.0);
1675 
1676  if (executingTraj)
1677  {
1678  // add the contribution of the Smith Predictor block
1680 
1681  // limb control loop
1682  if (taskVelModeOn)
1684  else
1685  ctrl->iterate(xdes,qdes);
1686 
1687  // handle the end-trajectory event
1688  bool inTarget=ctrl->isInTarget();
1689  if (inTarget && posDirectEnabled)
1690  inTarget=isInTargetHelper();
1691 
1692  if (inTarget && !taskVelModeOn)
1693  {
1694  executingTraj=false;
1695  motionDone =true;
1696 
1697  stopLimb(false);
1698  event="motion-done";
1699 
1700  // switch the solver status to one shot mode
1701  // if that's the case
1702  if (!trackingMode && (rxToken==txToken))
1703  setTrackingModeHelper(false);
1704  }
1705  else
1706  {
1707  // send commands to the robot
1708  if (debugInfoEnabled && (portDebugInfo.getOutputCount()>0))
1709  {
1710  portDebugInfo.prepare()=(this->*sendCtrlCmd)();
1711  debugInfo.update(txInfo.getTime());
1712  portDebugInfo.setEnvelope(debugInfo);
1713  portDebugInfo.writeStrict();
1714  }
1715  else
1716  (this->*sendCtrlCmd)();
1717  }
1718  }
1719 
1720  // stream out the end-effector pose
1721  if (portState.getOutputCount()>0)
1722  {
1723  portState.prepare()=chainState->EndEffPose();
1724  portState.setEnvelope(txInfo);
1725  portState.write();
1726  }
1727 
1728  if (event=="motion-onset")
1729  notifyEvent(event);
1730 
1732 
1733  if (event=="motion-done")
1734  {
1736  notifyEvent(event);
1737  }
1738  }
1739  else if ((++connectCnt)*getPeriod()>CARTCTRL_CONNECT_SOLVER_PING)
1740  {
1741  if (connectToSolver())
1742  {
1743  createController();
1744 
1745  // reserve id==0 for start-up context
1746  int id0;
1747  storeContext(&id0);
1748  }
1749 
1750  connectCnt=0;
1751  }
1752 }
1753 
1754 
1755 /************************************************************************/
1757 {
1758  yInfo("Stopping %s",ctrlName.c_str());
1759 
1760  if (connected)
1761  stopLimb();
1762 
1763  notifyEvent("closing");
1764 }
1765 
1766 
1767 /************************************************************************/
1768 bool ServerCartesianController::open(Searchable &config)
1769 {
1770  yInfo("***** Configuring cartesian controller *****");
1771  closed=false;
1772 
1773  // GENERAL group
1774  Bottle &optGeneral=config.findGroup("GENERAL");
1775  if (optGeneral.isNull())
1776  {
1777  yError("GENERAL group is missing");
1778  close();
1779  return false;
1780  }
1781 
1782  yInfo("Acquiring options for group GENERAL...");
1783 
1784  // scan for required params
1785  if (optGeneral.check("SolverNameToConnect"))
1786  slvName=optGeneral.find("SolverNameToConnect").asString();
1787  else
1788  {
1789  yError("SolverNameToConnect option is missing");
1790  close();
1791  return false;
1792  }
1793 
1794  if (optGeneral.check("KinematicPart"))
1795  {
1796  kinPart=optGeneral.find("KinematicPart").asString();
1797  if ((kinPart!="arm") && (kinPart!="leg") && (kinPart!="custom"))
1798  {
1799  yError("Attempt to instantiate an unknown kinematic part");
1800  yError("Available parts are: arm, leg, custom");
1801  close();
1802  return false;
1803  }
1804  }
1805  else
1806  {
1807  yError("KinematicPart option is missing");
1808  close();
1809  return false;
1810  }
1811 
1812  string _partKinType;
1813  if (optGeneral.check("KinematicType"))
1814  {
1815  kinType=optGeneral.find("KinematicType").asString();
1816  string _kinType=kinType;
1817  _partKinType=_kinType.substr(0,_kinType.find("_"));
1818 
1819  if ((_partKinType!="left") && (_partKinType!="right"))
1820  {
1821  yError("Attempt to instantiate unknown kinematic type");
1822  yError("Available types are: left, right, left_v*, right_v*");
1823  close();
1824  return false;
1825  }
1826  }
1827  else if (kinPart!="custom")
1828  {
1829  yError("KinematicType option is missing");
1830  close();
1831  return false;
1832  }
1833 
1834  if (optGeneral.check("NumberOfDrivers"))
1835  {
1836  numDrv=optGeneral.find("NumberOfDrivers").asInt32();
1837  if (numDrv<=0)
1838  {
1839  yError("NumberOfDrivers shall be positive");
1840  close();
1841  return false;
1842  }
1843  }
1844  else
1845  {
1846  yError("NumberOfDrivers option is missing");
1847  close();
1848  return false;
1849  }
1850 
1851  // optional params
1852  if (optGeneral.check("ControllerName"))
1853  ctrlName=optGeneral.find("ControllerName").asString();
1854  else
1855  {
1856  ctrlName="cartController/"+kinPart+_partKinType;
1857  yWarning("default ControllerName assumed: %s",ctrlName.c_str());
1858  }
1859 
1860  if (optGeneral.check("ControllerPeriod"))
1861  setPeriod((double)optGeneral.find("ControllerPeriod").asInt32()/1000.0);
1862 
1863  taskRefVelPeriodFactor=optGeneral.check("TaskRefVelPeriodFactor",
1864  Value(CARTCTRL_DEFAULT_TASKVEL_PERFACTOR)).asInt32();
1865 
1866  posDirectEnabled=optGeneral.check("PositionControl",
1867  Value(CARTCTRL_DEFAULT_POSCTRL)).asString()=="on";
1868 
1869  multipleJointsControlEnabled=optGeneral.check("MultipleJointsControl",
1870  Value(CARTCTRL_DEFAULT_MULJNTCTRL)).asString()=="on";
1871 
1872  debugInfoEnabled=optGeneral.check("DebugInfo",Value("off")).asString()=="on";
1873  if (debugInfoEnabled)
1874  yDebug("Commands to robot will be also streamed out on debug port");
1875 
1876  // scan DRIVER groups
1877  for (int i=0; i<numDrv; i++)
1878  {
1879  ostringstream entry;
1880  entry<<"DRIVER_"<<i;
1881  string entry_str(entry.str());
1882 
1883  Bottle &optDrv=config.findGroup(entry_str);
1884  if (optDrv.isNull())
1885  {
1886  yError("%s group is missing",entry_str.c_str());
1887  close();
1888  return false;
1889  }
1890 
1891  yInfo("Acquiring options for group %s...",entry_str.c_str());
1892 
1893  DriverDescriptor desc;
1894 
1895  if (optDrv.check("Key"))
1896  desc.key=optDrv.find("Key").asString();
1897  else
1898  {
1899  yError("Key option is missing");
1900  close();
1901  return false;
1902  }
1903 
1904  if (optDrv.check("JointsOrder"))
1905  {
1906  string jointsOrderType=optDrv.find("JointsOrder").asString();
1907 
1908  if (jointsOrderType=="direct")
1909  desc.jointsDirectOrder=true;
1910  else if (jointsOrderType=="reversed")
1911  desc.jointsDirectOrder=false;
1912  else
1913  {
1914  yError("Attempt to select an unknown mapping order");
1915  yError("Available orders are: direct, reversed");
1916  close();
1917  return false;
1918  }
1919  }
1920  else
1921  {
1922  yError("JointsOrder option is missing");
1923  close();
1924  return false;
1925  }
1926 
1927  if (Bottle *pMinAbsVelsBottle=optDrv.find("MinAbsVels").asList())
1928  {
1929  desc.useDefaultMinAbsVel=false;
1930  desc.minAbsVels.resize(pMinAbsVelsBottle->size());
1931 
1932  for (int j=0; j<pMinAbsVelsBottle->size(); j++)
1933  {
1934  desc.minAbsVels[j]=pMinAbsVelsBottle->get(j).asFloat64();
1935 
1936  if (desc.minAbsVels[j]<0.0)
1937  desc.minAbsVels[j]=-desc.minAbsVels[j];
1938  }
1939  }
1940  else
1941  {
1942  yWarning("MinAbsVels option is missing ... using default values");
1943  desc.useDefaultMinAbsVel=true;
1944  }
1945 
1946  lDsc.push_back(desc);
1947  }
1948 
1949  // acquire options for Plant modeling
1950  Bottle &optPlantModel=config.findGroup("PLANT_MODEL");
1951  if (!optPlantModel.isNull())
1952  {
1953  yInfo("PLANT_MODEL group detected");
1954  plantModelProperties.fromString(optPlantModel.toString());
1955 
1956  // append information about the predictor's period,
1957  // that must match the controller's period
1958  plantModelProperties.unput("Ts");
1959  plantModelProperties.put("Ts",getPeriod());
1960  }
1961  else
1962  plantModelProperties.clear();
1963 
1964  // instantiate kinematic object
1965  if (kinPart=="arm")
1966  limbState=new iCubArm(kinType);
1967  else if (kinPart=="leg")
1968  limbState=new iCubLeg(kinType);
1969  else if (optGeneral.check("CustomKinFile")) // custom kinematics case
1970  {
1971  ResourceFinder rf_kin;
1972  if (optGeneral.check("CustomKinContext"))
1973  rf_kin.setDefaultContext(optGeneral.find("CustomKinContext").asString());
1974  rf_kin.configure(0,NULL);
1975  string pathToCustomKinFile=rf_kin.findFileByName(optGeneral.find("CustomKinFile").asString());
1976 
1977  Property linksOptions;
1978  linksOptions.fromConfigFile(pathToCustomKinFile);
1979 
1980  limbState=new iKinLimb(linksOptions);
1981  if (!limbState->isValid())
1982  {
1983  yError("Invalid links parameters");
1984  close();
1985  return false;
1986  }
1987  }
1988  else
1989  {
1990  yError("CustomKinFile option is missing");
1991  close();
1992  return false;
1993  }
1994 
1995  Property DHTable; limbState->toLinksProperties(DHTable);
1996  yInfo()<<"DH Table: "<<DHTable.toString(); // stream version to prevent long strings truncation
1997 
1998  // duplicate the limb for planning purpose
1999  limbPlan=new iKinLimb(*limbState);
2000 
2003 
2004  openPorts();
2005 
2006  return true;
2007 }
2008 
2009 
2010 /************************************************************************/
2012 {
2013  if (closed)
2014  return true;
2015 
2016  detachAll();
2017 
2018  delete limbState;
2019  delete limbPlan;
2020 
2021  while (eventsMap.size()>0)
2022  unregisterEvent(*eventsMap.begin()->second);
2023 
2024  closePorts();
2025 
2026  contextMap.clear();
2027 
2028  return closed=true;
2029 }
2030 
2031 
2032 /************************************************************************/
2033 bool ServerCartesianController::attachAll(const PolyDriverList &p)
2034 {
2035  drivers=p;
2036  int nd=drivers.size();
2037 
2038  yInfo("***** Attaching drivers to cartesian controller %s *****",ctrlName.c_str());
2039  yInfo("Received list of %d driver(s)",nd);
2040 
2041  if (nd!=numDrv)
2042  {
2043  yError("Expected list of %d driver(s)",numDrv);
2044  return false;
2045  }
2046 
2047  int remainingJoints=chainState->getN();
2048 
2049  ctrlModeAvailable=true;
2050  encTimedEnabled=true;
2051  pidAvailable=true;
2052  posDirectAvailable=true;
2053 
2054  for (int i=0; i<numDrv; i++)
2055  {
2056  yInfo("Acquiring info on driver %s...",lDsc[i].key.c_str());
2057 
2058  // check if what we require is present within the given list
2059  int j;
2060  for (j=0; j<drivers.size(); j++)
2061  if (lDsc[i].key==drivers[j]->key)
2062  break;
2063 
2064  if (j>=drivers.size())
2065  {
2066  yError("None of provided drivers is of type %s",lDsc[i].key.c_str());
2067  return false;
2068  }
2069 
2070  // acquire interfaces and driver's info
2071  if (drivers[j]->poly->isValid())
2072  {
2073  yInfo("driver %s successfully open",lDsc[i].key.c_str());
2074 
2075  IControlMode *mod;
2076  IEncoders *enc;
2077  IEncodersTimed *ent;
2078  IPidControl *pid;
2079  IControlLimits *lim;
2080  IVelocityControl *vel;
2081  IPositionDirect *pos;
2082  IPositionControl *stp;
2083  int joints;
2084 
2085  drivers[j]->poly->view(enc);
2086  drivers[j]->poly->view(lim);
2087 
2088  ctrlModeAvailable&=drivers[j]->poly->view(mod);
2089  drivers[j]->poly->view(vel);
2090 
2091  encTimedEnabled&=drivers[j]->poly->view(ent);
2092  pidAvailable&=drivers[j]->poly->view(pid);
2093  posDirectAvailable&=drivers[j]->poly->view(pos);
2094  posDirectAvailable&=drivers[j]->poly->view(stp);
2095 
2096  enc->getAxes(&joints);
2097 
2098  // this is for allocating vector
2099  // to read data from the interface
2100  if (joints>maxPartJoints)
2101  maxPartJoints=joints;
2102 
2103  // handle chain's bounds
2104  if (joints>remainingJoints)
2105  joints=remainingJoints;
2106 
2107  remainingJoints-=joints;
2108 
2109  int *rmpTmp=new int[joints];
2110  for (int k=0; k<joints; k++)
2111  rmpTmp[k]=lDsc[i].jointsDirectOrder ? k : (joints-k-1);
2112 
2113  // prepare references for minimum achievable absolute velocities
2114  if (lDsc[i].useDefaultMinAbsVel)
2115  lDsc[i].minAbsVels.resize(joints,0.0);
2116  else if (lDsc[i].minAbsVels.length()<(size_t)joints)
2117  {
2118  Vector tmp=lDsc[i].minAbsVels;
2119  lDsc[i].minAbsVels.resize(joints,0.0);
2120 
2121  for (size_t k=0; k<tmp.length(); k++)
2122  lDsc[i].minAbsVels[k]=tmp[k];
2123  }
2124 
2125  lMod.push_back(mod);
2126  lEnc.push_back(enc);
2127  lEnt.push_back(ent);
2128  lPid.push_back(pid);
2129  lLim.push_back(lim);
2130  lPos.push_back(pos);
2131  lStp.push_back(stp);
2132  lJnt.push_back(joints);
2133  lRmp.push_back(rmpTmp);
2134  lVel.push_back(vel);
2135  }
2136  else
2137  {
2138  yError("unable to open driver %s",lDsc[i].key.c_str());
2139  return false;
2140  }
2141  }
2142 
2143  yInfo("%s: IControlMode %s",ctrlName.c_str(),
2144  ctrlModeAvailable?"available":"not available");
2145 
2146  yInfo("%s: %s interface will be used",ctrlName.c_str(),
2147  encTimedEnabled?"IEncodersTimed":"IEncoders");
2148 
2149  yInfo("%s: IPidControl %s",ctrlName.c_str(),
2150  pidAvailable?"available":"not available");
2151 
2152  yInfo("%s: IPositionDirect %s",ctrlName.c_str(),
2153  posDirectAvailable?"available":"not available");
2154 
2156  yInfo("%s: %s interface will be used",ctrlName.c_str(),
2157  posDirectEnabled?"IPositionDirect":"IVelocityControl");
2158 
2159  yInfo("%s: %s control will be used",ctrlName.c_str(),
2160  multipleJointsControlEnabled?"multiple joints":"single joint");
2161 
2163  {
2164  if (posDirectEnabled)
2166  else
2168  }
2169  else if (posDirectEnabled)
2171  else
2173 
2174  if (!alignJointsBounds())
2175  {
2176  yError("unable to retrieve joints limits");
2177  return false;
2178  }
2179 
2180  // exclude acceleration constraints by fixing
2181  // thresholds at high values
2182  for (int i=0; i<numDrv; i++)
2183  for (int j=0; j<lJnt[i]; j++)
2184  lVel[i]->setRefAcceleration(j,std::numeric_limits<double>::max());
2185 
2186  // init task-space reference velocity
2187  xdot_set.resize(7,0.0);
2188 
2189  // this line shall be put before any
2190  // call to attached-dependent methods
2191  attached=true;
2192 
2193  connectToSolver();
2194 
2195  // create controller
2196  createController();
2197 
2198  // reserve id==0 for start-up context
2199  int id0;
2200  storeContext(&id0);
2201 
2202  // create the target generator for
2203  // task-space reference velocity
2206 
2207  start();
2208 
2209  return true;
2210 }
2211 
2212 
2213 /************************************************************************/
2215 {
2216  if (isRunning())
2217  stop();
2218 
2219  delete taskRefVelTargetGen;
2220  taskRefVelTargetGen=NULL;
2221 
2222  for (unsigned int i=0; i<lRmp.size(); i++)
2223  {
2224  delete[] lRmp[i];
2225  lRmp[i]=NULL;
2226  }
2227 
2228  lDsc.clear();
2229  lMod.clear();
2230  lEnc.clear();
2231  lEnt.clear();
2232  lPid.clear();
2233  lLim.clear();
2234  lVel.clear();
2235  lPos.clear();
2236  lStp.clear();
2237  lJnt.clear();
2238  lRmp.clear();
2239 
2240  delete ctrl;
2241  ctrl=NULL;
2242 
2243  attached=false;
2244  return true;
2245 }
2246 
2247 
2248 /************************************************************************/
2250 {
2251  string portSlvName="/";
2252  portSlvName=portSlvName+slvName+"/in";
2253 
2254  bool ok=Network::exists(portSlvName,true);
2255  yInfo("%s: Checking if cartesian solver %s is alive... %s",
2256  ctrlName.c_str(),slvName.c_str(),ok?"ready":"not yet");
2257 
2258  return ok;
2259 }
2260 
2261 
2262 /************************************************************************/
2264 {
2265  if (attached && !connected && pingSolver())
2266  {
2267  yInfo("%s: Connecting to cartesian solver %s...",ctrlName.c_str(),slvName.c_str());
2268 
2269  string portSlvName="/";
2270  portSlvName=portSlvName+slvName;
2271 
2272  bool ok=true;
2273 
2274  ok&=Network::connect(portSlvName+"/out",portSlvIn.getName(),"udp");
2275  ok&=Network::connect(portSlvOut.getName(),portSlvName+"/in","udp");
2276  ok&=Network::connect(portSlvRpc.getName(),portSlvName+"/rpc");
2277 
2278  if (ok)
2279  yInfo("%s: Connections established with %s",ctrlName.c_str(),slvName.c_str());
2280  else
2281  {
2282  yError("%s: Problems detected while connecting to %s",ctrlName.c_str(),slvName.c_str());
2283  return false;
2284  }
2285 
2286  // this line shall be put before any
2287  // call to connected-dependent methods
2288  connected=true;
2289 
2290  // keep solver and controller status aligned at start-up
2291  Bottle command, reply;
2292  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
2293  command.addVocab32(IKINSLV_VOCAB_OPT_DOF);
2294 
2295  // send command to solver and wait for reply
2296  if (!portSlvRpc.write(command,reply))
2297  {
2298  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2299  return false;
2300  }
2301 
2302  // update chain's links
2303  // skip the first ack/nack vocab
2304  Bottle *rxDofPart=reply.get(1).asList();
2305  for (int i=0; i<rxDofPart->size(); i++)
2306  {
2307  if (rxDofPart->get(i).asInt32()!=0)
2308  {
2309  chainState->releaseLink(i);
2310  chainPlan->releaseLink(i);
2311  }
2312  else
2313  {
2314  chainState->blockLink(i);
2315  chainPlan->blockLink(i);
2316  }
2317  }
2318 
2320  return true;
2321  }
2322  else
2323  return false;
2324 }
2325 
2326 
2327 /************************************************************************/
2328 bool ServerCartesianController::goTo(unsigned int _ctrlPose, const Vector &xd,
2329  const double t, const bool latchToken)
2330 {
2331  if (connected && (ctrl->get_dim()!=0) && jointsHealthy)
2332  {
2333  motionDone=false;
2334 
2335  ctrl->set_ctrlPose(ctrlPose=_ctrlPose);
2336 
2337  // update trajectory execution time just if required
2338  if (t>0.0)
2339  setTrajTimeHelper(t);
2340 
2341  Bottle &b=portSlvOut.prepare();
2342  b.clear();
2343 
2344  // xd part
2345  addTargetOption(b,xd);
2346  // pose part
2348  // always put solver in continuous mode
2349  // before commanding a new desired pose
2350  // in order to compensate for movements
2351  // of uncontrolled joints
2352  // correct solver status will be reinstated
2353  // accordingly at the end of trajectory
2354  addModeOption(b,true);
2355  // token part
2356  addTokenOption(b,txToken=Time::now());
2357 
2358  skipSlvRes=false;
2359  if (latchToken)
2361 
2362  portSlvOut.writeStrict();
2363  return true;
2364  }
2365  else
2366  return false;
2367 }
2368 
2369 
2370 /************************************************************************/
2372 {
2373  if (connected)
2374  {
2375  Bottle command, reply;
2376  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
2377  command.addVocab32(IKINSLV_VOCAB_OPT_MODE);
2379 
2380  // send command to solver and wait for reply
2381  bool ret=false;
2382  if (!portSlvRpc.write(command,reply))
2383  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2384  else if (reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK)
2385  {
2386  trackingMode=f;
2387  ret=true;
2388  }
2389 
2390  return ret;
2391  }
2392  else
2393  return false;
2394 }
2395 
2396 
2397 /************************************************************************/
2399 {
2400  lock_guard<mutex> lck(mtx);
2401  return setTrackingModeHelper(f);
2402 }
2403 
2404 
2405 /************************************************************************/
2407 {
2408  if (attached && (f!=NULL))
2409  {
2410  *f=trackingMode;
2411  return true;
2412  }
2413  else
2414  return false;
2415 }
2416 
2417 
2418 /************************************************************************/
2420 {
2421  if (attached && pidAvailable)
2422  {
2423  useReferences=f;
2424  return true;
2425  }
2426  else
2427  return false;
2428 }
2429 
2430 
2431 /************************************************************************/
2433 {
2434  if (attached && (f!=NULL))
2435  {
2436  *f=useReferences;
2437  return true;
2438  }
2439  else
2440  return false;
2441 }
2442 
2443 
2444 /************************************************************************/
2446 {
2447  bool ret=false;
2448  if (connected && ((p=="position") || (p=="orientation")))
2449  {
2450  lock_guard<mutex> lck(mtx);
2451 
2452  Bottle command, reply;
2453  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
2454  command.addVocab32(IKINSLV_VOCAB_OPT_PRIO);
2455  command.addVocab32(p=="position"?IKINSLV_VOCAB_VAL_PRIO_XYZ:IKINSLV_VOCAB_VAL_PRIO_ANG);
2456 
2457  // send command to solver and wait for reply
2458  if (portSlvRpc.write(command,reply))
2459  ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK);
2460  else
2461  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2462  }
2463 
2464  return ret;
2465 }
2466 
2467 
2468 /************************************************************************/
2470 {
2471  bool ret=false;
2472  if (connected)
2473  {
2474  Bottle command, reply;
2475  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
2476  command.addVocab32(IKINSLV_VOCAB_OPT_PRIO);
2477 
2478  // send command to solver and wait for reply
2479  if (portSlvRpc.write(command,reply))
2480  {
2481  if (ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK))
2482  p=(reply.get(1).asVocab32()==IKINSLV_VOCAB_VAL_PRIO_XYZ)?
2483  "position":"orientation";
2484  }
2485  else
2486  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2487  }
2488 
2489  return ret;
2490 }
2491 
2492 
2493 /************************************************************************/
2494 bool ServerCartesianController::getPose(Vector &x, Vector &o, Stamp *stamp)
2495 {
2496  if (attached)
2497  {
2498  lock_guard<mutex> lck(mtx);
2499  Vector pose=chainState->EndEffPose();
2500 
2501  x.resize(3);
2502  o.resize(pose.length()-x.length());
2503 
2504  for (size_t i=0; i<x.length(); i++)
2505  x[i]=pose[i];
2506 
2507  for (size_t i=0; i<o.length(); i++)
2508  o[i]=pose[x.length()+i];
2509 
2510  if (stamp!=NULL)
2511  *stamp=txInfo;
2512 
2513  return true;
2514  }
2515  else
2516  return false;
2517 }
2518 
2519 
2520 /************************************************************************/
2521 bool ServerCartesianController::getPose(const int axis, Vector &x,
2522  Vector &o, Stamp *stamp)
2523 {
2524  if (attached)
2525  {
2526  lock_guard<mutex> lck(mtx);
2527 
2528  bool ret=false;
2529  if (axis<(int)chainState->getN())
2530  {
2531  Matrix H=chainState->getH(axis,true);
2532 
2533  x.resize(3);
2534  for (size_t i=0; i<x.length(); i++)
2535  x[i]=H(i,3);
2536 
2537  o=dcm2axis(H);
2538 
2539  poseInfo.update(txInfo.getTime());
2540  if (stamp!=NULL)
2541  *stamp=poseInfo;
2542 
2543  ret=true;
2544  }
2545 
2546  return ret;
2547  }
2548  else
2549  return false;
2550 }
2551 
2552 
2553 /************************************************************************/
2554 bool ServerCartesianController::goToPose(const Vector &xd, const Vector &od,
2555  const double t)
2556 {
2557  if (connected)
2558  {
2559  lock_guard<mutex> lck(mtx);
2560 
2561  Vector _xd(xd.length()+od.length());
2562  for (size_t i=0; i<xd.length(); i++)
2563  _xd[i]=xd[i];
2564 
2565  for (size_t i=0; i<od.length(); i++)
2566  _xd[xd.length()+i]=od[i];
2567 
2568  taskVelModeOn=false;
2569  return goTo(IKINCTRL_POSE_FULL,_xd,t);
2570  }
2571  else
2572  return false;
2573 }
2574 
2575 
2576 /************************************************************************/
2577 bool ServerCartesianController::goToPosition(const Vector &xd, const double t)
2578 {
2579  if (connected)
2580  {
2581  lock_guard<mutex> lck(mtx);
2582 
2583  taskVelModeOn=false;
2584  return goTo(IKINCTRL_POSE_XYZ,xd,t);
2585  }
2586  else
2587  return false;
2588 }
2589 
2590 
2591 /************************************************************************/
2592 bool ServerCartesianController::goToPoseSync(const Vector &xd, const Vector &od,
2593  const double t)
2594 {
2595  return goToPose(xd,od,t);
2596 }
2597 
2598 
2599 /************************************************************************/
2600 bool ServerCartesianController::goToPositionSync(const Vector &xd, const double t)
2601 {
2602  return goToPosition(xd,t);
2603 }
2604 
2605 
2606 /************************************************************************/
2607 bool ServerCartesianController::getDesired(Vector &xdhat, Vector &odhat,
2608  Vector &qdhat)
2609 {
2610  if (connected)
2611  {
2612  lock_guard<mutex> lck(mtx);
2613 
2614  xdhat.resize(3);
2615  odhat.resize(xdes.length()-3);
2616 
2617  for (size_t i=0; i<xdhat.length(); i++)
2618  xdhat[i]=xdes[i];
2619 
2620  for (size_t i=0; i<odhat.length(); i++)
2621  odhat[i]=xdes[xdhat.length()+i];
2622 
2623  qdhat.resize(chainState->getN());
2624  int cnt=0;
2625 
2626  for (unsigned int i=0; i<chainState->getN(); i++)
2627  {
2628  if ((*chainState)[i].isBlocked())
2629  qdhat[i]=CTRL_RAD2DEG*chainState->getAng(i);
2630  else
2631  qdhat[i]=CTRL_RAD2DEG*qdes[cnt++];
2632  }
2633 
2634  return true;
2635  }
2636  else
2637  return false;
2638 }
2639 
2640 
2641 /************************************************************************/
2642 bool ServerCartesianController::askForPose(const Vector &xd, const Vector &od,
2643  Vector &xdhat, Vector &odhat,
2644  Vector &qdhat)
2645 {
2646  if (!connected)
2647  return false;
2648 
2649  lock_guard<mutex> lck(mtx);
2650 
2651  Bottle command, reply;
2652  Vector tg(xd.length()+od.length());
2653  for (size_t i=0; i<xd.length(); i++)
2654  tg[i]=xd[i];
2655 
2656  for (size_t i=0; i<od.length(); i++)
2657  tg[xd.length()+i]=od[i];
2658 
2659  command.addVocab32(IKINSLV_VOCAB_CMD_ASK);
2662 
2663  // send command and wait for reply
2664  bool ret=false;
2665  if (portSlvRpc.write(command,reply))
2666  ret=getDesiredOption(reply,xdhat,odhat,qdhat);
2667  else
2668  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2669 
2670  return ret;
2671 }
2672 
2673 
2674 /************************************************************************/
2675 bool ServerCartesianController::askForPose(const Vector &q0, const Vector &xd,
2676  const Vector &od, Vector &xdhat,
2677  Vector &odhat, Vector &qdhat)
2678 {
2679  if (!connected)
2680  return false;
2681 
2682  lock_guard<mutex> lck(mtx);
2683 
2684  Bottle command, reply;
2685  Vector tg(xd.length()+od.length());
2686  for (size_t i=0; i<xd.length(); i++)
2687  tg[i]=xd[i];
2688 
2689  for (size_t i=0; i<od.length(); i++)
2690  tg[xd.length()+i]=od[i];
2691 
2692  command.addVocab32(IKINSLV_VOCAB_CMD_ASK);
2696 
2697  // send command and wait for reply
2698  bool ret=false;
2699  if (portSlvRpc.write(command,reply))
2700  ret=getDesiredOption(reply,xdhat,odhat,qdhat);
2701  else
2702  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2703 
2704  return ret;
2705 }
2706 
2707 
2708 /************************************************************************/
2709 bool ServerCartesianController::askForPosition(const Vector &xd, Vector &xdhat,
2710  Vector &odhat, Vector &qdhat)
2711 {
2712  if (!connected)
2713  return false;
2714 
2715  lock_guard<mutex> lck(mtx);
2716 
2717  Bottle command, reply;
2718  command.addVocab32(IKINSLV_VOCAB_CMD_ASK);
2721 
2722  // send command and wait for reply
2723  bool ret=false;
2724  if (portSlvRpc.write(command,reply))
2725  ret=getDesiredOption(reply,xdhat,odhat,qdhat);
2726  else
2727  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2728 
2729  return ret;
2730 }
2731 
2732 
2733 /************************************************************************/
2734 bool ServerCartesianController::askForPosition(const Vector &q0, const Vector &xd,
2735  Vector &xdhat, Vector &odhat,
2736  Vector &qdhat)
2737 {
2738  if (!connected)
2739  return false;
2740 
2741  lock_guard<mutex> lck(mtx);
2742 
2743  Bottle command, reply;
2744  command.addVocab32(IKINSLV_VOCAB_CMD_ASK);
2748 
2749  // send command and wait for reply
2750  bool ret=false;
2751  if (portSlvRpc.write(command,reply))
2752  ret=getDesiredOption(reply,xdhat,odhat,qdhat);
2753  else
2754  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2755 
2756  return ret;
2757 }
2758 
2759 
2760 /************************************************************************/
2762 {
2763  if (connected)
2764  {
2765  lock_guard<mutex> lck(mtx);
2766 
2767  curDof.resize(chainState->getN());
2768  for (unsigned int i=0; i<chainState->getN(); i++)
2769  curDof[i]=!(*chainState)[i].isBlocked();
2770 
2771  return true;
2772  }
2773  else
2774  return false;
2775 }
2776 
2777 
2778 /************************************************************************/
2779 bool ServerCartesianController::setDOF(const Vector &newDof, Vector &curDof)
2780 {
2781  if (connected)
2782  {
2783  lock_guard<mutex> lck(mtx);
2784 
2785  Bottle command, reply;
2786  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
2787  command.addVocab32(IKINSLV_VOCAB_OPT_DOF);
2788  Bottle &txDofPart=command.addList();
2789  for (size_t i=0; i<newDof.length(); i++)
2790  txDofPart.addInt32((int)newDof[i]);
2791 
2792  // send command to solver and wait for reply
2793  bool ret=false;
2794  if (portSlvRpc.write(command,reply))
2795  {
2796  // update chain's links
2797  // skip the first ack/nack vocab
2798  Bottle *rxDofPart=reply.get(1).asList();
2799  curDof.resize((size_t)rxDofPart->size());
2800  for (int i=0; i<rxDofPart->size(); i++)
2801  {
2802  curDof[i]=rxDofPart->get(i).asInt32();
2803  if (curDof[i]!=0.0)
2804  {
2805  chainState->releaseLink(i);
2806  chainPlan->releaseLink(i);
2807  }
2808  else
2809  {
2810  chainState->blockLink(i);
2811  chainPlan->blockLink(i);
2812  }
2813  }
2814 
2815  // update controller
2816  createController();
2817  ret=true;
2818  }
2819  else
2820  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2821 
2822  return ret;
2823  }
2824  else
2825  return false;
2826 }
2827 
2828 
2829 /************************************************************************/
2831 {
2832  if (connected)
2833  {
2834  lock_guard<mutex> lck(mtx);
2835 
2836  Bottle command, reply;
2837  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
2838  command.addVocab32(IKINSLV_VOCAB_OPT_REST_POS);
2839 
2840  // send command to solver and wait for reply
2841  bool ret=false;
2842  if (portSlvRpc.write(command,reply))
2843  {
2844  Bottle *rxRestPart=reply.get(1).asList();
2845  curRestPos.resize(rxRestPart->size());
2846  for (int i=0; i<rxRestPart->size(); i++)
2847  curRestPos[i]=rxRestPart->get(i).asFloat64();
2848 
2849  ret=true;
2850  }
2851  else
2852  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2853 
2854  return ret;
2855  }
2856  else
2857  return false;
2858 }
2859 
2860 
2861 /************************************************************************/
2862 bool ServerCartesianController::setRestPos(const Vector &newRestPos,
2863  Vector &curRestPos)
2864 {
2865  if (connected)
2866  {
2867  lock_guard<mutex> lck(mtx);
2868 
2869  Bottle command, reply;
2870  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
2871  command.addVocab32(IKINSLV_VOCAB_OPT_REST_POS);
2872  command.addList().read(newRestPos);
2873 
2874  // send command to solver and wait for reply
2875  bool ret=false;
2876  if (portSlvRpc.write(command,reply))
2877  {
2878  Bottle *rxRestPart=reply.get(1).asList();
2879  curRestPos.resize(rxRestPart->size());
2880  for (int i=0; i<rxRestPart->size(); i++)
2881  curRestPos[i]=rxRestPart->get(i).asFloat64();
2882 
2883  ret=true;
2884  }
2885  else
2886  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2887 
2888  return ret;
2889  }
2890  else
2891  return false;
2892 }
2893 
2894 
2895 /************************************************************************/
2896 bool ServerCartesianController::getRestWeights(Vector &curRestWeights)
2897 {
2898  if (connected)
2899  {
2900  lock_guard<mutex> lck(mtx);
2901 
2902  Bottle command, reply;
2903  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
2904  command.addVocab32(IKINSLV_VOCAB_OPT_REST_WEIGHTS);
2905 
2906  // send command to solver and wait for reply
2907  bool ret=false;
2908  if (portSlvRpc.write(command,reply))
2909  {
2910  Bottle *rxRestPart=reply.get(1).asList();
2911  curRestWeights.resize(rxRestPart->size());
2912  for (int i=0; i<rxRestPart->size(); i++)
2913  curRestWeights[i]=rxRestPart->get(i).asFloat64();
2914 
2915  ret=true;
2916  }
2917  else
2918  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2919 
2920  return ret;
2921  }
2922  else
2923  return false;
2924 }
2925 
2926 
2927 /************************************************************************/
2928 bool ServerCartesianController::setRestWeights(const Vector &newRestWeights,
2929  Vector &curRestWeights)
2930 {
2931  if (connected)
2932  {
2933  lock_guard<mutex> lck(mtx);
2934 
2935  Bottle command, reply;
2936  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
2937  command.addVocab32(IKINSLV_VOCAB_OPT_REST_WEIGHTS);
2938  command.addList().read(newRestWeights);
2939 
2940  // send command to solver and wait for reply
2941  bool ret=false;
2942  if (portSlvRpc.write(command,reply))
2943  {
2944  Bottle *rxRestPart=reply.get(1).asList();
2945  curRestWeights.resize(rxRestPart->size());
2946  for (int i=0; i<rxRestPart->size(); i++)
2947  curRestWeights[i]=rxRestPart->get(i).asFloat64();
2948 
2949  ret=true;
2950  }
2951  else
2952  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2953 
2954  return ret;
2955  }
2956  else
2957  return false;
2958 }
2959 
2960 
2961 /************************************************************************/
2962 bool ServerCartesianController::getLimits(const int axis, double *min,
2963  double *max)
2964 {
2965  bool ret=false;
2966  if (connected && (min!=NULL) && (max!=NULL))
2967  {
2968  lock_guard<mutex> lck(mtx);
2969  if (axis<(int)chainState->getN())
2970  {
2971  Bottle command, reply;
2972  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
2973  command.addVocab32(IKINSLV_VOCAB_OPT_LIM);
2974  command.addInt32(axis);
2975 
2976  // send command to solver and wait for reply
2977  if (!portSlvRpc.write(command,reply))
2978  yError("%s: unable to get reply from solver!",ctrlName.c_str());
2979  else if (reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK)
2980  {
2981  *min=reply.get(1).asFloat64();
2982  *max=reply.get(2).asFloat64();
2983  ret=true;
2984  }
2985  }
2986  }
2987 
2988  return ret;
2989 }
2990 
2991 
2992 /************************************************************************/
2993 bool ServerCartesianController::setLimits(const int axis, const double min,
2994  const double max)
2995 {
2996  bool ret=false;
2997  if (connected)
2998  {
2999  lock_guard<mutex> lck(mtx);
3000 
3001  Bottle command, reply;
3002  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
3003  command.addVocab32(IKINSLV_VOCAB_OPT_LIM);
3004  command.addInt32(axis);
3005  command.addFloat64(min);
3006  command.addFloat64(max);
3007 
3008  // send command to solver and wait for reply
3009  if (portSlvRpc.write(command,reply))
3010  ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK);
3011  else
3012  yError("%s: unable to get reply from solver!",ctrlName.c_str());
3013  }
3014 
3015  return ret;
3016 }
3017 
3018 
3019 /************************************************************************/
3021 {
3022  if (attached && (t!=NULL))
3023  {
3024  *t=trajTime;
3025  return true;
3026  }
3027  else
3028  return false;
3029 }
3030 
3031 
3032 /************************************************************************/
3034 {
3035  if (attached)
3036  {
3037  trajTime=ctrl->set_execTime(t,true);
3038  return true;
3039  }
3040  else
3041  return false;
3042 }
3043 
3044 
3045 /************************************************************************/
3047 {
3048  lock_guard<mutex> lck(mtx);
3049  return setTrajTimeHelper(t);
3050 }
3051 
3052 
3053 /************************************************************************/
3055 {
3056  if (attached && (tol!=NULL))
3057  {
3058  *tol=targetTol;
3059  return true;
3060  }
3061  else
3062  return false;
3063 }
3064 
3065 
3066 /************************************************************************/
3068 {
3069  if (attached)
3070  {
3071  ctrl->setInTargetTol(tol);
3073  return true;
3074  }
3075  else
3076  return false;
3077 }
3078 
3079 
3080 /************************************************************************/
3082 {
3083  Matrix H=chainState->getH();
3084  Vector e(6,0.0);
3085 
3087  {
3088  e[0]=xdes[0]-H(0,3);
3089  e[1]=xdes[1]-H(1,3);
3090  e[2]=xdes[2]-H(2,3);
3091  }
3092 
3094  {
3095  Matrix Des=axis2dcm(xdes.subVector(3,6));
3096  Vector ax=dcm2axis(Des*SE3inv(H));
3097  e[3]=ax[3]*ax[0];
3098  e[4]=ax[3]*ax[1];
3099  e[5]=ax[3]*ax[2];
3100  }
3101 
3102  return (norm(e)<targetTol);
3103 }
3104 
3105 
3106 /************************************************************************/
3108 {
3109  lock_guard<mutex> lck(mtx);
3110  return setInTargetTolHelper(tol);
3111 }
3112 
3113 
3114 /************************************************************************/
3116 {
3117  if (connected)
3118  {
3119  lock_guard<mutex> lck(mtx);
3120  qdot=velCmd;
3121  return true;
3122  }
3123  else
3124  return false;
3125 }
3126 
3127 
3128 /************************************************************************/
3129 bool ServerCartesianController::getTaskVelocities(Vector &xdot, Vector &odot)
3130 {
3131  if (connected)
3132  {
3133  lock_guard<mutex> lck(mtx);
3134 
3135  Matrix J=ctrl->get_J();
3136  Vector taskVel(7,0.0);
3137 
3138  if ((J.rows()>0) && (J.cols()==velCmd.length()))
3139  {
3140  taskVel=J*(CTRL_DEG2RAD*velCmd);
3141 
3142  Vector _odot=taskVel.subVector(3,(unsigned int)taskVel.length()-1);
3143  double thetadot=norm(_odot);
3144  if (thetadot>0.0)
3145  _odot/=thetadot;
3146 
3147  taskVel[3]=_odot[0];
3148  taskVel[4]=_odot[1];
3149  taskVel[5]=_odot[2];
3150  taskVel.push_back(thetadot);
3151  }
3152 
3153  xdot.resize(3);
3154  odot.resize(taskVel.length()-xdot.length());
3155 
3156  for (size_t i=0; i<xdot.length(); i++)
3157  xdot[i]=taskVel[i];
3158 
3159  for (size_t i=0; i<odot.length(); i++)
3160  odot[i]=taskVel[xdot.length()+i];
3161 
3162  return true;
3163  }
3164  else
3165  return false;
3166 }
3167 
3168 
3169 /************************************************************************/
3171  const Vector &odot)
3172 {
3173  if (connected)
3174  {
3175  lock_guard<mutex> lck(mtx);
3176 
3177  for (int i=0; i<3; i++)
3178  xdot_set[i]=xdot[i];
3179 
3180  for (size_t i=3; i<xdot_set.length(); i++)
3181  xdot_set[i]=odot[i-3];
3182 
3183  if (norm(xdot_set)>0.0)
3184  {
3185  if (!taskVelModeOn)
3186  {
3189  }
3190 
3191  taskVelModeOn=true;
3192  }
3193  else
3195 
3196  return true;
3197  }
3198  else
3199  return false;
3200 }
3201 
3202 
3203 /************************************************************************/
3204 bool ServerCartesianController::attachTipFrame(const Vector &x, const Vector &o)
3205 {
3206  if (connected && (x.length()>=3) || (o.length()>=4))
3207  {
3208  lock_guard<mutex> lck(mtx);
3209 
3210  Bottle command, reply;
3211  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
3212  command.addVocab32(IKINSLV_VOCAB_OPT_TIP_FRAME);
3213  Bottle &txTipPart=command.addList();
3214 
3215  for (int i=0; i<3; i++)
3216  txTipPart.addFloat64(x[i]);
3217 
3218  for (int i=0; i<4; i++)
3219  txTipPart.addFloat64(o[i]);
3220 
3221  // send command to solver and wait for reply
3222  bool ret=false;
3223  if (portSlvRpc.write(command,reply))
3224  {
3225  if (ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK))
3226  {
3227  Matrix HN=axis2dcm(o);
3228  HN(0,3)=x[0];
3229  HN(1,3)=x[1];
3230  HN(2,3)=x[2];
3231  chainState->setHN(HN);
3232  chainPlan->setHN(HN);
3233  }
3234  }
3235  else
3236  yError("%s: unable to get reply from solver!",ctrlName.c_str());
3237 
3238  return ret;
3239  }
3240  else
3241  return false;
3242 }
3243 
3244 
3245 /************************************************************************/
3247 {
3248  if (connected)
3249  {
3250  lock_guard<mutex> lck(mtx);
3251  Matrix HN=chainState->getHN();
3252 
3253  x=HN.getCol(3);
3254  x.pop_back();
3255 
3256  o=dcm2axis(HN);
3257  return true;
3258  }
3259  else
3260  return false;
3261 }
3262 
3263 
3264 /************************************************************************/
3266 {
3267  return attachTipFrame(Vector(3,0.0),Vector(4,0.0));
3268 }
3269 
3270 
3271 /************************************************************************/
3273 {
3274  if (attached && (f!=NULL))
3275  {
3276  *f=motionDone;
3277  return true;
3278  }
3279  else
3280  return false;
3281 }
3282 
3283 
3284 /************************************************************************/
3286  const double timeout)
3287 {
3288  bool done=false;
3289  double t0=Time::now();
3290 
3291  while (!done)
3292  {
3293  Time::delay(period);
3294 
3295  if (!checkMotionDone(&done) || ((timeout>0.0) && ((Time::now()-t0)>timeout)))
3296  return false;
3297  }
3298 
3299  return true;
3300 }
3301 
3302 
3303 /************************************************************************/
3305 {
3306  if (connected)
3307  {
3308  if (executingTraj)
3309  {
3310  executingTraj=false;
3311  taskVelModeOn=false;
3312  motionDone =true;
3313 
3314  stopLimb();
3315 
3317  skipSlvRes=true;
3318 
3319  notifyEvent("motion-done");
3320 
3321  // switch the solver status to one shot mode
3322  // if that's the case
3323  if (!trackingMode)
3324  setTrackingModeHelper(false);
3325  }
3326 
3327  return true;
3328  }
3329  else
3330  return false;
3331 }
3332 
3333 
3334 /************************************************************************/
3336 {
3337  lock_guard<mutex> lck(mtx);
3338  return stopControlHelper();
3339 }
3340 
3341 
3342 /************************************************************************/
3344 {
3345  if (connected && (id!=NULL))
3346  {
3347  mtx.lock();
3348  unsigned int N=chainState->getN();
3349  mtx.unlock();
3350 
3351  Vector _dof,_restPos,_restWeights;
3352  Vector _tip_x,_tip_o;
3353 
3354  getDOF(_dof);
3355  getRestPos(_restPos);
3356  getRestWeights(_restWeights);
3357  getTipFrame(_tip_x,_tip_o);
3358 
3359  Matrix _limits(N,2);
3360  for (unsigned int axis=0; axis<N; axis++)
3361  {
3362  double min,max;
3363  getLimits(axis,&min,&max);
3364  _limits(axis,0)=min;
3365  _limits(axis,1)=max;
3366  }
3367 
3368  double _trajTime,_tol;
3369  bool _mode,_useReference;
3370 
3371  getTrajTime(&_trajTime);
3372  getInTargetTol(&_tol);
3373  getTrackingMode(&_mode);
3374  getReferenceMode(&_useReference);
3375 
3376  lock_guard<mutex> lck(mtx);
3377 
3378  Context &context=contextMap[contextIdCnt];
3379  context.dof=_dof;
3380  context.restPos=_restPos;
3381  context.restWeights=_restWeights;
3382  context.limits=_limits;
3383  context.tip_x=_tip_x;
3384  context.tip_o=_tip_o;
3385  context.trajTime=_trajTime;
3386  context.tol=_tol;
3387  context.mode=_mode;
3388  context.useReferences=_useReference;
3389  context.straightness=ctrl->get_gamma();
3390  getPosePriority(context.posePriority);
3391  getTask2ndOptions(context.task_2);
3393 
3394  *id=contextIdCnt++;
3395  return true;
3396  }
3397  else
3398  return false;
3399 }
3400 
3401 
3402 /************************************************************************/
3404 {
3405  if (attached)
3406  {
3407  mtx.lock();
3408 
3409  map<int,Context>::iterator itr=contextMap.find(id);
3410  bool valid=(itr!=contextMap.end());
3411  Context context;
3412  if (valid)
3413  context=itr->second;
3414 
3415  mtx.unlock();
3416 
3417  if (valid)
3418  {
3419  setDOF(context.dof,context.dof);
3420  setRestPos(context.restPos,context.restPos);
3421  setRestWeights(context.restWeights,context.restWeights);
3422  attachTipFrame(context.tip_x,context.tip_o);
3423 
3424  for (unsigned int axis=0; axis<chainState->getN(); axis++)
3425  setLimits(axis,context.limits(axis,0),context.limits(axis,1));
3426 
3427  setTrackingMode(context.mode);
3429  setTrajTime(context.trajTime);
3430  setInTargetTol(context.tol);
3431  ctrl->set_gamma(context.straightness);
3432  setPosePriority(context.posePriority);
3433  setTask2ndOptions(context.task_2);
3435 
3436  return true;
3437  }
3438  else
3439  return false;
3440  }
3441  else
3442  return false;
3443 }
3444 
3445 
3446 /************************************************************************/
3448 {
3449  map<int,Context>::iterator itr=contextMap.find(id);
3450  if (itr!=contextMap.end())
3451  {
3452  contextMap.erase(itr);
3453  return true;
3454  }
3455  else
3456  return false;
3457 }
3458 
3459 
3460 /************************************************************************/
3462 {
3463  if (contextIdList!=NULL)
3464  {
3465  lock_guard<mutex> lck(mtx);
3466 
3467  for (int i=0; i<contextIdList->size(); i++)
3468  {
3469  int id=contextIdList->get(i).asInt32();
3470  map<int,Context>::iterator itr=contextMap.find(id);
3471  if (itr!=contextMap.end())
3472  contextMap.erase(itr);
3473  }
3474 
3475  return true;
3476  }
3477  else
3478  return false;
3479 }
3480 
3481 
3482 /************************************************************************/
3484 {
3485  if (attached)
3486  {
3487  info.clear();
3488 
3489  Bottle &serverVer=info.addList();
3490  serverVer.addString("server_version");
3491  serverVer.addString(CARTCTRL_SERVER_VER);
3492 
3493  string kinPartStr(kinPart);
3494  string type=limbState->getType();
3495 
3496  size_t pos=type.find("_v");
3497  iKinLimbVersion hwVer("1.0");
3498  if (pos!=string::npos)
3499  hwVer=iKinLimbVersion(type.substr(pos+2));
3500 
3501  Bottle &partVer=info.addList();
3502  partVer.addString(kinPartStr+"_version");
3503  partVer.addString(hwVer.get_version());
3504 
3505  Bottle &partType=info.addList();
3506  partType.addString(kinPartStr+"_type");
3507  partType.addString(type);
3508 
3509  Bottle &events=info.addList();
3510  events.addString("events");
3511  Bottle &eventsList=events.addList();
3512  eventsList.addString("motion-onset");
3513  eventsList.addString("motion-done");
3514  eventsList.addString("motion-ongoing");
3515  eventsList.addString("closing");
3516  eventsList.addString("*");
3517 
3518  return true;
3519  }
3520  else
3521  return false;
3522 }
3523 
3524 
3525 /************************************************************************/
3527  const double checkPoint)
3528 {
3529  double time=txInfo.getTime();
3530  map<string,CartesianEvent*>::iterator itr;
3531 
3532  if (portEvent.getOutputCount()>0)
3533  {
3534  Bottle &ev=portEvent.prepare();
3535  ev.clear();
3536 
3537  ev.addString(event);
3538  ev.addFloat64(time);
3539  if (checkPoint>=0.0)
3540  ev.addFloat64(checkPoint);
3541 
3542  eventInfo.update(time);
3543  portEvent.setEnvelope(eventInfo);
3544  portEvent.writeStrict();
3545  }
3546 
3547  // rise the all-events callback
3548  itr=eventsMap.find("*");
3549  if (itr!=eventsMap.end())
3550  {
3551  if (itr->second!=NULL)
3552  {
3553  CartesianEvent &Event=*itr->second;
3554  Event.cartesianEventVariables.type=event;
3555  Event.cartesianEventVariables.time=time;
3556 
3557  if (checkPoint>=0.0)
3558  Event.cartesianEventVariables.motionOngoingCheckPoint=checkPoint;
3559 
3560  Event.cartesianEventCallback();
3561  }
3562  }
3563 
3564  string typeExtended=event;
3565  if (checkPoint>=0.0)
3566  {
3567  ostringstream ss;
3568  ss<<event<<"-"<<checkPoint;
3569  typeExtended=ss.str();
3570  }
3571 
3572  // rise the event specific callback
3573  itr=eventsMap.find(typeExtended);
3574  if (itr!=eventsMap.end())
3575  {
3576  if (itr->second!=NULL)
3577  {
3578  CartesianEvent &Event=*itr->second;
3579  Event.cartesianEventVariables.type=event;
3580  Event.cartesianEventVariables.time=time;
3581 
3582  if (checkPoint>=0.0)
3583  Event.cartesianEventVariables.motionOngoingCheckPoint=checkPoint;
3584 
3585  Event.cartesianEventCallback();
3586  }
3587  }
3588 }
3589 
3590 
3591 /************************************************************************/
3592 bool ServerCartesianController::registerEvent(CartesianEvent &event)
3593 {
3594  if (!connected)
3595  return false;
3596 
3597  string type=event.cartesianEventParameters.type;
3598  if (type=="motion-ongoing")
3599  {
3600  double checkPoint=event.cartesianEventParameters.motionOngoingCheckPoint;
3601  registerMotionOngoingEvent(checkPoint);
3602 
3603  ostringstream ss;
3604  ss<<type<<"-"<<checkPoint;
3605  type=ss.str();
3606  }
3607 
3608  eventsMap[type]=&event;
3609  return true;
3610 }
3611 
3612 
3613 /************************************************************************/
3615 {
3616  if (!connected)
3617  return false;
3618 
3619  string type=event.cartesianEventParameters.type;
3620  if (type=="motion-ongoing")
3621  {
3622  double checkPoint=event.cartesianEventParameters.motionOngoingCheckPoint;
3623  unregisterMotionOngoingEvent(checkPoint);
3624 
3625  ostringstream ss;
3626  ss<<type<<"-"<<event.cartesianEventParameters.motionOngoingCheckPoint;
3627  type=ss.str();
3628  }
3629 
3630  eventsMap.erase(type);
3631  return true;
3632 }
3633 
3634 
3635 /************************************************************************/
3637 {
3638  if (motionOngoingEventsCurrent.size()!=0)
3639  {
3640  double curCheckPoint=*motionOngoingEventsCurrent.begin();
3641  if (pathPerc>=curCheckPoint)
3642  {
3643  notifyEvent("motion-ongoing",curCheckPoint);
3644  motionOngoingEventsCurrent.erase(curCheckPoint);
3645  }
3646  }
3647 }
3648 
3649 
3650 /************************************************************************/
3652 {
3653  while (motionOngoingEventsCurrent.size()!=0)
3654  {
3655  double curCheckPoint=*motionOngoingEventsCurrent.begin();
3656  notifyEvent("motion-ongoing",curCheckPoint);
3657  motionOngoingEventsCurrent.erase(curCheckPoint);
3658  }
3659 }
3660 
3661 
3662 /************************************************************************/
3664 {
3665  if ((checkPoint>=0.0) && (checkPoint<=1.0))
3666  {
3667  lock_guard<mutex> lck(mtx);
3668  motionOngoingEvents.insert(checkPoint);
3669  return true;
3670  }
3671  else
3672  return false;
3673 }
3674 
3675 
3676 /************************************************************************/
3678 {
3679  bool ret=false;
3680  if ((checkPoint>=0.0) && (checkPoint<=1.0))
3681  {
3682  lock_guard<mutex> lck(mtx);
3683  multiset<double>::iterator itr=motionOngoingEvents.find(checkPoint);
3684  if (itr!=motionOngoingEvents.end())
3685  {
3686  motionOngoingEvents.erase(itr);
3687  ret=true;
3688  }
3689  }
3690 
3691  return ret;
3692 }
3693 
3694 
3695 /************************************************************************/
3697 {
3698  Bottle events;
3699 
3700  lock_guard<mutex> lck(mtx);
3701  for (multiset<double>::iterator itr=motionOngoingEvents.begin(); itr!=motionOngoingEvents.end(); itr++)
3702  events.addFloat64(*itr);
3703 
3704  return events;
3705 }
3706 
3707 
3708 /************************************************************************/
3710 {
3711  bool ret=false;
3712  if (connected)
3713  {
3714  Bottle command, reply;
3715  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
3716  command.addVocab32(IKINSLV_VOCAB_OPT_TASK2);
3717 
3718  // send command to solver and wait for reply
3719  if (portSlvRpc.write(command,reply))
3720  {
3721  if (ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK))
3722  v=reply.get(1);
3723  }
3724  else
3725  yError("%s: unable to get reply from solver!",ctrlName.c_str());
3726  }
3727 
3728  return ret;
3729 }
3730 
3731 
3732 /************************************************************************/
3734 {
3735  bool ret=false;
3736  if (connected)
3737  {
3738  lock_guard<mutex> lck(mtx);
3739 
3740  Bottle command, reply;
3741  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
3742  command.addVocab32(IKINSLV_VOCAB_OPT_TASK2);
3743  command.add(v);
3744 
3745  // send command to solver and wait for reply
3746  if (portSlvRpc.write(command,reply))
3747  ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK);
3748  else
3749  yError("%s: unable to get reply from solver!",ctrlName.c_str());
3750  }
3751 
3752  return ret;
3753 }
3754 
3755 
3756 /************************************************************************/
3758 {
3759  bool ret=false;
3760  if (connected)
3761  {
3762  Bottle command, reply;
3763  command.addVocab32(IKINSLV_VOCAB_CMD_GET);
3764  command.addVocab32(IKINSLV_VOCAB_OPT_CONVERGENCE);
3765 
3766  // send command to solver and wait for reply
3767  if (portSlvRpc.write(command,reply))
3768  {
3769  if (ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK))
3770  options=*reply.get(1).asList();
3771  }
3772  else
3773  yError("%s: unable to get reply from solver!",ctrlName.c_str());
3774  }
3775 
3776  return ret;
3777 }
3778 
3779 
3780 /************************************************************************/
3782 {
3783  bool ret=false;
3784  if (connected)
3785  {
3786  lock_guard<mutex> lck(mtx);
3787 
3788  Bottle command, reply;
3789  command.addVocab32(IKINSLV_VOCAB_CMD_SET);
3790  command.addVocab32(IKINSLV_VOCAB_OPT_CONVERGENCE);
3791  command.addList()=options;
3792 
3793  // send command to solver and wait for reply
3794  if (portSlvRpc.write(command,reply))
3795  ret=(reply.get(0).asVocab32()==IKINSLV_VOCAB_REP_ACK);
3796  else
3797  yError("%s: unable to get reply from solver!",ctrlName.c_str());
3798  }
3799 
3800  return ret;
3801 }
3802 
3803 
3804 /************************************************************************/
3805 bool ServerCartesianController::tweakSet(const Bottle &options)
3806 {
3807  bool ret=true;
3808 
3809  // straightness
3810  if (options.check("straightness"))
3811  ctrl->set_gamma(options.find("straightness").asFloat64());
3812 
3813  // secondary task
3814  if (options.check("task_2"))
3815  ret&=setTask2ndOptions(options.find("task_2"));
3816 
3817  // solver convergence options
3818  if (options.check("tol") || options.check("constr_tol") ||
3819  options.check("max_iter"))
3820  ret&=setSolverConvergenceOptions(options);
3821 
3822  return ret;
3823 }
3824 
3825 
3826 /************************************************************************/
3828 {
3829  if (attached)
3830  {
3831  lock_guard<mutex> lck(mtx);
3832  options.clear();
3833 
3834  bool ret=true;
3835 
3836  // straightness
3837  Bottle &straightness=options.addList();
3838  straightness.addString("straightness");
3839  straightness.addFloat64(ctrl->get_gamma());
3840 
3841  // secondary task
3842  Value v;
3843  ret&=getTask2ndOptions(v);
3844  if (ret)
3845  {
3846  Bottle &task2=options.addList();
3847  task2.addString("task_2");
3848  task2.add(v);
3849  }
3850 
3851  // solver convergence options
3852  Bottle b;
3854  if (ret)
3855  options.append(b);
3856 
3857  return ret;
3858  }
3859  else
3860  return false;
3861 }
3862 
3863 
3864 /************************************************************************/
3866 {
3867  close();
3868 }
3869 
3870 
3871 
#define IKINCARTCTRL_VOCAB_OPT_Q
#define IKINCARTCTRL_VOCAB_OPT_INFO
#define IKINCARTCTRL_VOCAB_VAL_POSE_XYZ
#define IKINCARTCTRL_VOCAB_OPT_PRIO
#define IKINCARTCTRL_VOCAB_OPT_UNREGISTER
#define IKINCARTCTRL_VOCAB_VAL_TRUE
#define IKINCARTCTRL_VOCAB_CMD_GO
#define IKINCARTCTRL_VOCAB_OPT_REST_POS
#define IKINCARTCTRL_VOCAB_OPT_REFERENCE
#define IKINCARTCTRL_VOCAB_OPT_DES
#define IKINCARTCTRL_VOCAB_OPT_LIM
#define IKINCARTCTRL_VOCAB_OPT_QDOT
#define IKINCARTCTRL_VOCAB_OPT_LIST
#define IKINCARTCTRL_VOCAB_OPT_X
#define IKINCARTCTRL_VOCAB_REP_ACK
#define IKINCARTCTRL_VOCAB_VAL_FALSE
#define IKINCARTCTRL_VOCAB_CMD_STORE
#define IKINCARTCTRL_VOCAB_OPT_TIME
#define IKINCARTCTRL_VOCAB_CMD_DELETE
#define IKINCARTCTRL_VOCAB_OPT_MODE
#define IKINCARTCTRL_VOCAB_CMD_TASKVEL
#define IKINCARTCTRL_VOCAB_VAL_POSE_FULL
#define IKINCARTCTRL_VOCAB_VAL_MODE_TRACK
#define IKINCARTCTRL_VOCAB_OPT_DOF
#define IKINCARTCTRL_VOCAB_OPT_TOL
#define IKINCARTCTRL_VOCAB_VAL_MODE_SINGLE
#define IKINCARTCTRL_VOCAB_CMD_ASK
#define IKINCARTCTRL_VOCAB_CMD_SET
#define IKINCARTCTRL_VOCAB_OPT_REST_WEIGHTS
#define IKINCARTCTRL_VOCAB_CMD_RESTORE
#define IKINCARTCTRL_VOCAB_OPT_ISSOLVERON
#define IKINCARTCTRL_VOCAB_OPT_TIP_FRAME
#define IKINCARTCTRL_VOCAB_CMD_EVENT
#define IKINCARTCTRL_VOCAB_OPT_XDOT
#define IKINCARTCTRL_VOCAB_OPT_TWEAK
#define IKINCARTCTRL_VOCAB_OPT_POSE
#define IKINCARTCTRL_VOCAB_CMD_STOP
#define IKINCARTCTRL_VOCAB_OPT_REGISTER
#define IKINCARTCTRL_VOCAB_VAL_EVENT_ONGOING
#define IKINCARTCTRL_VOCAB_REP_NACK
#define IKINCARTCTRL_VOCAB_OPT_MOTIONDONE
#define CARTCTRL_DEFAULT_TRAJTIME
#define CARTCTRL_DEFAULT_POSCTRL
#define CARTCTRL_CONNECT_SOLVER_PING
#define CARTCTRL_DEFAULT_TASKVEL_PERFACTOR
#define CARTCTRL_SERVER_VER
#define CARTCTRL_DEFAULT_PER
#define CARTCTRL_DEFAULT_MULJNTCTRL
#define CARTCTRL_DEFAULT_TOL
#define CTRL_RAD2DEG
Definition: XSensMTx.cpp:25
#define CTRL_DEG2RAD
Definition: XSensMTx.cpp:26
void onRead(yarp::os::Bottle &command)
CartesianCtrlCommandPort(ServerCartesianController *server)
CartesianCtrlRpcProcessor(ServerCartesianController *server)
bool read(yarp::os::ConnectionReader &connection)
servercartesiancontroller : implements the server part of the Cartesian Interface.
bool tweakSet(const yarp::os::Bottle &options)
yarp::os::BufferedPort< yarp::os::Bottle > portEvent
iCub::iKin::MultiRefMinJerkCtrl * ctrl
bool deleteContexts(yarp::os::Bottle *contextIdList)
std::deque< yarp::dev::IVelocityControl * > lVel
yarp::os::Bottle sendCtrlCmdSingleJointPosition()
yarp::os::BufferedPort< yarp::sig::Vector > portState
void notifyEvent(const std::string &event, const double checkPoint=-1.0)
std::deque< yarp::dev::IPositionControl * > lStp
yarp::os::Bottle sendCtrlCmdMultipleJointsVelocity()
bool askForPosition(const yarp::sig::Vector &xd, yarp::sig::Vector &xdhat, yarp::sig::Vector &odhat, yarp::sig::Vector &qdhat)
std::map< int, Context > contextMap
bool getDOF(yarp::sig::Vector &curDof)
yarp::os::Bottle sendCtrlCmdMultipleJointsPosition()
std::deque< DriverDescriptor > lDsc
bool getRestWeights(yarp::sig::Vector &curRestWeights)
yarp::os::BufferedPort< yarp::os::Bottle > portDebugInfo
CartesianCtrlRpcProcessor * rpcProcessor
bool getTipFrame(yarp::sig::Vector &x, yarp::sig::Vector &o)
bool goToPosition(const yarp::sig::Vector &xd, const double t=0.0)
bool attachAll(const yarp::dev::PolyDriverList &p)
std::deque< yarp::dev::IEncodersTimed * > lEnt
iCub::iKin::iKinChain * chainState
bool setLimits(const int axis, const double min, const double max)
double getFeedback(yarp::sig::Vector &_fb)
bool open(yarp::os::Searchable &config)
yarp::os::Bottle sendCtrlCmdSingleJointVelocity()
bool setRestWeights(const yarp::sig::Vector &newRestWeights, yarp::sig::Vector &curRestWeights)
yarp::os::Bottle(ServerCartesianController::* sendCtrlCmd)()
std::multiset< double > motionOngoingEventsCurrent
bool attachTipFrame(const yarp::sig::Vector &x, const yarp::sig::Vector &o)
yarp::os::BufferedPort< yarp::os::Bottle > portSlvOut
bool getTask2ndOptions(yarp::os::Value &v)
std::deque< yarp::dev::IControlMode * > lMod
bool registerEvent(yarp::dev::CartesianEvent &event)
bool getLimits(const int axis, double *min, double *max)
bool unregisterMotionOngoingEvent(const double checkPoint)
std::deque< yarp::dev::IControlLimits * > lLim
void setJointsCtrlMode(const std::vector< int > &jointsToSet)
bool tweakGet(yarp::os::Bottle &options)
bool waitMotionDone(const double period=0.1, const double timeout=0.0)
bool setTask2ndOptions(const yarp::os::Value &v)
bool setInTargetTolHelper(const double tol)
bool respond(const yarp::os::Bottle &command, yarp::os::Bottle &reply)
bool getSolverConvergenceOptions(yarp::os::Bottle &options)
bool setPosePriority(const std::string &p)
bool askForPose(const yarp::sig::Vector &xd, const yarp::sig::Vector &od, yarp::sig::Vector &xdhat, yarp::sig::Vector &odhat, yarp::sig::Vector &qdhat)
bool getTaskVelocities(yarp::sig::Vector &xdot, yarp::sig::Vector &odot)
bool goToPoseSync(const yarp::sig::Vector &xd, const yarp::sig::Vector &od, const double t=0.0)
bool getInfo(yarp::os::Bottle &info)
bool setSolverConvergenceOptions(const yarp::os::Bottle &options)
TaskRefVelTargetGenerator * taskRefVelTargetGen
bool goToPose(const yarp::sig::Vector &xd, const yarp::sig::Vector &od, const double t=0.0)
std::map< std::string, yarp::dev::CartesianEvent * > eventsMap
bool unregisterEvent(yarp::dev::CartesianEvent &event)
bool goTo(unsigned int _ctrlPose, const yarp::sig::Vector &xd, const double t, const bool latchToken=false)
bool areJointsHealthyAndSet(std::vector< int > &jointsToSet)
yarp::os::BufferedPort< yarp::os::Bottle > portSlvIn
bool setTaskVelocities(const yarp::sig::Vector &xdot, const yarp::sig::Vector &odot)
std::multiset< double > motionOngoingEvents
bool goToPositionSync(const yarp::sig::Vector &xd, const double t=0.0)
CartesianCtrlCommandPort * portCmd
bool setRestPos(const yarp::sig::Vector &newRestPos, yarp::sig::Vector &curRestPos)
iCub::iKin::iKinChain * chainPlan
std::deque< yarp::dev::IPositionDirect * > lPos
std::deque< yarp::dev::IEncoders * > lEnc
void stopLimb(const bool execStopPosition=true)
yarp::dev::PolyDriverList drivers
std::condition_variable cv_syncEvent
bool setDOF(const yarp::sig::Vector &newDof, yarp::sig::Vector &curDof)
bool getRestPos(yarp::sig::Vector &curRestPos)
bool getPose(yarp::sig::Vector &x, yarp::sig::Vector &o, yarp::os::Stamp *stamp=NULL)
bool getDesired(yarp::sig::Vector &xdhat, yarp::sig::Vector &odhat, yarp::sig::Vector &qdhat)
bool getJointsVelocities(yarp::sig::Vector &qdot)
bool registerMotionOngoingEvent(const double checkPoint)
std::deque< yarp::dev::IPidControl * > lPid
void configure(const yarp::os::Property &options, iCub::iKin::iKinChain &chain)
yarp::sig::Vector computeCmd(const yarp::sig::Vector &u)
void restart(const yarp::sig::Vector &y0)
void reset(const yarp::sig::Vector &x0)
yarp::sig::Vector integrate(const yarp::sig::Vector &vel)
TaskRefVelTargetGenerator(const double Ts, const yarp::sig::Vector &x0)
A class for defining a saturated integrator based on Tustin formula: .
Definition: pids.h:48
static yarp::os::Bottle * getEndEffectorPoseOption(const yarp::os::Bottle &b)
Retrieves the end-effector pose data.
Definition: iKinHlp.cpp:156
static void addVectorOption(yarp::os::Bottle &b, const int vcb, const yarp::sig::Vector &v)
Definition: iKinHlp.cpp:26
static yarp::os::Bottle * getJointsOption(const yarp::os::Bottle &b)
Retrieves the joints configuration data.
Definition: iKinHlp.cpp:163
static void addModeOption(yarp::os::Bottle &b, const bool tracking)
Appends to a bottle all data needed to change the tracking mode.
Definition: iKinHlp.cpp:127
static void addTargetOption(yarp::os::Bottle &b, const yarp::sig::Vector &xd)
Appends to a bottle all data needed to command a target.
Definition: iKinHlp.cpp:86
static bool getDesiredOption(const yarp::os::Bottle &reply, yarp::sig::Vector &xdhat, yarp::sig::Vector &odhat, yarp::sig::Vector &qdhat)
Definition: iKinHlp.cpp:38
static bool getTokenOption(const yarp::os::Bottle &b, double *token)
Retrieves the token from the bottle.
Definition: iKinHlp.cpp:170
static void addTokenOption(yarp::os::Bottle &b, const double token)
Appends to a bottle a token to be exchanged with the solver.
Definition: iKinHlp.cpp:140
static void addPoseOption(yarp::os::Bottle &b, const unsigned int pose)
Appends to a bottle all data needed to change the pose mode.
Definition: iKinHlp.cpp:114
A class derived from iKinCtrl implementing the multi-referential approach (pdf).
Definition: iKinInv.h:760
void setPlantParameters(const yarp::os::Property &parameters, const std::string &entryTag="dimension")
Allows user to assign values to the parameters of plant under control (for the configuration space on...
Definition: iKinInv.cpp:965
virtual yarp::sig::Vector iterate(yarp::sig::Vector &xd, yarp::sig::Vector &qd, yarp::sig::Vector *xdot_set, const unsigned int verbose)
void add_compensation(const yarp::sig::Vector &comp)
Adds to the controller input a further compensation term.
Definition: iKinInv.cpp:956
double set_execTime(const double _execTime, const bool warn=false)
Sets the task execution time in seconds.
Definition: iKinInv.cpp:942
yarp::sig::Vector get_qdot() const
Returns the actual derivative of joint angles.
Definition: iKinInv.h:913
virtual void set_q(const yarp::sig::Vector &q0)
Sets the joint angles values.
Definition: iKinInv.cpp:934
double get_gamma() const
Returns the parameter gamma which is used to blend the contribute of the task controller versus the c...
Definition: iKinInv.h:901
void set_gamma(double _gamma)
Sets the parameter gamma which is used to blend the contribute of the task controller versus the cont...
Definition: iKinInv.h:934
virtual void restart(const yarp::sig::Vector &q0)
Reinitializes the algorithm's internal state and resets the starting point.
Definition: iKinInv.cpp:885
A class for defining the iCub Arm.
Definition: iKinFwd.h:1194
A class for defining the iCub Leg.
Definition: iKinFwd.h:1349
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
yarp::sig::Matrix getHN() const
Returns HN, the rigid roto-translation matrix from the Nth frame to the end-effector.
Definition: iKinFwd.h:579
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
bool releaseLink(const unsigned int i)
Releases the ith Link.
Definition: iKinFwd.cpp:463
bool setBlockingValue(const unsigned int i, double Ang)
Changes the value of the ith blocked Link.
Definition: iKinFwd.cpp:414
yarp::sig::Vector EndEffPose(const bool axisRep=true)
Returns the coordinates of end-effector.
Definition: iKinFwd.cpp:850
yarp::sig::Vector getAng()
Returns the current free joint angles values.
Definition: iKinFwd.cpp:611
yarp::sig::Vector setAng(const yarp::sig::Vector &q)
Sets the free joint angles to values of q[i].
unsigned int getN() const
Returns the number of Links belonging to the Chain.
Definition: iKinFwd.h:550
unsigned int getDOF() const
Returns the current number of Chain's DOF.
Definition: iKinFwd.h:557
bool blockLink(const unsigned int i, double Ang)
Blocks the ith Link at the a certain value of its joint angle.
Definition: iKinFwd.cpp:394
virtual bool isInTarget()
Checks if the End-Effector is in target.
Definition: iKinInv.h:315
virtual yarp::sig::Matrix get_J() const
Returns the actual Jacobian used in computation.
Definition: iKinInv.h:387
virtual yarp::sig::Vector get_q() const
Returns the actual joint angles values.
Definition: iKinInv.h:375
virtual void setInTargetTol(double tol_x)
Sets tolerance for in-target check (5e-3 by default).
Definition: iKinInv.h:278
unsigned int get_dim() const
Returns the number of Chain DOF.
Definition: iKinInv.h:345
void set_ctrlPose(unsigned int _ctrlPose)
Sets the state of Pose control settings.
Definition: iKinInv.cpp:64
virtual yarp::sig::Vector get_x() const
Returns the actual cartesian position of the End-Effector.
Definition: iKinInv.h:357
virtual double getInTargetTol() const
Returns tolerance for in-target check.
Definition: iKinInv.h:284
A class for defining the versions of the iCub limbs.
Definition: iKinFwd.h:1046
std::string get_version() const
Return the version string.
Definition: iKinFwd.cpp:1600
A class for defining generic Limb.
Definition: iKinFwd.h:874
iKinChain * asChain()
Returns a pointer to the Limb seen as Chain object.
Definition: iKinFwd.h:1013
std::string getType() const
Returns the Limb type as a string.
Definition: iKinFwd.h:1019
bool toLinksProperties(yarp::os::Property &options)
Provides the links attributes listed in a property object.
Definition: iKinFwd.cpp:1443
bool isValid() const
Checks if the limb has been properly configured.
Definition: iKinFwd.h:998
cmd
Definition: dataTypes.h:30
double norm(const yarp::sig::Matrix &M, int col)
Returns the norm of the vector given in the form: matrix(:,col).
#define IKINCTRL_POSE_FULL
Definition: iKinInv.h:37
#define IKINCTRL_POSE_XYZ
Definition: iKinInv.h:38
#define IKINCTRL_POSE_ANG
Definition: iKinInv.h:39
#define IKINSLV_VOCAB_OPT_DOF
Definition: iKinVocabs.h:28
#define IKINSLV_VOCAB_OPT_PRIO
Definition: iKinVocabs.h:27
#define IKINSLV_VOCAB_VAL_PRIO_XYZ
Definition: iKinVocabs.h:42
#define IKINSLV_VOCAB_VAL_MODE_TRACK
Definition: iKinVocabs.h:44
#define IKINSLV_VOCAB_VAL_MODE_SINGLE
Definition: iKinVocabs.h:45
#define IKINSLV_VOCAB_OPT_Q
Definition: iKinVocabs.h:32
#define IKINSLV_VOCAB_OPT_CONVERGENCE
Definition: iKinVocabs.h:39
#define IKINSLV_VOCAB_OPT_MODE
Definition: iKinVocabs.h:25
#define IKINSLV_VOCAB_CMD_SET
Definition: iKinVocabs.h:17
#define IKINSLV_VOCAB_CMD_ASK
Definition: iKinVocabs.h:18
#define IKINSLV_VOCAB_REP_ACK
Definition: iKinVocabs.h:48
#define IKINSLV_VOCAB_OPT_REST_POS
Definition: iKinVocabs.h:35
#define IKINSLV_VOCAB_OPT_TIP_FRAME
Definition: iKinVocabs.h:37
#define IKINSLV_VOCAB_CMD_GET
Definition: iKinVocabs.h:16
#define IKINSLV_VOCAB_OPT_LIM
Definition: iKinVocabs.h:29
#define IKINSLV_VOCAB_OPT_TASK2
Definition: iKinVocabs.h:38
#define IKINSLV_VOCAB_OPT_REST_WEIGHTS
Definition: iKinVocabs.h:36
#define IKINSLV_VOCAB_REP_NACK
Definition: iKinVocabs.h:49
#define IKINSLV_VOCAB_OPT_X
Definition: iKinVocabs.h:31
#define IKINSLV_VOCAB_VAL_PRIO_ANG
Definition: iKinVocabs.h:43
#define IKINSLV_VOCAB_OPT_XD
Definition: iKinVocabs.h:30
static string pathToCustomKinFile
Definition: main.cpp:163
bool done
Definition: main.cpp:42
const FSC max
Definition: strain.h:48
const FSC min
Definition: strain.h:49
degrees time
Definition: sine.m:5
yarp::sig::Vector minAbsVels