iCub-main
Loading...
Searching...
No Matches
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
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
42using namespace std;
43using namespace yarp::os;
44using namespace yarp::dev;
45using namespace yarp::sig;
46using namespace yarp::math;
47using namespace iCub::ctrl;
48using namespace iCub::iKin;
49
50
51/************************************************************************/
56
57
58/************************************************************************/
59bool 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/************************************************************************/
79
80
81/************************************************************************/
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/************************************************************************/
146{
147 yAssert(x0.length()>=7);
148 I->reset(x0.subVector(0,2));
149 R=axis2dcm(x0.subVector(3,6));
150}
151
152
153/************************************************************************/
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/************************************************************************/
169
170
171/************************************************************************/
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;
194 ctrl=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;
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
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
279 {
280 portDebugInfo.interrupt();
281 portDebugInfo.close();
282 }
283
284 delete rpcProcessor;
285 connected=false;
286}
287
288
289/************************************************************************/
290bool 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())
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);
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
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);
1164 velCmd.resize(chainState->getDOF(),0.0);
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/************************************************************************/
1319void 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/************************************************************************/
1540void 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)
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
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 {
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/************************************************************************/
1768bool 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")
1967 else if (kinPart=="leg")
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
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/************************************************************************/
2033bool 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
2194
2195 // create controller
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;
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 {
2311 }
2312 else
2313 {
2315 chainPlan->blockLink(i);
2316 }
2317 }
2318
2320 return true;
2321 }
2322 else
2323 return false;
2324}
2325
2326
2327/************************************************************************/
2328bool 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)
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 {
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 {
2424 return true;
2425 }
2426 else
2427 return false;
2428}
2429
2430
2431/************************************************************************/
2433{
2434 if (attached && (f!=NULL))
2435 {
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/************************************************************************/
2494bool 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/************************************************************************/
2521bool 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/************************************************************************/
2554bool 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/************************************************************************/
2577bool 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/************************************************************************/
2592bool ServerCartesianController::goToPoseSync(const Vector &xd, const Vector &od,
2593 const double t)
2594{
2595 return goToPose(xd,od,t);
2596}
2597
2598
2599/************************************************************************/
2600bool ServerCartesianController::goToPositionSync(const Vector &xd, const double t)
2601{
2602 return goToPosition(xd,t);
2603}
2604
2605
2606/************************************************************************/
2607bool 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/************************************************************************/
2642bool 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/************************************************************************/
2675bool 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/************************************************************************/
2709bool 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/************************************************************************/
2734bool 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/************************************************************************/
2779bool 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 {
2807 }
2808 else
2809 {
2811 chainPlan->blockLink(i);
2812 }
2813 }
2814
2815 // update controller
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/************************************************************************/
2862bool 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/************************************************************************/
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/************************************************************************/
2928bool 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/************************************************************************/
2962bool 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/************************************************************************/
2993bool 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/************************************************************************/
3129bool 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/************************************************************************/
3204bool 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
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();
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);
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/************************************************************************/
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/************************************************************************/
3805bool 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/************************************************************************/
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
ServerCartesianController * server
void onRead(yarp::os::Bottle &command)
CartesianCtrlCommandPort(ServerCartesianController *server)
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::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
bool setLimits(const int axis, const double min, const double max)
double getFeedback(yarp::sig::Vector &_fb)
bool open(yarp::os::Searchable &config)
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)
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
const yarp::sig::Vector & integrate(const yarp::sig::Vector &x)
Executes one-step integration of input vector.
Definition pids.cpp:115
void reset(const yarp::sig::Vector &y0)
Resets the internal state and sets the output vector to the given value.
Definition pids.cpp:128
double getTs()
Returns the sample time.
Definition pids.h:135
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.
Definition iKinInv.h:759
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:912
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:900
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:933
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:1193
A class for defining the iCub Leg.
Definition iKinFwd.h:1348
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:578
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:549
unsigned int getDOF() const
Returns the current number of Chain's DOF.
Definition iKinFwd.h:556
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:1045
std::string get_version() const
Return the version string.
Definition iKinFwd.cpp:1600
A class for defining generic Limb.
Definition iKinFwd.h:873
std::string getType() const
Returns the Limb type as a string.
Definition iKinFwd.h:1018
bool toLinksProperties(yarp::os::Property &options)
Provides the links attributes listed in a property object.
Definition iKinFwd.cpp:1443
iKinChain * asChain()
Returns a pointer to the Limb seen as Chain object.
Definition iKinFwd.h:1012
bool isValid() const
Checks if the limb has been properly configured.
Definition iKinFwd.h:997
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:161
bool done
Definition main.cpp:42
degrees time
Definition sine.m:5
yarp::sig::Vector minAbsVels