funny-things
All Modules
main.cpp
1/*
2 * Copyright (C) 2014 iCub Facility - Istituto Italiano di Tecnologia
3 * Author: Ugo Pattacini & Alessandro Roncone
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 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 * Public License for more details
14*/
15
16#include <mutex>
17#include <iostream>
18#include <fstream>
19#include <iomanip>
20#include <string>
21
22#include <yarp/os/all.h>
23#include <yarp/dev/PolyDriver.h>
24#include <yarp/dev/IPositionControl.h>
25#include <yarp/dev/IControlMode.h>
26#include <yarp/dev/IControlLimits.h>
27#include <yarp/math/Rand.h>
28#include <yarp/math/NormRand.h>
29
30#include "iCubBlinker_IDL.h"
31
32using namespace std;
33using namespace yarp::os;
34using namespace yarp::math;
35
36enum InteractionMode
37{
38 INTERACTION_MODE_UNKNOWN=0,
39 INTERACTION_MODE_IDLE, INTERACTION_MODE_CONVERSATION,
40 INTERACTION_MODE_CALIBRATION_CLOSURE,INTERACTION_MODE_CALIBRATION_OPENING
41};
42
43string int2hex(const int _i)
44{
45 std::ostringstream hex;
46 hex << std::hex << _i;
47 return hex.str();
48}
49
50string int2string(const int _a)
51{
52 std::ostringstream ss;
53 ss << _a;
54 return ss.str();
55}
56
57string double2string(const double _a)
58{
59 std::ostringstream ss;
60 ss << _a;
61 return ss.str();
62}
63
64/***************************************************************/
65class Blinker: public RFModule, public iCubBlinker_IDL
66{
67private:
68 // Resource finder used to find for files and configurations:
69 ResourceFinder* rf;
70 // PolyDriver and interface to command the eyelids in the rfe robots
71 yarp::dev::PolyDriver _poly;
72 yarp::dev::IPositionControl* _iPos{ nullptr };
73 double _minPoly{ 0.0 }, _maxPoly{ 0.0 };
74 // TODO check if it is correct
75 size_t _joint_eylids{ 0 };
76
77 string name;
78 string robot;
79
80 bool doubleBlink;
81 string blinkingBehavior;
82 string blinkingPeriod;
83
84 Port emotionsPort;
85 RpcServer rpcPort;
86
87 mutex mtx;
88 bool isBlinking;
89
90 double dt;
91 double t0;
92 int doubleBlinkCnt;
93
94 int sMin;
95 int sMax;
96
97 InteractionMode int_mode;
98 double fixed_blinkper;
99
100 double blinkper_nrm, blinkper_sgm; // period of the blinking
101 double closure_nrm, closure_sgm; // closure statistics
102 double sustain_nrm, sustain_sgm; // sustain statistics
103 double opening_nrm, opening_sgm; // opening statistics
104
105 /***************************************************************/
106 bool sendRawValue(const string &_value)
107 {
108 if (emotionsPort.getOutputCount()>0)
109 {
110 Bottle cmd;
111 cmd.addString(_value);
112 emotionsPort.write(cmd);
113
114 return true;
115 }
116 else
117 return false;
118 }
119
120 /***************************************************************/
121 bool doBlink()
122 {
123 if (blinkingBehavior=="naturalistic")
124 {
125 return doBlinkNaturalistic();
126 }
127 else if (blinkingBehavior=="fast")
128 {
129 return doBlinkFast();
130 }
131 else
132 {
133 yError("Blinking behavior is neither naturalistic or fast!");
134 return false;
135 }
136 }
137
138 /***************************************************************/
139 bool doBlinkFast()
140 {
141 bool res = true;
142
143 if (_iPos) {
144 yDebug()<<"Sending position"<<_maxPoly;
145 res &= _iPos->positionMove(_joint_eylids, _maxPoly); // the max means eyes closed
146 // wait motion done
147 bool motion_done = false;
148 while (!motion_done) {
149 Time::delay(0.001);
150 auto ok = _iPos->checkMotionDone(_joint_eylids, &motion_done);
151 if(!ok) {
152 yError()<<"Unable to check if the motion of the eyelids is done";
153 return false;
154 }
155
156 }
157 yDebug()<<"Sending position"<<_minPoly;
158 res &= _iPos->positionMove(_joint_eylids, _minPoly); // the min means eyes opened
159 }
160 else {
161 yDebug("Sending raw value: %i",sMin);
162 res = res && sendRawValue(("S" + int2string(sMin))); // close eyelids
163 Time::delay(0.15);
164 yDebug("Sending raw value: %i",sMax);
165 res = res && sendRawValue(("S" + int2string(sMax))); // open eyelids
166 }
167
168 Time::delay(0.05);
169
170 return res;
171 }
172
173 /***************************************************************/
174 bool doBlinkNaturalistic()
175 {
176 double t_cl = NormRand::scalar(closure_nrm,closure_sgm);
177 // Cut the normal distribution to its first sigma
178 while (t_cl<closure_nrm-closure_sgm || t_cl>closure_nrm+closure_sgm)
179 {
180 t_cl = NormRand::scalar(closure_nrm,closure_sgm);
181 }
182
183 double t_su = NormRand::scalar(sustain_nrm,sustain_sgm);
184 // Cut the normal distribution to its first sigma
185 while (t_su<sustain_nrm-sustain_sgm || t_su>sustain_nrm+sustain_sgm)
186 {
187 t_su = NormRand::scalar(sustain_nrm,sustain_sgm);
188 }
189
190 double t_op = NormRand::scalar(opening_nrm,opening_sgm);
191 // Cut the normal distribution to its first sigma
192 while (t_op<opening_nrm-opening_sgm || t_op>opening_nrm+opening_sgm)
193 {
194 t_op = NormRand::scalar(opening_nrm,opening_sgm);
195 }
196
197 yDebug("Starting a naturalistic blink. T_cl %g \t T_su %g \t T_op %g Total %g",
198 t_cl,t_su,t_op,t_cl+t_su+t_op);
199
200
201 if (_iPos) {
202 // the minimum means fully open, the max means fully closed in the iCub
203 // mounting the rfe board
204 for (int i = 0; i < 11; i++)
205 {
206 auto targetPos = _minPoly + i * (_maxPoly - _minPoly) / 10;
207 string rawvalue = "S" + int2string(targetPos);
208 yDebug() << "Sending postion: " << targetPos << " " << i * 10;
209 _iPos->positionMove(_joint_eylids, targetPos);
210 bool motion_done = false;
211 while (!motion_done) {
212 Time::delay(0.001);
213 auto ok = _iPos->checkMotionDone(_joint_eylids, &motion_done);
214 if(!ok) {
215 yError()<<"Unable to check if the motion of the eyelids is done";
216 return false;
217 }
218
219 }
220 Time::delay(t_op / 10.0);
221 }
222
223 Time::delay(t_su);
224
225 for (int i = 0; i < 11; i++)
226 {
227 auto targetPos = _maxPoly - i * (_maxPoly - _minPoly) / 10;
228 string rawvalue = "S" + int2string(targetPos);
229 yDebug() << "Sending postion: " << targetPos << " " << 100 - i * 10;
230 _iPos->positionMove(_joint_eylids, targetPos);
231 bool motion_done = false;
232 while (!motion_done) {
233 Time::delay(0.001);
234 auto ok = _iPos->checkMotionDone(_joint_eylids, &motion_done);
235 if(!ok) {
236 yError()<<"Unable to check if the motion of the eyelids is done";
237 return false;
238 }
239
240 }
241 Time::delay(t_cl / 10.0);
242 }
243
244 }
245 else {
246 for (int i = 0; i < 11; i++)
247 {
248 int valueToSend = sMax - i * (sMax - sMin) / 10;
249 string rawvalue = "S" + int2string(valueToSend);
250 yDebug("Sending raw value: %s %i", rawvalue.c_str(), 100 - i * 10);
251 sendRawValue(rawvalue);
252 Time::delay(t_cl / 10.0);
253 }
254
255 Time::delay(t_su);
256
257 for (int i = 0; i < 11; i++)
258 {
259 int valueToSend = sMin + i * (sMax - sMin) / 10;
260 string rawvalue = "S" + int2string(valueToSend);
261 yDebug("Sending raw value: %s %i", rawvalue.c_str(), i * 10);
262 sendRawValue(rawvalue);
263 Time::delay(t_op / 10.0);
264 }
265 }
266
267 return true;
268 }
269
270 /***************************************************************/
271 bool set_calib_values()
272 {
273 yWarning("[iCubBlinker] Sending calib values does nothing currently!");
274
275 return false;
276 }
277
278 /***************************************************************/
279 bool setInteractionMode_IDLE()
280 {
281 Bottle idle_mode=(rf->findGroup("idle_mode"));
282
283 if (idle_mode.size()>0)
284 {
285 bool res = retrieveInteractionMode_params(idle_mode);
286 if (res)
287 {
288 int_mode = INTERACTION_MODE_IDLE;
289 }
290 return res;
291 }
292 else
293 {
294 yError("[iCubBlinker] no idle_mode group found in .ini file!");
295 return false;
296 }
297
298 return true;
299 }
300
301 /***************************************************************/
302 bool setInteractionMode_CONVERSATION()
303 {
304 Bottle conversation_mode=(rf->findGroup("conversation_mode"));
305
306 if (conversation_mode.size()>0)
307 {
308 bool res = retrieveInteractionMode_params(conversation_mode);
309 if (res)
310 {
311 int_mode = INTERACTION_MODE_CONVERSATION;
312 }
313 return res;
314 }
315 else
316 {
317 yError("[iCubBlinker] no conversation_mode group found in ini file!");
318 return false;
319 }
320
321 return true;
322 }
323
324 /***************************************************************/
325 bool retrieveInteractionMode_params(Bottle &int_mode)
326 {
327 // If the parameters are not found, it will default to the idle mode
328 blinkper_nrm = int_mode.check("blinkper_nrm",Value(5.2)).asFloat64();
329 blinkper_sgm = int_mode.check("blinkper_sgm",Value(3.7)).asFloat64();
330
331 closure_nrm = int_mode.check("closure_nrm",Value(0.111)).asFloat64();
332 closure_sgm = int_mode.check("closure_sgm",Value(0.031)).asFloat64();
333
334 sustain_nrm = int_mode.check("sustain_nrm",Value(0.020)).asFloat64();
335 sustain_sgm = int_mode.check("sustain_sgm",Value(0.005)).asFloat64();
336
337 opening_nrm = int_mode.check("opening_nrm",Value(0.300)).asFloat64();
338 opening_sgm = int_mode.check("opening_sgm",Value(0.123)).asFloat64();
339
340 return true;
341 }
342
343 /***************************************************************/
344 string InteractionMode_params_toString()
345 {
346 stringstream res;
347
348 res << "[" << name << "] blinker period:\t[ nrm " << blinkper_nrm << "\tsgm " << blinkper_sgm << " ]" << endl;
349 res << "[" << name << "] closure speed: \t[ nrm " << closure_nrm << "\tsgm " << closure_sgm << " ]" << endl;
350 res << "[" << name << "] sustain speed: \t[ nrm " << sustain_nrm << "\tsgm " << sustain_sgm << " ]" << endl;
351 res << "[" << name << "] opening speed: \t[ nrm " << opening_nrm << "\tsgm " << opening_sgm << " ]" << endl;
352
353 return res.str();
354 }
355
356 /***************************************************************/
357 bool computeNextBlinkPeriod()
358 {
359 if (blinkingPeriod=="fixed")
360 {
361 dt=fixed_blinkper;
362 yInfo("[iCubBlinker] Next blink in %g [s]",dt);
363 return true;
364 }
365 else if (blinkingPeriod=="gaussian")
366 {
367 dt=1e9;
368 int i=0;
369
370 // Cut the normal distribution to its first sigma
371 while (dt<blinkper_nrm-blinkper_sgm || dt>blinkper_nrm+blinkper_sgm)
372 {
373 dt = NormRand::scalar(blinkper_nrm,blinkper_sgm);
374 yDebug("[iCubBlinker] Computing next blink.. %g %g %g %i",dt,blinkper_nrm-blinkper_sgm,blinkper_nrm+blinkper_sgm,i); i++;
375 }
376 yInfo("[iCubBlinker] Next blink in %g [s]",dt);
377 return true;
378 }
379 else
380 {
381 yError("blinkingPeriod was neither gaussian nor fixed!");
382 return false;
383 }
384 }
385
386public:
387 /***************************************************************/
388 bool configure(ResourceFinder &_mainRF)
389 {
390 rf = const_cast<ResourceFinder*>(&_mainRF);
391
392 name =rf->check("name", Value("iCubBlinker")).asString().c_str();
393 robot=rf->check("robot",Value("icub")).asString().c_str();
394 blinkingBehavior=rf->check("blinkingBehavior",Value("fast")).asString().c_str();
395 blinkingPeriod=rf->check("blinkingPeriod",Value("fixed")).asString().c_str();
396 fixed_blinkper=rf->check("fixedBlinkPer",Value(5.0)).asFloat64();
397
398 isBlinking=rf->check("autoStart");
399
400 yarp::os::Property rcb_face_conf{ {"device",Value("remote_controlboard")},
401 {"local", Value(getName("/face/remoteControlBoard"))},
402 {"remote",Value("/icub/face")},
403 {"part",Value("face")} };
404
405 if (_poly.open(rcb_face_conf))
406 {
407 yarp::dev::IControlMode* iCM{ nullptr };
408 yarp::dev::IControlLimits* iCtrlLim{ nullptr };
409 auto ok = _poly.view(iCM);
410 ok &= _poly.view(_iPos);
411 ok &= _poly.view(iCtrlLim);
412 if (iCM)
413 ok &= iCM->setControlMode(_joint_eylids, VOCAB_CM_POSITION); // TODO, maybe it is better POSITION_DIRECT?
414 if (iCtrlLim) {
415 ok &= iCtrlLim->getLimits(_joint_eylids, &_minPoly, &_maxPoly);
416 _maxPoly = _maxPoly - 25.0; // safe zone for avoiding hw fault
417 }
418 if (_iPos) {
419 ok &= _iPos->setRefSpeed(_joint_eylids, 50.0); // max velocity that doesn't give problems
420 ok &= _iPos->setRefAcceleration(_joint_eylids, std::numeric_limits<double>::max());
421 }
422 if (!ok)
423 {
424 yError() << "Fail to configure correctly the remote_controlboard";
425 return false;
426 }
427 }
428 else
429 {
430 yWarning() << "Failed to open the remote_controlboard device for commanding the eyelids, you can ignore this warning if your robot doesn't have the rfe board";
431 auto ok = emotionsPort.open(("/" + name + "/emotions/raw").c_str());
432 if (rf->check("autoConnect"))
433 {
434 ok &= Network::connect(emotionsPort.getName().c_str(), "/" + robot + "/face/raw/in");
435 }
436 if (!ok)
437 {
438 yError() << "Configuration phase failed, please check if yarprobotinterface (iCub with RFE) or the the serial device (iCub without RFE) are running.";
439 return false;
440 }
441 }
442
443
444
445 doubleBlink=rf->check("doubleBlink");
446
447 rpcPort.open(("/"+name+"/rpc").c_str());
448 attach(rpcPort);
449
450 Bottle calib=(rf->findGroup("calibration"));
451
452 if (calib.size() > 0)
453 {
454 sMin = calib.check("sMin",Value(00)).asInt32();
455 sMax = calib.check("sMax",Value(70)).asInt32();
456
457 yInfo("[iCubBlinker] Eyelid calibs loaded: (%i %i)", sMin, sMax);
458 }
459 else
460 {
461 sMin = 00;
462 sMax = 70;
463 }
464
465 Rand::init();
466 NormRand::init();
467 doubleBlinkCnt=0;
468
469 int_mode = INTERACTION_MODE_IDLE;
470 set_interaction_mode("idle");
471
472 computeNextBlinkPeriod();
473 t0=Time::now();
474
475 print_params();
476
477 return true;
478 }
479
480 /************************************************************************/
481 bool attach(RpcServer &source)
482 {
483 return this->yarp().attachAsServer(source);
484 }
485
486 /***************************************************************/
487 bool close()
488 {
489 if (_poly.isValid())
490 {
491 _poly.close();
492 _iPos = nullptr;
493 }
494 emotionsPort.close();
495 rpcPort.close();
496 return true;
497 }
498
499 /***************************************************************/
500 double getPeriod() { return 0.01; }
501
502 bool start()
503 {
504 yInfo("[iCubBlinker] start command received");
505 isBlinking=true;
506 return true;
507 }
508
509 bool stop()
510 {
511 yInfo("[iCubBlinker] stop command received");
512 isBlinking=false;
513 return true;
514 }
515
516 string status()
517 {
518 string res=isBlinking?"on":"off";
519 res=res+"_"+get_interaction_mode();
520 return res;
521 }
522
523 bool blink_single()
524 {
525 t0=Time::now();
526 return doBlink();
527 }
528
529 bool blink_fast()
530 {
531 t0=Time::now();
532 return doBlinkFast();
533 }
534
535 bool blink_naturalistic()
536 {
537 t0=Time::now();
538 return doBlinkNaturalistic();
539 }
540
541 bool dblink()
542 {
543 t0=Time::now();
544 return doBlink() && doBlink();
545 }
546
547 /***************************************************************/
548 string print_params()
549 {
550 stringstream res;
551
552 res << endl;
553 res << "[" << name << "] robot: " << robot << endl;
554 res << "[" << name << "] blinkingBehavior: " << blinkingBehavior;
555 res << "\tblinkingPeriod: " << blinkingPeriod << "\tFixed Blink period: " << fixed_blinkper << endl;
556 res << "[" << name << "] isBlinking: " << (isBlinking?"true":"false") << "\tdoubleBlink: " << get_double_blink() << endl;
557 res << "[" << name << "] calibration [sMin sMax]: [" << sMin << " " << sMax << "]" << endl;
558 res << "[" << name << "] InteractionMode: " << get_interaction_mode() << endl;
559 res << InteractionMode_params_toString();
560
561 printf("%s\n", res.str().c_str());
562
563 return res.str();
564 }
565
566 /***************************************************************/
567 string save()
568 {
569 string path = rf->getHomeContextPath().c_str();
570 string inifile = path+"/"+rf->find("from").asString();
571 yInfo("Saving calib configuration to %s",inifile.c_str());
572
573 ofstream myfile;
574 myfile.open(inifile.c_str(),ios::trunc);
575
576 if (myfile.is_open())
577 {
578 myfile << "name \t" << name << endl;
579 myfile << "robot \t" << robot << endl;
580 if (rf->check("autoStart"))
581 {
582 myfile << "autoStart" << endl;
583 }
584 myfile << "calib \t(" << sMin << "\t" << sMax << ")\n";
585 }
586 myfile.close();
587 return inifile;
588 }
589
590 /***************************************************************/
591 string load()
592 {
593 string fileName=rf->findFile(rf->find("from").asString().c_str());
594 if (fileName=="")
595 {
596 yWarning("[iCubBlinker::load] No filename has been found. Skipping..");
597 return string("");
598 }
599
600 yInfo("[iCubBlinker::load] File loaded: %s", fileName.c_str());
601 yWarning("[iCubBlinker::load] Only the calib values will be loaded.");
602 Property data; data.fromConfigFile(fileName.c_str());
603 Bottle b; b.read(data);
604 Bottle calib=(b.findGroup("calibration"));
605
606 if (calib.size() > 0)
607 {
608 sMin = calib.check("sMin",Value(00)).asInt32();
609 sMax = calib.check("sMax",Value(70)).asInt32();
610
611 yInfo("[iCubBlinker::load] Eyelid calibs loaded: (%i %i)", sMin, sMax);
612
613 return fileName;
614 }
615
616 // set_calib_values();
617
618 return string("");
619 }
620
621 /***************************************************************/
622 bool set_interaction_mode(const std::string& val)
623 {
624 bool res = false;
625
626 if (val == "idle")
627 {
628 res = setInteractionMode(INTERACTION_MODE_IDLE);
629 }
630 else if (val == "conversation")
631 {
632 res = setInteractionMode(INTERACTION_MODE_CONVERSATION);
633 }
634
635 yInfo("[iCubBlinker] Interaction mode set to %s",get_interaction_mode().c_str());
636 printf("%s\n",InteractionMode_params_toString().c_str());
637
638 return res;
639 }
640
641 /***************************************************************/
642 bool setInteractionMode(InteractionMode _int_mode)
643 {
644 if (_int_mode==INTERACTION_MODE_IDLE)
645 {
646 return setInteractionMode_IDLE();
647 }
648 else if (_int_mode==INTERACTION_MODE_CONVERSATION)
649 {
650 return setInteractionMode_CONVERSATION();
651 }
652 else
653 {
654 int_mode = _int_mode;
655 return true;
656 }
657 }
658
659 /***************************************************************/
660 string get_interaction_mode()
661 {
662 if (int_mode == INTERACTION_MODE_UNKNOWN)
663 {
664 return "interaction_mode_unknown";
665 }
666 else if (int_mode == INTERACTION_MODE_IDLE)
667 {
668 return "idle";
669 }
670 else if (int_mode == INTERACTION_MODE_CONVERSATION)
671 {
672 return "conversation";
673 }
674 else if (int_mode == INTERACTION_MODE_CALIBRATION_OPENING ||
675 int_mode == INTERACTION_MODE_CALIBRATION_CLOSURE)
676 {
677 return "calibration";
678 }
679
680 return string("");
681 }
682
683 /***************************************************************/
684 bool calib()
685 {
686 yError("Not yet implemented!");
687 return false;
688 }
689
690 /***************************************************************/
691 bool set_blinking_behavior(const std::string& val)
692 {
693 bool res=false;
694
695 if (val=="naturalistic" || val=="fast")
696 {
697 blinkingBehavior=val;
698 res=true;
699 }
700 else
701 {
702 yError("Invalid blinking behavior requested! %s",val.c_str());
703 }
704
705 yInfo("Blinking behavior set to %s",get_blinking_behavior().c_str());
706
707 return res;
708 }
709
710 /***************************************************************/
711 string get_blinking_behavior()
712 {
713 return blinkingBehavior;
714 }
715
716 /***************************************************************/
717 bool set_blinking_period(const std::string& val)
718 {
719 bool res=false;
720
721 if (val=="gaussian" || val=="fixed")
722 {
723 blinkingPeriod=val;
724 res=true;
725 }
726 else
727 {
728 yError("Invalid blinking period requested! %s",val.c_str());
729 }
730
731 yInfo("Blinking period set to %s",get_blinking_period().c_str());
732
733 return res;
734 }
735
736 /***************************************************************/
737 string get_blinking_period()
738 {
739 if (blinkingPeriod=="gaussian")
740 {
741 return blinkingPeriod;
742 }
743 else
744 {
745 return blinkingPeriod + " (" + double2string(fixed_blinkper) + " [s])";
746 }
747 }
748
749 /***************************************************************/
750 bool set_double_blink(const string &val)
751 {
752 if (val=="on")
753 {
754 doubleBlink=true;
755 }
756 else if (val=="off")
757 {
758 doubleBlink=false;
759 }
760 else
761 {
762 return false;
763 }
764
765 return true;
766 }
767
768 /***************************************************************/
769 string get_double_blink()
770 {
771 return (doubleBlink?"on":"off");
772 }
773
774 /***************************************************************/
775 bool updateModule()
776 {
777 lock_guard<mutex> lg(mtx);
778
779 if (Time::now()-t0>=dt)
780 {
781 if (isBlinking)
782 {
783 doBlink();
784 if (doubleBlink)
785 {
786 if ((++doubleBlinkCnt)%5==0)
787 {
788 doBlink();
789 doubleBlinkCnt=0;
790 }
791 }
792
793 computeNextBlinkPeriod();
794 t0=Time::now();
795 }
796 }
797
798 return true;
799 }
800};
801
802/***************************************************************/
803int main(int argc, char *argv[])
804{
805 ResourceFinder rf;
806 rf.setDefaultContext("funny-things");
807 rf.setDefaultConfigFile("iCubBlinker.ini");
808 rf.configure(argc,argv);
809
810 if (rf.check("help"))
811 {
812 printf("\n");
813 yInfo("[ICUB BLINKER] Options:");
814 yInfo(" --context path: where to find the called resource (default funnyThings).");
815 yInfo(" --from from: the name of the .ini file (default iCubBlinker.ini).");
816 yInfo(" --name name: the name of the module (default iCubBlinker).");
817 yInfo(" --robot robot: the name of the robot. Default icub.");
818 yInfo(" --autoStart flag: If the module should autostart the blinking behavior. Default no.");
819 yInfo(" --autoConnect flag: If the module should autoconnect itself to the face expression port. Default no.");
820 yInfo(" --blinkingBehavior string: String that specifies the desired blinking behavior (either naturalistic or fast).");
821 yInfo(" --blinkingPeriod string: String that specifies the desired blinking period (either gaussian or fixed).");
822 yInfo(" --fixedBlinkPer double: the blinking period in case of fixed blinkingPeriod (default 5.0).");
823 yInfo(" --calibration::sMin int: Manually set the minimum value for the blinking behavior (default 00).");
824 yInfo(" --calibration::sMax int: Manually set the maximum value for the blinking behavior (default 70).");
825 printf("\n");
826 return 0;
827 }
828
829 Network yarp;
830 if (!yarp.checkNetwork())
831 {
832 yError("YARP server not available!");
833 return 1;
834 }
835
836 Blinker blinker;
837 return blinker.runModule(rf);
838}
839
840