75 #include <yarp/os/Network.h>
76 #include <yarp/os/RFModule.h>
77 #include <yarp/os/PeriodicThread.h>
78 #include <yarp/os/Bottle.h>
79 #include <yarp/os/BufferedPort.h>
80 #include <yarp/os/Time.h>
81 #include <yarp/os/Log.h>
82 #include <yarp/os/LogStream.h>
83 #include <yarp/sig/Vector.h>
84 #include <yarp/math/Math.h>
86 #include <yarp/dev/Drivers.h>
87 #include <yarp/dev/CartesianControl.h>
88 #include <yarp/dev/PolyDriver.h>
99 using namespace yarp::os;
101 using namespace yarp::sig;
102 using namespace yarp::math;
104 #define PRINT_STATUS_PER 0.1
111 struct struct_jointProperties
126 double defaultExecTime;
136 string button_actions [20];
139 string hat_actions [20];
162 PeriodicThread((double)_period/1000.0), rf(_rf)
188 if (rf.check(
"silent"))
190 yInfo (
"Running in silent mode\n");
194 if (rf.check(
"force_configuration"))
196 yInfo (
"Force configuration option found\n");
200 if (rf.findGroup(
"INPUTS").check(
"InputsNumber"))
202 num_inputs = rf.findGroup(
"INPUTS").find(
"InputsNumber").asInt32();
203 inputMax =
new double [num_inputs];
204 inputMin =
new double [num_inputs];
205 outputMax =
new double [num_inputs];
206 outputMin =
new double [num_inputs];
207 jointDeadband =
new double [num_inputs];
208 reverse =
new int [num_inputs];
209 yDebug (
"Number of input axes in the configuration options: %d \n",num_inputs);
213 yError (
"Unable to find number of input axes in the configuration options\n");
220 b = rf.findGroup(
"INPUTS").findGroup(
"Reverse");
221 if (b.size()-1 == num_inputs)
223 for (
int i = 1; i < b.size(); i++) reverse[i-1] = b.get(i).asInt32();
225 else {yError (
"Configuration error: invalid number of entries 'Reverse'\n");
return false;}
226 b = rf.findGroup(
"INPUTS").findGroup(
"InputMax");
227 if (b.size()-1 == num_inputs)
229 for (
int i = 1; i < b.size(); i++) inputMax[i-1] = b.get(i).asFloat64();
231 else {yError (
"Configuration error: invalid number of entries 'InputMax'\n");
return false;}
232 b = rf.findGroup(
"INPUTS").findGroup(
"InputMin");
233 if (b.size()-1 == num_inputs)
235 for (
int i = 1; i < b.size(); i++) inputMin[i-1] = b.get(i).asFloat64();
237 else {yError (
"Configuration error: invalid number of entries 'InputMin'\n");
return false;}
238 b = rf.findGroup(
"INPUTS").findGroup(
"OutputMax");
239 if (b.size()-1 == num_inputs)
241 for (
int i = 1; i < b.size(); i++) outputMax[i-1] = b.get(i).asFloat64();
243 else {yError (
"Configuration error: invalid number of entries 'OutputMax'\n");
return false;}
244 b = rf.findGroup(
"INPUTS").findGroup(
"OutputMin");
245 if (b.size()-1 == num_inputs)
247 for (
int i = 1; i < b.size(); i++) outputMin[i-1] = b.get(i).asFloat64();
249 else {yError (
"Configuration error: invalid number of entries 'OutputMin'\n");
return false;}
251 b = rf.findGroup(
"INPUTS").findGroup(
"Deadband");
252 if (b.size()-1 == num_inputs)
254 for (
int i = 1; i < b.size(); i++) jointDeadband[i-1] = b.get(i).asFloat64();
256 else {yError (
"Configuration error: invalid number of entries 'Deadband'\n");
return false;}
258 if (rf.findGroup(
"OUTPUTS").check(
"OutputsNumber"))
260 num_outputs = rf.findGroup(
"OUTPUTS").find(
"OutputsNumber").asInt32();
261 jointProperties =
new struct_jointProperties [num_outputs];
265 yError (
"Unable to find number of output axes in the configuration options\n");
269 for (
int i=0; i<num_outputs; i++)
272 sprintf (
tmp,
"Ax%d",i);
273 if (!rf.findGroup(
"OUTPUTS").check(
tmp))
275 yError (
"Error reading [OUTPUT] block, unable to find Ax%d identifier\n",i);
278 b = rf.findGroup(
"OUTPUTS").findGroup(
tmp);
279 if (b.get(1).asString()==
"polar_r_theta")
282 jointProperties[i].param[0]=b.get(2).asInt32();
283 jointProperties[i].param[1]=b.get(3).asInt32();
284 jointProperties[i].param[2]=b.get(4).asInt32();
287 if (b.get(1).asString()==
"cartesian_xyz")
290 jointProperties[i].param[0]=b.get(2).asInt32();
291 jointProperties[i].param[1]=0;
292 jointProperties[i].param[2]=0;
295 if (b.get(1).asString()==
"constant")
298 jointProperties[i].param[0]=b.get(2).asInt32();
299 jointProperties[i].param[1]=0;
300 jointProperties[i].param[2]=0;
303 if (b.get(1).asString()==
"string")
306 jointProperties[i].param[0]=0;
307 jointProperties[i].param[1]=0;
308 jointProperties[i].param[2]=0;
309 jointProperties[i].param_s=b.get(2).asString();
313 yError() <<
"Unknown [OUTPUT] property";
320 string output_port_name;
321 if (rf.findGroup(
"GENERAL").check(
"outputPortName"))
323 output_port_name = rf.findGroup(
"GENERAL").find(
"outputPortName").asString();
327 output_port_name =
"/joystickCtrl:o";
328 yWarning (
"outputPortName not found, using %s \n", output_port_name.c_str());
331 ret &= port_command.open(output_port_name.c_str());
333 ret &= port_axis_only.open(
"/joystickCtrl/raw_axis:o");
334 ret &= port_buttons_only.open(
"/joystickCtrl/raw_buttons:o");
337 yError() <<
"Unable to open module ports";
342 Bottle& exec_comm_bottle = rf.findGroup(
"BUTTONS_EXECUTE");
343 if (!exec_comm_bottle.isNull())
345 yInfo (
"associating the following actions to the buttons: \n");
346 for (
int iii = 0; iii < 20; iii++){
348 sprintf(
tmp,
"button%d", iii);
349 if (exec_comm_bottle.check(
tmp))
351 button_actions[iii] = exec_comm_bottle.find(
tmp).toString();
352 printf (
"%s %s\n",
tmp, button_actions[iii].c_str());
359 Bottle& hats_exec_bottle = rf.findGroup(
"HATS_EXECUTE");
360 if (!hats_exec_bottle.isNull())
362 yInfo (
"associating the following actions to the hats: \n");
363 for (
int iii = 0; iii < 20; iii++){
365 sprintf(
tmp,
"hat%d", iii);
366 if (hats_exec_bottle.check(
tmp))
368 hat_actions[iii] = hats_exec_bottle.find(
tmp).toString();
369 printf (
"%s %s\n",
tmp, hat_actions[iii].c_str());
378 if ( SDL_InitSubSystem ( SDL_INIT_JOYSTICK ) < 0 )
380 yError (
"Unable to initialize Joystick: %s\n", SDL_GetError() );
387 int joystick_num = SDL_NumJoysticks ();
388 if (joystick_num == 0)
390 yError (
"Error: No joysticks found\n");
return false;
392 else if (joystick_num == 1)
395 yInfo (
"One joystick found \n");
396 #if (SDL_MAJOR_VERSION == 2)
397 yInfo (
"Using joystick: %s \n", SDL_JoystickNameForIndex(joy_id));
399 yInfo (
"Using joystick: %s \n", SDL_JoystickName(joy_id));
405 yInfo (
"More than one joystick found:\n");
406 for (
int i=0; i<joystick_num; i++)
408 #if (SDL_MAJOR_VERSION == 2)
409 yInfo (
"%d: %s\n",i,SDL_JoystickNameForIndex(i));
411 yInfo (
"%d: %s\n",i,SDL_JoystickName(i));
417 if (rf.findGroup(
"GENERAL").check(
"DefaultJoystickNumber"))
419 joy_id = rf.findGroup(
"GENERAL").find(
"DefaultJoystickNumber").asInt32();
420 yInfo (
"Multiple joysticks found, using #%d, as specified in the configuration options\n", joy_id);
424 yWarning (
"No default joystick specified in the configuration options\n");
425 yWarning (
"Which joystick you want to use? (choose number) \n");
431 joy1 = SDL_JoystickOpen ( joy_id );
434 yError (
"Could not open joystick\n" );
439 numAxes = SDL_JoystickNumAxes ( joy1 );
440 numBalls = SDL_JoystickNumBalls ( joy1 );
441 numHats = SDL_JoystickNumHats ( joy1 );
442 numButtons = SDL_JoystickNumButtons ( joy1 );
443 yInfo (
"Characteristics of joy %d: \n", joy_id);
444 yInfo (
"%i Axes\n", numAxes );
445 yInfo (
"%i Balls\n", numBalls );
446 yInfo (
"%i Hats\n", numHats );
447 yInfo (
"%i Buttons\n", numButtons );
453 yError (
"Error: selected joystick has %d Axes?!\n",numAxes );
457 if (numAxes!=num_inputs)
459 if (force_cfg ==
false)
461 yWarning (
"Warning: # of joystick axes (%d) differs from # of configured input axes (%d)!\n",numAxes,num_inputs );
462 yWarning (
"This probably means that your .ini file does not containt a correct configuration.\n");
463 yWarning (
"Do you want to continue anyway (y/n)?\n");
466 if (input[0]!=
'y' && input[0]!=
'Y')
468 yInfo (
"Quitting...\n");
473 yWarning (
"Overriding the number of axes specified in the configuration file. Using %d axes.\n",numAxes);
478 yWarning (
"Warning: # of joystick axes (%d) differs from # of configured input axes (%d)!\n",numAxes,num_inputs );
479 yWarning (
"This probably means that your .ini file does not containt a correct configuration.\n");
480 yWarning (
"However, --force_configuration option is enabled. This will override the number of axes specified in the configuration file.\n");
481 yWarning (
"Using %d axes.\n",numAxes);
507 yInfo (
"Thread started successfully\n");
509 yError (
"Thread did not start\n");
526 SDL_JoystickUpdate ();
529 for (
int i=0; i < numButtons; ++i )
531 rawButtonsOld[i] = rawButtons[i];
532 rawButtons[i] = SDL_JoystickGetButton ( joy1, i );
535 for (
int i=0; i < numHats; ++i )
537 rawHatsOld[i] = rawHats[i];
538 rawHats[i] = SDL_JoystickGetHat ( joy1, i );
541 for (
int i=0; i < numAxes; ++i )
543 rawAxes[i] = (double)SDL_JoystickGetAxis ( joy1, i );
547 for(
int i=0;i<num_inputs;i++)
549 double v = rawAxes[i];
550 if (jointDeadband[i]>0)
552 if (fabs(v)<jointDeadband[i]) v=0;
557 if (inputMax[i]==inputMin[i])
563 v = (v<inputMax[i]) ? v : inputMax[i];
564 v = (v>inputMin[i]) ? v : inputMin[i];
565 v = v - ((inputMax[i]-inputMin[i])/2+inputMin[i]);
566 v = v / (inputMax[i]-inputMin[i]);
567 v = v * (outputMax[i]-outputMin[i]);
568 v = v + ((outputMax[i]-outputMin[i])/2+outputMin[i]);
585 for(
int i=0;i<num_outputs;i++)
589 if (jointProperties[i].param[2] == 0)
591 outAxes[i]= atan2( (rawAxes[jointProperties[i].param[0]]),
592 (rawAxes[jointProperties[i].param[1]]) ) * 180.0 / 3.14159265;
594 else if (jointProperties[i].param[2] == 1)
596 outAxes[i]= sqrt ( pow((rawAxes[jointProperties[i].param[0]]),2)+
597 pow((rawAxes[jointProperties[i].param[1]]),2) );
602 yWarning (
"Unknown parameter for JTYPE_POLAR, joint %d\n",i);
607 outAxes[i]=rawAxes[jointProperties[i].param[0]];
611 outAxes[i]=(jointProperties[i].param[0]);
616 yWarning (
"Unknown property, joint %d\n",i);
621 for (
int i=0;i<numButtons;i++)
623 if (rawButtonsOld[i] == 0 && rawButtons[i] == 1)
626 if (!button_actions[i].empty())
628 yInfo (
"executing script %d: %s\n", i, button_actions[i].c_str());
629 int ret = system(button_actions[i].c_str());
633 yWarning (
"no scripts associated to button %d\n", i);
639 for (
int i=0;i<numHats;i++)
641 if (rawHats[i] != SDL_HAT_CENTERED)
644 if (!hat_actions[i].empty())
646 string action(hat_actions[i]);
650 bool trigger_mode=
true;
665 case SDL_HAT_RIGHTUP:
668 case SDL_HAT_RIGHTDOWN:
669 action +=
"rightdown";
674 case SDL_HAT_LEFTDOWN:
675 action +=
"leftdown";
682 if (rawHatsOld[i]==SDL_HAT_CENTERED)
684 yInfo (
"executing script %d: %s\n", i, action.c_str());
685 int ret = system(action.c_str());
690 yInfo (
"executing script %d: %s\n", i, action.c_str());
691 int ret = system(action.c_str());
696 yWarning (
"no scripts associated to button %d\n", i);
702 for(
int i=0;i<num_outputs;i++)
705 data.addString(jointProperties[i].param_s.c_str());
707 data.addFloat64(outAxes[i]);
709 for (
int i=0;i<numButtons;i++)
711 buttons_data.addFloat64(rawButtons[i]);
713 for (
int i=0;i<numAxes; i++)
715 axis_data.addFloat64(rawAxes[i]);
719 if (port_command.getOutputCount()>0)
721 port_command.prepare() =
data;
722 port_command.write();
724 if (port_axis_only.getOutputCount()>0)
726 port_axis_only.prepare() = axis_data;
727 port_axis_only.write();
729 if (port_buttons_only.getOutputCount()>0)
731 port_buttons_only.prepare() = buttons_data;
732 port_buttons_only.write();
736 if (!silent) printStatus();
741 if (rawAxes)
delete [] rawAxes;
742 if (rawHats)
delete [] rawHats;
743 if (rawHatsOld)
delete [] rawHatsOld;
744 if (outAxes)
delete [] outAxes;
745 if (rawButtons)
delete [] rawButtons;
746 if (inputMax)
delete [] inputMax;
747 if (inputMin)
delete [] inputMin;
748 if (outputMax)
delete [] outputMax;
749 if (outputMin)
delete [] outputMin;
750 if (jointDeadband)
delete [] jointDeadband;
751 if (jointProperties)
delete [] jointProperties;
752 if (reverse)
delete [] reverse;
753 port_command.interrupt();
754 port_command.close();
755 port_axis_only.interrupt();
756 port_axis_only.close();
757 port_buttons_only.interrupt();
758 port_buttons_only.close();
764 double t=Time::now();
765 std::ostringstream buff;
772 for (
int i=0;i <numAxes; i++)
774 buff << std::setw(9) << std::fixed << std::setprecision(1) << rawAxes[i];
777 for (
int i=0;i <num_outputs; i++)
779 buff << std::setw(9) << std::fixed << std::setprecision(1) << outAxes[i];
781 yDebug() << buff.str();
801 if (rf.findGroup(
"GENERAL").check(
"rateThread"))
803 rateThread = rf.findGroup(
"GENERAL").find(
"rateThread").asInt32();
807 yWarning (
"rateThread option not found, assuming %d ms\n", rateThread);
842 rf.setDefaultConfigFile(
"joystickControl.ini");
843 rf.setDefaultContext(
"joystickControl");
844 rf.configure(
argc,argv);
846 if (rf.check(
"help"))
848 yInfo (
"Options:\n");
849 yInfo (
"--silent: supress text output\n");
850 yInfo (
"--force_configuration: force a joystick configuration for a joystick with differnt # of axes, buttons etc.\n");
856 if (!
yarp.checkNetwork())
858 yError(
"Sorry YARP network does not seem to be available, is the yarp server available?\n");
864 SDL_JoystickEventState ( SDL_QUERY );
868 return mod.runModule(rf);
virtual bool configure(ResourceFinder &rf)
virtual double getPeriod()
virtual bool updateModule()
BufferedPort< Bottle > port_buttons_only
virtual bool threadInit()
virtual void afterStart(bool s)
virtual void threadRelease()
struct_jointProperties * jointProperties
BufferedPort< Bottle > port_command
CtrlThread(unsigned int _period, ResourceFinder &_rf)
BufferedPort< Bottle > port_axis_only
int main(int argc, char *argv[])
Copyright (C) 2008 RobotCub Consortium.