56#include <yarp/os/all.h>
57#include <yarp/sig/all.h>
58#include <yarp/dev/all.h>
59#include <yarp/math/Math.h>
60#include <iCub/action/actionPrimitives.h>
65using namespace yarp::os;
66using namespace yarp::dev;
67using namespace yarp::sig;
68using namespace yarp::math;
69using namespace iCub::action;
73class Gazer :
public PeriodicThread
76 ActionPrimitives *action;
81 Gazer(PolyDriver &driver, ActionPrimitives *action,
const Vector &offset) :
84 driver.view(this->igaze);
94 igaze->lookAtFixationPoint(x+offset);
100class WriterModule:
public RFModule
103 ActionPrimitives *action;
104 PolyDriver driverArm;
105 PolyDriver driverGaze;
111 struct SegmentParameters
118 double cartesian_time;
119 double cartesian_straightness;
122 deque<SegmentParameters> segParams;
123 deque<deque<ActionPrimitivesWayPoint> > wayPoints;
124 Vector stiffness_old,damping_old,orientation;
125 double scale,reach_above,segment_time,cartesian_time,cartesian_straightness;
129 void setStraightness(
const double straightness)
131 ICartesianControl *icart;
132 action->getCartesianIF(icart);
135 Bottle &straightOpt=options.addList();
136 straightOpt.addString(
"straightness");
137 straightOpt.addFloat64(straightness);
138 icart->tweakSet(options);
142 Vector parseDrawing(TiXmlDocument& drawing)
144 SegmentParameters params;
145 params.orientation=orientation;
147 params.reach_above=reach_above;
148 params.segment_time=segment_time;
149 params.cartesian_time=cartesian_time;
150 params.cartesian_straightness=cartesian_straightness;
152 ActionPrimitivesWayPoint wp;
154 wp.trajTime=cartesian_time;
155 wp.duration=segment_time;
160 Vector top_left_corner(2,0.0);
162 TiXmlHandle hText(&drawing);
165 pElem=hText.FirstChildElement().Element();
167 return top_left_corner;
169 string type=pElem->Value();
171 return top_left_corner;
173 pElem=TiXmlHandle(pElem).FirstChildElement().Element();
176 string type=pElem->Value();
179 deque<ActionPrimitivesWayPoint> path;
181 pElem->QueryDoubleAttribute(
"x1",&wp.x[0]);
182 pElem->QueryDoubleAttribute(
"y1",&wp.x[1]);
186 top_left_corner[0]=std::min(top_left_corner[0],wp.x[0]);
187 top_left_corner[1]=std::min(top_left_corner[1],wp.x[1]);
189 pElem->QueryDoubleAttribute(
"x2",&wp.x[0]);
190 pElem->QueryDoubleAttribute(
"y2",&wp.x[1]);
194 top_left_corner[0]=std::min(top_left_corner[0],wp.x[0]);
195 top_left_corner[1]=std::min(top_left_corner[1],wp.x[1]);
198 segParams.push_back(params);
199 wayPoints.push_back(path);
201 else if (type==
"polyline")
203 deque<ActionPrimitivesWayPoint> path;
204 Bottle points(pElem->Attribute(
"points"));
205 wp.duration/=points.size();
207 for (
int i=0; i<points.size(); i+=2)
209 wp.x[0]=scale*points.get(i).asFloat64();
210 wp.x[1]=scale*points.get(i+1).asFloat64();
213 top_left_corner[0]=std::min(top_left_corner[0],wp.x[0]);
214 top_left_corner[1]=std::min(top_left_corner[1],wp.x[1]);
217 params.type=
"polyline";
218 segParams.push_back(params);
219 wayPoints.push_back(path);
222 pElem=pElem->NextSiblingElement();
225 return top_left_corner;
229 void tranformPoints(
const Vector &data_top_left_corner)
231 for (
size_t i=0; i<wayPoints.size(); i++)
233 for (
size_t j=0; j<wayPoints[i].size(); j++)
235 Vector p=wayPoints[i][j].x;
238 p[0]-=data_top_left_corner[0];
239 p[1]-=data_top_left_corner[1];
241 wayPoints[i][j].x=(H*p).subVector(0,2);
242 wayPoints[i][j].x[2]+=segParams[i].delta_z;
250 for (
size_t i=0; i<wayPoints.size(); i++)
252 for (
size_t j=0; j<wayPoints[i].size(); j++)
254 yInfo()<<
"point["<<i<<
"]["<<j<<
"]=("
255 <<wayPoints[i][j].x.toString(3,3).c_str()<<
")";
265 if (gazer->isSuspended())
271 Vector torsoEnabled,torsoDisabled(3,0.0);
272 action->getTorsoJoints(torsoEnabled);
274 Vector x,o,x_offset(3,0.0);
278 for (i=0; i<wayPoints.size(); i++)
280 setStraightness(segParams[i].cartesian_straightness);
282 action->getPose(x,o);
283 x_offset[2]=segParams[i].reach_above;
284 action->pushAction(x+x_offset,segParams[i].orientation);
285 action->pushAction(wayPoints[i][0].x+x_offset,segParams[i].orientation);
286 action->pushAction(wayPoints[i][0].x,segParams[i].orientation);
288 action->checkActionsDone(done,
true);
292 action->setTorsoJoints(torsoDisabled);
293 action->pushAction(wayPoints[i]);
295 action->checkActionsDone(done,
true);
296 action->setTorsoJoints(torsoEnabled);
302 action->getPose(x,o);
303 x_offset[2]=segParams[i].reach_above;
304 action->pushAction(x+x_offset,segParams[i].orientation);
314 WriterModule() : action(NULL), gazer(NULL), interrupting(false) { }
317 bool configure(ResourceFinder &rf)
319 string name=rf.find(
"name").asString().c_str();
320 setName(name.c_str());
322 string partUsed=rf.find(
"part").asString().c_str();
323 if ((partUsed!=
"left_arm") && (partUsed!=
"right_arm"))
325 yError()<<
"invalid part requested!";
329 Property config; config.fromConfigFile(rf.findFile(
"from").c_str());
330 Bottle &bGeneral=config.findGroup(
"general");
331 if (bGeneral.isNull())
333 yError()<<
"group \"general\" is missing!";
337 Property option(bGeneral.toString().c_str());
338 option.put(
"local",name.c_str());
339 option.put(
"part",partUsed.c_str());
340 option.put(
"grasp_model_type",rf.find(
"grasp_model_type").asString().c_str());
341 option.put(
"grasp_model_file",rf.findFile(
"grasp_model_file").c_str());
342 option.put(
"hand_sequences_file",rf.findFile(
"hand_sequences_file").c_str());
344 Bottle &bWriting=config.findGroup(
"writing_general");
345 if (bWriting.isNull())
347 yError()<<
"group \"writing_general\" is missing!";
351 scale=bWriting.check(
"scale",Value(1.0)).asFloat64();
352 scale*=bWriting.check(
"conversion",Value(1.0)).asFloat64();
353 reach_above=bWriting.check(
"reach_above",Value(0.05)).asFloat64();
354 segment_time=bWriting.check(
"segment_time",Value(1.0)).asFloat64();
355 cartesian_time=bWriting.check(
"cartesian_time",Value(1.0)).asFloat64();
356 cartesian_straightness=bWriting.check(
"cartesian_straightness",Value(1.0)).asFloat64();
358 orientation.resize(4,0.0);
359 if (Bottle *pB=bWriting.find(
"orientation").asList())
361 int len=std::min(orientation.length(),pB->size());
362 for (
int i=0; i<len; i++)
363 orientation[i]=pB->get(i).asFloat64();
366 Vector top_left_corner(3,0.0);
367 if (Bottle *pB=bWriting.find(
"top_left_corner").asList())
369 int len=std::min(top_left_corner.length(),pB->size());
370 for (
int i=0; i<len; i++)
371 top_left_corner[i]=pB->get(i).asFloat64();
373 top_left_corner.push_back(1.0);
376 H(0,1)=1.0; H(1,0)=1.0; H(2,2)=-1.0;
377 H.setCol(3,top_left_corner);
379 TiXmlDocument drawing(rf.findFile(
"drawing").c_str());
380 if (!drawing.LoadFile())
386 Vector data_top_left_corner=parseDrawing(drawing);
387 for (
size_t i=0; i<wayPoints.size(); i++)
389 ostringstream segment_tag;
390 segment_tag<<
"writing_segment_"<<i;
391 Bottle &bSegment=config.findGroup(segment_tag.str().c_str());
392 if (!bSegment.isNull())
394 if (Bottle *pB=bSegment.find(
"orientation").asList())
396 int len=std::min(orientation.length(),pB->size());
397 for (
int j=0; j<len; j++)
398 segParams[i].orientation[j]=pB->get(j).asFloat64();
401 segParams[i].delta_z=bSegment.check(
"delta_z",Value(segParams[i].delta_z)).asFloat64();
402 segParams[i].reach_above=bSegment.check(
"reach_above",Value(segParams[i].reach_above)).asFloat64();
403 segParams[i].segment_time=bSegment.check(
"segment_time",Value(segParams[i].segment_time)).asFloat64();
404 segParams[i].cartesian_time=bSegment.check(
"cartesian_time",Value(segParams[i].cartesian_time)).asFloat64();
405 segParams[i].cartesian_straightness=bSegment.check(
"cartesian_straightness",Value(segParams[i].cartesian_straightness)).asFloat64();
407 for (
size_t j=0; j<wayPoints[i].size(); j++)
409 wayPoints[i][j].o=segParams[i].orientation;
410 wayPoints[i][j].trajTime=segParams[i].cartesian_time;
411 wayPoints[i][j].duration=segParams[i].segment_time;
412 if (segParams[i].type!=
"line")
413 wayPoints[i][j].duration/=wayPoints[i].size();
418 tranformPoints(data_top_left_corner);
421 yInfo()<<
"***** Instantiating primitives for "<<partUsed;
422 action=
new ActionPrimitives(option);
423 if (!action->isValid())
429 setStraightness(cartesian_straightness);
432 Bottle &bImpedance=config.findGroup(
"impedance");
433 if (!bImpedance.isNull())
435 impedanceOn=bImpedance.check(
"enable",Value(
"off")).asString()==
"on";
438 Vector stiffness(5,0.0);
439 if (Bottle *pB=bImpedance.find(
"stiffness").asList())
441 int len=std::min(stiffness.length(),pB->size());
442 for (
int i=0; i<len; i++)
443 stiffness[i]=pB->get(i).asFloat64();
446 Vector damping(stiffness.length(),0.0);
447 if (Bottle *pB=bImpedance.find(
"damping").asList())
449 int len=std::min(damping.length(),pB->size());
450 for (
int i=0; i<len; i++)
451 damping[i]=pB->get(i).asFloat64();
454 string robot=bGeneral.check(
"robot",Value(
"icub")).asString().c_str();
455 Property driverOption(
"(device remote_controlboard)");
456 driverOption.put(
"remote",(
"/"+robot+
"/"+partUsed).c_str());
457 driverOption.put(
"local",(
"/"+name+
"/impedance").c_str());
458 if (driverArm.open(driverOption))
460 IInteractionMode *imod;
461 IImpedanceControl *iimp;
463 driverArm.view(imod);
464 driverArm.view(iimp);
466 size_t len=std::min(stiffness.length(),damping.length());
467 stiffness_old.resize(len); damping_old.resize(len);
468 for (
size_t i=0; i<len; i++)
470 iimp->getImpedance(i,&stiffness_old[i],&damping_old[i]);
471 iimp->setImpedance(i,stiffness[i],damping[i]);
472 imod->setInteractionMode(i,VOCAB_IM_COMPLIANT);
483 Bottle &bGaze=config.findGroup(
"gaze");
486 if (bGaze.check(
"enable",Value(
"off")).asString()==
"on")
488 Vector offset(3,0.0);
489 if (Bottle *pB=bGaze.find(
"offset").asList())
491 int len=std::min(offset.length(),pB->size());
492 for (
int i=0; i<len; i++)
493 offset[i]=pB->get(i).asFloat64();
496 Property driverOption(
"(device gazecontrollerclient)");
497 driverOption.put(
"remote",
"/iKinGazeCtrl");
498 driverOption.put(
"local",(
"/"+name+
"/gaze").c_str());
499 if (driverGaze.open(driverOption))
500 gazer=
new Gazer(driverGaze,action,offset);
509 rpcPort.open((
"/"+name+
"/rpc").c_str());
516 bool respond(
const Bottle &command, Bottle &reply)
518 int ack=Vocab32::encode(
"ack");
519 int nack=Vocab32::encode(
"nack");
521 if (command.size()>0)
523 switch (command.get(0).asVocab32())
526 case createVocab32(
'g',
'o'):
529 reply.addVocab32(ack);
531 reply.addVocab32(nack);
538 return RFModule::respond(command,reply);
542 reply.addVocab32(nack);
559 bool interruptModule()
562 action->syncCheckInterrupt(
true);
573 if (driverArm.isValid())
577 IInteractionMode *imod;
578 IImpedanceControl *iimp;
580 driverArm.view(imod);
581 driverArm.view(iimp);
583 for (
size_t i=0; i<stiffness_old.length(); i++)
585 imod->setInteractionMode(i,VOCAB_IM_STIFF);
586 iimp->setImpedance(i,stiffness_old[i],damping_old[i]);
593 if (driverGaze.isValid())
607int main(
int argc,
char *argv[])
610 if (!yarp.checkNetwork())
612 yError()<<
"YARP server not available!";
617 rf.setDefaultContext(
"funny-things");
618 rf.setDefaultConfigFile(
"iCubWriter.ini");
619 rf.setDefault(
"part",
"right_arm");
620 rf.setDefault(
"grasp_model_type",
"springy");
621 rf.setDefault(
"grasp_model_file",
"grasp_model.ini");
622 rf.setDefault(
"hand_sequences_file",
"hand_sequences.ini");
623 rf.setDefault(
"drawing",
"drawings/icub.svg");
624 rf.setDefault(
"name",
"iCubWriter");
625 rf.configure(argc,argv);
628 return mod.runModule(rf);