iCub-main
Loading...
Searching...
No Matches
skinManager.cpp
Go to the documentation of this file.
1
2/*
3 * Copyright (C) 2009 RobotCub Consortium, European Commission FP6 Project IST-004370
4 * Authors: Andrea Del Prete, Alexander Schmitz
5 * email: andrea.delprete@iit.it, alexander.schmitz@iit.it
6 * website: www.robotcub.org
7 * Permission is granted to copy, distribute, and/or modify this program
8 * under the terms of the GNU General Public License, version 2 or any
9 * later version published by the Free Software Foundation.
10 *
11 * A copy of the license can be found at
12 * http://www.robotcub.org/icub/license/gpl.txt
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details
18 */
19
20#include <sstream> // string stream
21#include <yarp/os/Log.h>
22#include <yarp/os/LogStream.h>
24
25using std::string;
26using std::vector;
27
28using yarp::os::Bottle;
29using yarp::sig::Vector;
30
31using namespace iCub::skinManager;
32
33// module default values
34const int skinManager::MIN_BASELINE_DEFAULT = 3;
35const int skinManager::ADD_THRESHOLD_DEFAULT = 2;
36const int skinManager::PERIOD_DEFAULT = 50;
37const bool skinManager::SMOOTH_FILTER_DEFAULT = false;
38const float skinManager::SMOOTH_FACTOR_DEFAULT = 0.5;
39const float skinManager::COMPENSATION_GAIN_DEFAULT = 0.2f;
40const float skinManager::CONTACT_COMPENSATION_GAIN_DEFAULT = 0.0f;
41const string skinManager::MODULE_NAME_DEFAULT = "skinManager";
42const string skinManager::ROBOT_NAME_DEFAULT = "icub";
43const bool skinManager::ZERO_UP_RAW_DATA_DEFAULT = false;
44const bool skinManager::BINARIZATION_DEFAULT = false;
45const string skinManager::RPC_PORT_DEFAULT = "/rpc";
46
47bool skinManager::configure(yarp::os::ResourceFinder &rf) {
48 /* Process all parameters from both command-line and .ini file */
49
50 /* get the module name which will form the stem of all module port names */
51 moduleName = rf.check("name", Value(MODULE_NAME_DEFAULT.c_str()), "module name (string)").asString();
52 robotName = rf.check("robot", Value(ROBOT_NAME_DEFAULT.c_str()), "name of the robot (string)").asString();
53 /* before continuing, set the module name before getting any other parameters,
54 * specifically the port names which are dependent on the module name*/
55 setName(moduleName.c_str());
56
57 /* get some other values from the configuration file */
58 int period = (int)rf.check("period", Value(PERIOD_DEFAULT),
59 "Period of the thread in ms (positive int)").asInt32();
60 float minBaseline = (float)rf.check("minBaseline", Value(MIN_BASELINE_DEFAULT),
61 "If the baseline reaches this value then, if allowed, a calibration is executed (float in [0,255])").asFloat64();
62 float compGain = (float)rf.check("compensationGain", Value(COMPENSATION_GAIN_DEFAULT),
63 "Gain of the compensation algorithm (float)").asFloat64();
64 float contCompGain = (float)rf.check("contactCompensationGain", Value(CONTACT_COMPENSATION_GAIN_DEFAULT),
65 "Gain of the compensation algorithm during contact (float)").asFloat64();
66 int addThreshold = (int)rf.check("addThreshold", Value(ADD_THRESHOLD_DEFAULT),
67 "Value added to all the touch thresholds (positive int)").asInt32();
68
69 bool zeroUpRawData = rf.check("zeroUpRawData", Value(ZERO_UP_RAW_DATA_DEFAULT),
70 "if true the raw data are considered from zero up, otherwise from 255 down (bool)").asBool();
71 bool smoothFilter = rf.check("smoothFilter", Value(SMOOTH_FILTER_DEFAULT),
72 "if true then the smoothing filter is active (bool)").asBool();
73 float smoothFactor = (float) rf.check("smoothFactor", Value(SMOOTH_FACTOR_DEFAULT),
74 "Determine the smoothing intensity (float in [0,1])").asFloat64();
75 bool binarization = rf.check("binarization", Value(BINARIZATION_DEFAULT),
76 "if true then the binarization is active (bool)").asBool();
77
78 /*
79 * attach a port of the same name as the module (prefixed with a /) to the module
80 * so that messages received from the port are redirected to the respond method
81 */
82 string handlerPortName = "/";
83 handlerPortName += getName(rf.check("handlerPort", Value(RPC_PORT_DEFAULT.c_str())).asString());
84 if (!handlerPort.open(handlerPortName.c_str())) {
85 cout << getName() << ": Unable to open port " << handlerPortName << endl;
86 return false;
87 }
88 attach(handlerPort); // attach to port
89 handlerPort.setRpcMode(true);
90
91
92 /* ****** Threads ****** */
93 // Compensator thread
94 /* create the thread and pass pointers to the module parameters */
95 myThread = new CompensationThread(moduleName, &rf, robotName, compGain, contCompGain, addThreshold, minBaseline,
96 zeroUpRawData, period, binarization, smoothFilter, smoothFactor);
97 /* now start the thread to do the work */
98 if(!myThread->start()) { // this calls threadInit() and it if returns true, it then calls run()
99 yError() << "[SkinManager] Could not start the compensator thread.";
100 return false;
101 }
102
103 // Skin diagnostics thread
104 thSkinDiagnostics = new SkinDiagnosticsReadThread(20, rf);
105 if (!thSkinDiagnostics->start()) {
106 yError() << "[SkinManager] Could not start the skin diagnostics thread.";
107 return false;
108 }
109 return true;
110}
111
112
114{
115 handlerPort.interrupt();
116
117 return true;
118}
119
120
122{
123 /* stop the threads */
124 if(myThread) {
125 myThread->stop();
126 delete myThread;
127 }
128 if (thSkinDiagnostics) {
129 thSkinDiagnostics->stop();
130 delete thSkinDiagnostics;
131 }
132
133 handlerPort.close();
134
135 return true;
136}
137
138
139bool skinManager::respond(const Bottle& command, Bottle& reply) {
140 stringstream temp;
141 reply.clear();
142
144 Bottle params;
145 if(command.get(0).isInt32()){
146 // if first value is int then it is the id of the command
147 com = (SkinManagerCommand)command.get(0).asInt32();
148 yInfo("[rpc] Command received: %s", SkinManagerCommandList[com].c_str());
149 params = command.tail();
150 }
151 else if(!identifyCommand(command, com, params)){
152 reply.addString("Unknown command. Input 'help' to get a list of the available commands.");
153 return true;
154 }
155
156 switch( com ){
157 case quit:
158 reply.addString("quitting");
159 return false;
160
161 case help:
162 reply.addVocab32("many"); // print every string added to the bottle on a new line
163 reply.addString((string(getName().c_str()) + " commands are: ").c_str());
164 for(unsigned int i=0; i< SkinManagerCommandSize; i++){
165 reply.addString( ("- "+SkinManagerCommandList[i]+": "+SkinManagerCommandDesc[i]).c_str() );
166 }
167 return true;
168
169 case calibrate:
170 myThread->calibrate();
171 break;
172
173 case get_touch_thr:
174 {
175 Vector touchThreshold = myThread->getTouchThreshold();
176 for(size_t i=0; i< touchThreshold.size(); i++)
177 reply.addFloat64(touchThreshold[i]);
178 return true;
179 }
180
181 case set_binarization:
182 {
183 if(params.size()<1){
184 reply.addString("Binarization state missing! Specify either on or off.");
185 return true;
186 }
187 string value = params.get(0).asString().c_str();
188 if(value.compare("on")==0)
189 myThread->setBinarization(true);
190 else if(value.compare("off")==0)
191 myThread->setBinarization(false);
192 else{
193 reply.addString("Value not recognized.");
194 return true;
195 }
196 break;
197 }
198
199 case get_binarization:
200 if(myThread->getBinarization())
201 reply.addString("on");
202 else
203 reply.addString("off");
204 return true;
205
207 {
208 if(params.size()<1){
209 reply.addString("Smooth filter state missing! Specify either on or off.");
210 return true;
211 }
212 string value = params.get(0).asString().c_str();
213 if(value.compare("on")==0)
214 myThread->setSmoothFilter(true);
215 else if(value.compare("off")==0)
216 myThread->setSmoothFilter(false);
217 else{
218 reply.addString("Value not recognized.");
219 return true;
220 }
221 break;
222 }
223
225 if(myThread->getSmoothFilter())
226 reply.addString("on");
227 else
228 reply.addString("off");
229 return true;
230
232 {
233 if(params.size()<1 || (!params.get(0).isFloat64() && !params.get(0).isInt32())){
234 reply.addString("New smooth factor value missing or not a number! Smooth factor not updated.");
235 return true;
236 }
237
238 stringstream temp;
239 if(myThread->setSmoothFactor((float)params.get(0).asFloat64())){
240 temp<< "New smooth factor set: "<< params.get(0).asFloat64();
241 }
242 else{
243 temp<< "ERROR in setting new smooth factor: "<< params.get(0).asFloat64();
244 }
245 reply.addString( temp.str().c_str());
246 return true;
247 }
248
250 reply.addFloat64(myThread->getSmoothFactor());
251 return true;
252
253 case set_threshold:
254 {
255 if(params.size()<1 || (!params.get(0).isInt32())){
256 reply.addString("New threshold value missing or not an integer! Threshold not updated.");
257 return true;
258 }
259
260 stringstream temp;
261 if(myThread->setAddThreshold(params.get(0).asInt32())){
262 temp<< "New threshold set: "<< params.get(0).asInt32();
263 }
264 else{
265 temp<< "ERROR in setting new threshold: "<< params.get(0).asInt32();
266 }
267 reply.addString( temp.str().c_str());
268 return true;
269 }
270
271 case get_threshold:
272 reply.addInt32(myThread->getAddThreshold());
273 return true;
274
275 case set_gain:
276 {
277 if(params.size()<1 || (!params.get(0).isFloat64())){
278 reply.addString("New gain value missing or not a double! Gain not updated.");
279 return true;
280 }
281
282 stringstream temp;
283 if(myThread->setCompensationGain(params.get(0).asFloat64())){
284 temp<< "New gain set: "<< params.get(0).asFloat64();
285 }
286 else{
287 temp<< "ERROR in setting new gain: "<< params.get(0).asFloat64();
288 }
289 reply.addString( temp.str().c_str());
290 return true;
291 }
292
293 case get_gain:
294 reply.addFloat64(myThread->getCompensationGain());
295 return true;
296
297 case set_cont_gain:
298 {
299 if(params.size()<1 || (!params.get(0).isFloat64())){
300 reply.addString("New gain value missing or not a double! Contact gain not updated.");
301 return true;
302 }
303
304 stringstream temp;
305 if(myThread->setContactCompensationGain(params.get(0).asFloat64())){
306 temp<< "New contact gain set: "<< params.get(0).asFloat64();
307 }
308 else{
309 temp<< "ERROR in setting new contact gain: "<< params.get(0).asFloat64();
310 }
311 reply.addString( temp.str().c_str());
312 return true;
313 }
314
315 case get_cont_gain:
316 reply.addFloat64(myThread->getContactCompensationGain());
317 return true;
318
320 reply.addFloat64(myThread->getMaxNeighborDistance());
321 return true;
322
324 {
325 if(params.size()<1 || (!params.get(0).isFloat64())){
326 reply.addString("New max neighbor distance value missing or not a double! Not updated.");
327 return true;
328 }
329
330 stringstream temp;
331 if(myThread->setMaxNeighborDistance(params.get(0).asFloat64())){
332 temp<< "New max neighbor distance set: "<< params.get(0).asFloat64();
333 }
334 else{
335 temp<< "ERROR in setting new max neighbor distance: "<< params.get(0).asFloat64();
336 }
337 reply.addString( temp.str().c_str());
338 return true;
339 }
340
341 case get_skin_parts:
342 {
343 vector<SkinPart> spl = myThread->getSkinParts();
344 for(vector<SkinPart>::const_iterator it=spl.begin(); it!=spl.end(); it++){
345 reply.addInt32(*it);
346 reply.addString(SkinPart_s[*it].c_str());
347 }
348 return true;
349 }
350
351 case enable_skin_part:
352 if(!(params.size()>0 && params.get(0).isInt32())){
353 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
354 return true;
355 }
356 if(myThread->enableSkinPart((SkinPart)params.get(0).asInt32()))
357 reply.addString("SkinPart enabled");
358 else
359 reply.addString("SkinPart not found");
360 return true;
361
363 if(!(params.size()>0 && params.get(0).isInt32())){
364 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
365 return true;
366 }
367 if(myThread->disableSkinPart((SkinPart)params.get(0).asInt32()))
368 reply.addString("SkinPart disabled");
369 else
370 reply.addString("SkinPart not found");
371 return true;
372
373 case is_skin_enabled:
374 if(!(params.size()>0 && params.get(0).isInt32())){
375 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
376 return true;
377 }
378 if(myThread->isSkinEnabled((SkinPart)params.get(0).asInt32()))
379 reply.addString("yes");
380 else
381 reply.addString("no");
382 return true;
383
384 case is_calibrating:
385 if(myThread->isCalibrating())
386 reply.addString("yes");
387 else
388 reply.addString("no");
389 return true;
390
391 case get_pose:
392 {
393 if(!(params.size()>0 && params.get(0).isInt32())){
394 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
395 return true;
396 }
397 SkinPart sp = (SkinPart) params.get(0).asInt32();
398 if(params.size()>1 && params.get(1).isInt32()){
399 unsigned int taxelId = params.get(1).asInt32();
400 Vector res = myThread->getTaxelPose(sp, taxelId);
401 if(res.size()>0)
402 addToBottle(reply, res);
403 else
404 reply.addString("No poses for the specified skin part");
405 }
406 else{
407 vector<Vector> res = myThread->getTaxelPoses(sp);
408 addToBottle(reply, res);
409 }
410 return true;
411 }
412
413 case set_pose:
414 {
415 if(!(params.size()>6 && params.get(0).isInt32() )){
416 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
417 return true;
418 }
419 SkinPart sp = (SkinPart) params.get(0).asInt32();
420 if(params.get(1).isInt32()){
421 unsigned int taxelId = params.get(1).asInt32();
422 Vector pose;
423 if(!bottleToVector(params.tail().tail(), pose)){
424 reply.addString("ERROR while reading the taxel pose");
425 return true;
426 }
427 if(myThread->setTaxelPose(sp, taxelId, pose))
428 reply.addInt32(skin_manager_ok);
429 else{
430 reply.addInt32(skin_manager_error);
431 reply.addString("ERROR: pose was not set");
432 }
433 }
434 else{
435 Vector poses;
436 if(!bottleToVector(params.tail(), poses)){
437 reply.addString("ERROR while reading the taxel poses");
438 return true;
439 }
440 if(myThread->setTaxelPoses(sp, poses))
441 reply.addInt32(skin_manager_ok);
442 else{
443 reply.addInt32(skin_manager_error);
444 reply.addString("ERROR: pose was not set");
445 }
446 }
447 return true;
448 }
449 case get_position:
450 {
451 if(!(params.size()>0 && params.get(0).isInt32())){
452 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
453 return true;
454 }
455 SkinPart sp = (SkinPart) params.get(0).asInt32();
456 if(params.size()>1 && params.get(1).isInt32()){
457 unsigned int taxelId = params.get(1).asInt32();
458 Vector res = myThread->getTaxelPosition(sp, taxelId);
459 if(res.size()>0)
460 addToBottle(reply, res);
461 else
462 reply.addString("No position for the specified skin part");
463 }
464 else{
465 vector<Vector> res = myThread->getTaxelPositions(sp);
466 if(res.empty())
467 reply.addString("Specified skin part has not been found.");
468 else
469 addToBottle(reply, res);
470 }
471 return true;
472 }
473 case set_position:
474 {
475 if(!(params.size()>3 && params.get(0).isInt32() )){
476 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
477 return true;
478 }
479 SkinPart sp = (SkinPart) params.get(0).asInt32();
480 if(params.get(1).isInt32()){
481 unsigned int taxelId = params.get(1).asInt32();
482 Vector pose;
483 if(!bottleToVector(params.tail().tail(), pose)){
484 reply.addString("ERROR while reading the taxel position");
485 return true;
486 }
487 if(myThread->setTaxelPosition(sp, taxelId, pose))
488 reply.addInt32(skin_manager_ok);
489 else{
490 reply.addInt32(skin_manager_error);
491 reply.addString("ERROR: position was not set");
492 }
493 }
494 else{
495 Vector poses;
496 if(!bottleToVector(params.tail(), poses)){
497 reply.addString("ERROR while reading the taxel positions");
498 return true;
499 }
500 if(myThread->setTaxelPositions(sp, poses))
501 reply.addInt32(skin_manager_ok);
502 else{
503 reply.addInt32(skin_manager_error);
504 reply.addString("ERROR: position was not set");
505 }
506 }
507 return true;
508 }
509 case get_confidence:
510 {
511 if(!(params.size()>0 && params.get(0).isInt32())){
512 reply.addString(("ERROR: SkinPart is not specified. Params read are: "+string(params.toString().c_str())).c_str());
513 return true;
514 }
515 SkinPart sp = (SkinPart) params.get(0).asInt32();
516 if(params.size()>1 && params.get(1).isInt32()){
517 unsigned int taxelId = params.get(1).asInt32();
518 double res = myThread->getPoseConfidence(sp, taxelId);
519 reply.addFloat64(res);
520 }
521 else{
522 Vector res = myThread->getPoseConfidences(sp);
523 if(res.size()==0)
524 reply.addString("Specified skin part has not been found");
525 else
526 addToBottle(reply, res);
527 }
528 return true;
529
530 }
531 case get_info:
532 reply.append(myThread->getInfo());
533 return true;
534
535 default:
536 reply.addString("ERROR: This command is known but it is not managed in the code.");
537 return true;
538 }
539
540 reply.addString( (SkinManagerCommandList[com]+" command received.").c_str());
541
542 return true;
543}
544
545void skinManager::addToBottle(Bottle& b, const Vector& v){
546 for(unsigned int i=0; i<v.size(); i++)
547 b.addFloat64(v[i]);
548}
549
550void skinManager::addToBottle(Bottle& b, const vector<Vector>& v){
551 for(unsigned int i=0; i<v.size(); i++)
552 for(unsigned int j=0; j<v[i].size(); j++)
553 b.addFloat64(v[i][j]);
554}
555
556bool skinManager::bottleToVector(const yarp::os::Bottle& b, yarp::sig::Vector& v){
557 for(int i=0; i<b.size(); i++)
558 if(b.get(i).isFloat64() || b.get(i).isInt32())
559 v.push_back(b.get(i).asFloat64());
560 else
561 return false;
562 return true;
563}
564
568bool skinManager::identifyCommand(Bottle commandBot, SkinManagerCommand &com, Bottle& params) {
569 for(unsigned int i=0; i<SkinManagerCommandSize; i++){
570 stringstream stream(SkinManagerCommandList[i]);
571 string word;
572 int j=0;
573 bool found = true;
574
575 while(stream>>word){
576 if (commandBot.get(j).asString() != word.c_str()){
577 found=false;
578 break;
579 }
580 j++;
581 }
582 if(found){
583 com = (SkinManagerCommand)i;
584 params = commandBot.tail();
585 for(int k=1; k<j; k++)
586 params = params.tail();
587 return true;
588 }
589 }
590
591 return false;
592}
593
595 double avgTime, stdDev, period;
596 period = myThread->getPeriod();
597 myThread->getEstimatedPeriod(avgTime, stdDev);
598 double avgTimeUsed, stdDevUsed;
599 myThread->getEstimatedUsed(avgTimeUsed, stdDevUsed); // real duration of run()
600 if(avgTime > 1.3 * period){
601 yWarning("Thread too slow. Real period: %3.3f+/-%3.3f. Expected period: %3.3f.\n", avgTime, stdDev, period);
602 yWarning("Duration of 'run' method: %3.3f+/-%3.3f.\n", avgTimeUsed, stdDevUsed);
603 }
604 return true;
605}
606
607double skinManager::getPeriod(){ return 1.0;}
608
bool setTaxelPosition(SkinPart sp, unsigned int taxelId, const Vector &position)
Vector getTaxelPose(SkinPart sp, unsigned int taxelId)
bool setTaxelPose(SkinPart sp, unsigned int taxelId, const Vector &pose)
double getPoseConfidence(SkinPart sp, unsigned int taxelId)
vector< Vector > getTaxelPoses(SkinPart sp=SKIN_PART_ALL)
bool setTaxelPositions(SkinPart sp, const Vector &positions)
bool setTaxelPoses(SkinPart sp, const vector< Vector > &poses)
Vector getTaxelPosition(SkinPart sp, unsigned int taxelId)
vector< Vector > getTaxelPositions(SkinPart sp=SKIN_PART_ALL)
bool respond(const yarp::os::Bottle &command, yarp::os::Bottle &reply)
bool configure(yarp::os::ResourceFinder &rf)
const std::string SkinPart_s[]
Definition common.h:64
const std::string SkinManagerCommandDesc[]
const std::string SkinManagerCommandList[]