00001
00027 #include "sr_robot_lib/sr_robot_lib.hpp"
00028 #include <string>
00029 #include <utility>
00030 #include <map>
00031 #include <vector>
00032 #include <boost/foreach.hpp>
00033
00034 #include <sys/time.h>
00035
00036 #include <ros/ros.h>
00037
00038 #include "sr_robot_lib/shadow_PSTs.hpp"
00039 #include "sr_robot_lib/biotac.hpp"
00040 #include "sr_robot_lib/UBI0.hpp"
00041 #include <controller_manager_msgs/ListControllers.h>
00042 #include <sr_robot_lib/motor_updater.hpp>
00043
00044 #define SERIOUS_ERROR_FLAGS PALM_0200_EDC_SERIOUS_ERROR_FLAGS
00045 #define error_flag_names palm_0200_edc_error_flag_names
00046
00047 using std::vector;
00048 using std::string;
00049 using std::pair;
00050 using std::map;
00051 using std::ostringstream;
00052 using sr_actuator::SrMotorActuator;
00053 using tactiles::GenericTactiles;
00054 using tactiles::ShadowPSTs;
00055 using tactiles::Biotac;
00056 using tactiles::UBI0;
00057 using ros_ethercat_model::RobotState;
00058 using generic_updater::MotorUpdater;
00059 using shadow_joints::CalibrationMap;
00060 using shadow_joints::Joint;
00061 using shadow_joints::JointToSensor;
00062 using shadow_joints::MotorWrapper;
00063 using shadow_joints::PartialJointToSensor;
00064 using generic_updater::MotorUpdater;
00065 using generic_updater::UpdateConfig;
00066 using boost::shared_ptr;
00067 using boost::ptr_vector;
00068
00069
00070 namespace shadow_robot
00071 {
00072 #ifdef DEBUG_PUBLISHER
00073
00074 template<class StatusType, class CommandType>
00075 const int SrRobotLib<StatusType, CommandType>::nb_debug_publishers_const = 20;
00076
00077
00078 #endif
00079
00080 template <class StatusType, class CommandType>
00081 const int SrRobotLib<StatusType, CommandType>::nb_sensor_data = 37;
00082
00083 template <class StatusType, class CommandType>
00084 const char* SrRobotLib<StatusType, CommandType>::human_readable_sensor_data_types[nb_sensor_data] = {
00085 "TACTILE_SENSOR_TYPE_SAMPLE_FREQUENCY_HZ",
00086 "TACTILE_SENSOR_TYPE_MANUFACTURER",
00087 "TACTILE_SENSOR_TYPE_SERIAL_NUMBER",
00088 "TACTILE_SENSOR_TYPE_SOFTWARE_VERSION",
00089 "TACTILE_SENSOR_TYPE_PCB_VERSION",
00090 "TACTILE_SENSOR_TYPE_WHICH_SENSORS",
00091 "TACTILE_SENSOR_TYPE_PST3_PRESSURE_TEMPERATURE",
00092 "TACTILE_SENSOR_TYPE_PST3_PRESSURE_RAW_ZERO_TRACKING",
00093 "TACTILE_SENSOR_TYPE_PST3_DAC_VALUE",
00094 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_1",
00095 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_2",
00096 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_3",
00097 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_4",
00098 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_5",
00099 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_6",
00100 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_7",
00101 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_8",
00102 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_9",
00103 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_10",
00104 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_11",
00105 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_12",
00106 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_13",
00107 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_14",
00108 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_15",
00109 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_16",
00110 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_17",
00111 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_18",
00112 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_19",
00113 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_20",
00114 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_21",
00115 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_22",
00116 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_23",
00117 "TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_24",
00118 "TACTILE_SENSOR_TYPE_BIOTAC_PDC",
00119 "TACTILE_SENSOR_TYPE_BIOTAC_TAC",
00120 "TACTILE_SENSOR_TYPE_BIOTAC_TDC",
00121 "TACTILE_SENSOR_TYPE_UBI0_TACTILE"};
00122
00123 template <class StatusType, class CommandType>
00124 const int32u SrRobotLib<StatusType, CommandType>::sensor_data_types[nb_sensor_data] = {
00125 TACTILE_SENSOR_TYPE_SAMPLE_FREQUENCY_HZ,
00126 TACTILE_SENSOR_TYPE_MANUFACTURER,
00127 TACTILE_SENSOR_TYPE_SERIAL_NUMBER,
00128 TACTILE_SENSOR_TYPE_SOFTWARE_VERSION,
00129 TACTILE_SENSOR_TYPE_PCB_VERSION,
00130 TACTILE_SENSOR_TYPE_WHICH_SENSORS,
00131 TACTILE_SENSOR_TYPE_PST3_PRESSURE_TEMPERATURE,
00132 TACTILE_SENSOR_TYPE_PST3_PRESSURE_RAW_ZERO_TRACKING,
00133 TACTILE_SENSOR_TYPE_PST3_DAC_VALUE,
00134 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_1,
00135 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_2,
00136 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_3,
00137 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_4,
00138 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_5,
00139 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_6,
00140 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_7,
00141 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_8,
00142 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_9,
00143 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_10,
00144 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_11,
00145 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_12,
00146 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_13,
00147 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_14,
00148 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_15,
00149 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_16,
00150 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_17,
00151 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_18,
00152 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_19,
00153 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_20,
00154 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_21,
00155 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_22,
00156 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_23,
00157 TACTILE_SENSOR_TYPE_BIOTAC_ELECTRODE_24,
00158 TACTILE_SENSOR_TYPE_BIOTAC_PDC,
00159 TACTILE_SENSOR_TYPE_BIOTAC_TAC,
00160 TACTILE_SENSOR_TYPE_BIOTAC_TDC,
00161 TACTILE_SENSOR_TYPE_UBI0_TACTILE};
00162
00163 template<class StatusType, class CommandType>
00164 const double SrRobotLib<StatusType, CommandType>::tactile_timeout = 10.0;
00165
00166 template<class StatusType, class CommandType>
00167 SrRobotLib<StatusType, CommandType>::SrRobotLib(hardware_interface::HardwareInterface *hw, ros::NodeHandle nh,
00168 ros::NodeHandle nhtilde, string device_id, string joint_prefix)
00169 : main_pic_idle_time(0),
00170 main_pic_idle_time_min(1000),
00171 tactile_current_state(operation_mode::device_update_state::INITIALIZATION),
00172 hw_(static_cast<RobotState *> (hw)),
00173 device_id_(device_id),
00174 joint_prefix_(joint_prefix),
00175 nullify_demand_(false),
00176 nodehandle_(nh),
00177 nh_tilde(nhtilde),
00178
00179
00180
00181 nullify_demand_server_(
00182 nh_tilde.advertiseService("nullify_demand", &SrRobotLib::nullify_demand_callback, this)),
00183
00184
00185
00186
00187
00188
00189 generic_sensor_update_rate_configs_vector(
00190 read_update_rate_configs("generic_sensor_data_update_rate/", nb_sensor_data,
00191 human_readable_sensor_data_types, sensor_data_types)),
00192
00193
00194 pst3_sensor_update_rate_configs_vector(
00195 read_update_rate_configs("pst3_sensor_data_update_rate/", nb_sensor_data,
00196 human_readable_sensor_data_types, sensor_data_types)),
00197
00198
00199 biotac_sensor_update_rate_configs_vector(
00200 read_update_rate_configs("biotac_sensor_data_update_rate/", nb_sensor_data,
00201 human_readable_sensor_data_types, sensor_data_types)),
00202
00203
00204 ubi0_sensor_update_rate_configs_vector(
00205 read_update_rate_configs("ubi0_sensor_data_update_rate/", nb_sensor_data,
00206 human_readable_sensor_data_types, sensor_data_types)),
00207
00208 tactile_init_max_duration(tactile_timeout),
00209
00210
00211 tactile_check_init_timeout_timer(
00212 this->nh_tilde.createTimer(tactile_init_max_duration,
00213 boost::bind(
00214 &SrRobotLib<StatusType,
00215 CommandType>::tactile_init_timer_callback,
00216 this, _1), true)),
00217 lock_tactile_init_timeout_(boost::shared_ptr<boost::mutex>(new boost::mutex())),
00218 tactiles_init(shared_ptr<GenericTactiles<StatusType, CommandType> >(
00219 new GenericTactiles<StatusType, CommandType>(nodehandle_, device_id_,
00220 generic_sensor_update_rate_configs_vector,
00221 operation_mode::device_update_state::INITIALIZATION))),
00222
00223
00224 calibration_map(read_joint_calibration())
00225 {
00226 }
00227
00228 template<class StatusType, class CommandType>
00229 void SrRobotLib<StatusType, CommandType>::reinitialize_sensors()
00230 {
00231
00232 tactiles_init = shared_ptr<GenericTactiles<StatusType, CommandType> >(
00233 new GenericTactiles<StatusType, CommandType>(nodehandle_, device_id_,
00234 generic_sensor_update_rate_configs_vector,
00235 operation_mode::device_update_state::INITIALIZATION));
00236 tactile_current_state = operation_mode::device_update_state::INITIALIZATION;
00237 }
00238
00239 template<class StatusType, class CommandType>
00240 bool SrRobotLib<StatusType, CommandType>::nullify_demand_callback(sr_robot_msgs::NullifyDemand::Request &request,
00241 sr_robot_msgs::NullifyDemand::Response &response)
00242 {
00243 if (request.nullify_demand)
00244 ROS_INFO_STREAM(
00245 "Nullifying the demand sent to the motor. "
00246 "Will ignore the values computed by the controllers and send 0.");
00247 else
00248 ROS_INFO_STREAM("Using the value computed by the controllers to send the demands to the motors.");
00249
00250 nullify_demand_ = request.nullify_demand;
00251 return true;
00252 }
00253
00254 template<class StatusType, class CommandType>
00255 void SrRobotLib<StatusType, CommandType>::build_tactile_command(CommandType *command)
00256 {
00257
00258 boost::mutex::scoped_lock l(*lock_tactile_init_timeout_);
00259
00260 if (tactile_current_state == operation_mode::device_update_state::INITIALIZATION)
00261 {
00262 if (tactiles_init->sensor_updater->build_init_command(command)
00263 != operation_mode::device_update_state::INITIALIZATION)
00264 {
00265 tactile_current_state = operation_mode::device_update_state::OPERATION;
00266
00267 tactile_check_init_timeout_timer.stop();
00268
00269 switch (tactiles_init->tactiles_vector->at(0).which_sensor)
00270 {
00271 case TACTILE_SENSOR_PROTOCOL_TYPE_PST3:
00272 tactiles = shared_ptr<ShadowPSTs<StatusType, CommandType> >(
00273 new ShadowPSTs<StatusType, CommandType>(nodehandle_, device_id_,
00274 pst3_sensor_update_rate_configs_vector,
00275 operation_mode::device_update_state::OPERATION,
00276 tactiles_init->tactiles_vector));
00277
00278 ROS_INFO("PST3 tactiles initialized");
00279 break;
00280
00281 case TACTILE_SENSOR_PROTOCOL_TYPE_BIOTAC_2_3:
00282 tactiles = shared_ptr<Biotac<StatusType, CommandType> >(
00283 new Biotac<StatusType, CommandType>(nodehandle_, device_id_,
00284 biotac_sensor_update_rate_configs_vector,
00285 operation_mode::device_update_state::OPERATION,
00286 tactiles_init->tactiles_vector));
00287
00288 ROS_INFO("Biotac tactiles initialized");
00289 break;
00290
00291 case TACTILE_SENSOR_PROTOCOL_TYPE_UBI0:
00292 tactiles = shared_ptr<UBI0<StatusType, CommandType> >(
00293 new UBI0<StatusType, CommandType>(nodehandle_, device_id_, ubi0_sensor_update_rate_configs_vector,
00294 operation_mode::device_update_state::OPERATION,
00295 tactiles_init->tactiles_vector));
00296
00297 ROS_INFO("UBI0 tactiles initialized");
00298 break;
00299
00300 case TACTILE_SENSOR_PROTOCOL_TYPE_INVALID:
00301 ROS_WARN_STREAM("TACTILE_SENSOR_PROTOCOL_TYPE_INVALID!!");
00302 break;
00303 case TACTILE_SENSOR_PROTOCOL_TYPE_CONFLICTING:
00304 ROS_WARN_STREAM("TACTILE_SENSOR_PROTOCOL_TYPE_CONFLICTING!!");
00305 break;
00306 }
00307 }
00308 }
00309 else
00310 {
00311 tactile_current_state = tactiles->sensor_updater->build_command(command);
00312 }
00313 }
00314
00315 template<class StatusType, class CommandType>
00316 void SrRobotLib<StatusType, CommandType>::update_tactile_info(StatusType *status)
00317 {
00318
00319 boost::mutex::scoped_lock l(*lock_tactile_init_timeout_);
00320 if (tactile_current_state == operation_mode::device_update_state::INITIALIZATION)
00321 {
00322 if (tactiles_init != NULL)
00323 {
00324 tactiles_init->update(status);
00325 }
00326 }
00327 else
00328 {
00329 if (tactiles != NULL)
00330 {
00331 tactiles->update(status);
00332 }
00333 }
00334 }
00335
00336 template<class StatusType, class CommandType>
00337 CalibrationMap SrRobotLib<StatusType, CommandType>::read_joint_calibration()
00338 {
00339 CalibrationMap joint_calibration;
00340
00341 XmlRpc::XmlRpcValue calib;
00342 nodehandle_.getParam("sr_calibrations", calib);
00343 ROS_ASSERT(calib.getType() == XmlRpc::XmlRpcValue::TypeArray);
00344
00345 for (int32_t index_cal = 0; index_cal < calib.size(); ++index_cal)
00346 {
00347
00348
00349 ROS_ASSERT(calib[index_cal][0].getType() == XmlRpc::XmlRpcValue::TypeString);
00350 ROS_ASSERT(calib[index_cal][1].getType() == XmlRpc::XmlRpcValue::TypeArray);
00351
00352 string joint_name = static_cast<string> (calib[index_cal][0]);
00353 vector<joint_calibration::Point> calib_table_tmp;
00354
00355
00356 for (int32_t index_table = 0; index_table < calib[index_cal][1].size(); ++index_table)
00357 {
00358 ROS_ASSERT(calib[index_cal][1][index_table].getType() == XmlRpc::XmlRpcValue::TypeArray);
00359
00360 ROS_ASSERT(calib[index_cal][1][index_table].size() == 2);
00361 ROS_ASSERT(calib[index_cal][1][index_table][0].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00362 ROS_ASSERT(calib[index_cal][1][index_table][1].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00363
00364
00365 joint_calibration::Point point_tmp;
00366 point_tmp.raw_value = static_cast<double> (calib[index_cal][1][index_table][0]);
00367 point_tmp.calibrated_value = sr_math_utils::to_rad(static_cast<double> (calib[index_cal][1][index_table][1]));
00368 calib_table_tmp.push_back(point_tmp);
00369 }
00370
00371 joint_calibration.insert(joint_name, shared_ptr<shadow_robot::JointCalibration>(
00372 new shadow_robot::JointCalibration(calib_table_tmp)));
00373 }
00374
00375 return joint_calibration;
00376 }
00377
00378 template<class StatusType, class CommandType>
00379 vector<JointToSensor> SrRobotLib<StatusType, CommandType>::read_joint_to_sensor_mapping()
00380 {
00381 vector<JointToSensor> joint_to_sensor_vect;
00382
00383 map<string, int> sensors_map;
00384 for (unsigned int i = 0; i < SENSORS_NUM_0220; ++i)
00385 {
00386 sensors_map[sensor_names[i]] = i;
00387 }
00388
00389 XmlRpc::XmlRpcValue joint_to_sensor_mapping;
00390 nodehandle_.getParam("joint_to_sensor_mapping", joint_to_sensor_mapping);
00391 ROS_ASSERT(joint_to_sensor_mapping.getType() == XmlRpc::XmlRpcValue::TypeArray);
00392 for (int32_t i = 0; i < joint_to_sensor_mapping.size(); ++i)
00393 {
00394 JointToSensor tmp_vect;
00395
00396 XmlRpc::XmlRpcValue map_one_joint = joint_to_sensor_mapping[i];
00397
00398
00399
00400
00401 int param_index = 0;
00402
00403 if (map_one_joint[param_index].getType() == XmlRpc::XmlRpcValue::TypeInt)
00404 {
00405 if (1 == static_cast<int> (map_one_joint[0]))
00406 {
00407 tmp_vect.calibrate_after_combining_sensors = true;
00408 }
00409 else
00410 {
00411 tmp_vect.calibrate_after_combining_sensors = false;
00412 }
00413
00414 param_index++;
00415 }
00416 else
00417 {
00418
00419 tmp_vect.calibrate_after_combining_sensors = false;
00420 }
00421
00422 ROS_ASSERT(map_one_joint.getType() == XmlRpc::XmlRpcValue::TypeArray);
00423 for (int32_t i = param_index; i < map_one_joint.size(); ++i)
00424 {
00425 ROS_ASSERT(map_one_joint[i].getType() == XmlRpc::XmlRpcValue::TypeArray);
00426 PartialJointToSensor tmp_joint_to_sensor;
00427
00428 ROS_ASSERT(map_one_joint[i][0].getType() == XmlRpc::XmlRpcValue::TypeString);
00429 tmp_vect.sensor_names.push_back(static_cast<string> (map_one_joint[i][0]));
00430 tmp_joint_to_sensor.sensor_id = sensors_map[static_cast<string> (map_one_joint[i][0])];
00431
00432 ROS_ASSERT(map_one_joint[i][1].getType() == XmlRpc::XmlRpcValue::TypeDouble);
00433 tmp_joint_to_sensor.coeff = static_cast<double> (map_one_joint[i][1]);
00434 tmp_vect.joint_to_sensor_vector.push_back(tmp_joint_to_sensor);
00435 }
00436 joint_to_sensor_vect.push_back(tmp_vect);
00437 }
00438
00439 return joint_to_sensor_vect;
00440 }
00441
00442 template<class StatusType, class CommandType>
00443 vector<UpdateConfig> SrRobotLib<StatusType,
00444 CommandType>::read_update_rate_configs(string base_param,
00445 int nb_data_defined,
00446 const char *human_readable_data_types[],
00447 const int32u data_types[])
00448 {
00449 vector<UpdateConfig> update_rate_configs_vector;
00450 typedef pair<string, int32u> ConfPair;
00451 vector<ConfPair> config;
00452
00453 for (int i = 0; i < nb_data_defined; ++i)
00454 {
00455 ConfPair tmp;
00456
00457 ROS_DEBUG_STREAM(" read " << base_param << " config [" << i << "] = " << human_readable_data_types[i]);
00458
00459 tmp.first = base_param + human_readable_data_types[i];
00460 tmp.second = data_types[i];
00461 config.push_back(tmp);
00462 }
00463
00464 for (unsigned int i = 0; i < config.size(); ++i)
00465 {
00466 double rate;
00467 if (nodehandle_.getParam(config[i].first, rate))
00468 {
00469 UpdateConfig config_tmp;
00470
00471 config_tmp.when_to_update = rate;
00472 config_tmp.what_to_update = config[i].second;
00473 update_rate_configs_vector.push_back(config_tmp);
00474
00475 ROS_DEBUG_STREAM(
00476 " read " << base_param << " config [" << i << "] = " << "what: " << config_tmp.what_to_update <<
00477 " when: " << config_tmp.when_to_update);
00478 }
00479 }
00480
00481 return update_rate_configs_vector;
00482 }
00483
00484 template<class StatusType, class CommandType>
00485 void SrRobotLib<StatusType, CommandType>::tactile_init_timer_callback(const ros::TimerEvent &event)
00486 {
00487
00488 boost::mutex::scoped_lock l(*lock_tactile_init_timeout_);
00489
00490 if (tactile_current_state == operation_mode::device_update_state::INITIALIZATION)
00491 {
00492 tactile_current_state = operation_mode::device_update_state::OPERATION;
00493 tactiles = boost::shared_ptr<tactiles::UBI0<StatusType, CommandType> >(
00494 new tactiles::UBI0<StatusType, CommandType>(nodehandle_, device_id_,
00495 ubi0_sensor_update_rate_configs_vector,
00496 operation_mode::device_update_state::OPERATION,
00497 tactiles_init->tactiles_vector));
00498 ROS_ERROR_STREAM("Tactile Initialization Timeout: considering UBI0 tactiles");
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516 template
00517 class SrRobotLib<ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_STATUS, ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_COMMAND>;
00518
00519 template
00520 class SrRobotLib<ETHERCAT_DATA_STRUCTURE_0230_PALM_EDC_STATUS, ETHERCAT_DATA_STRUCTURE_0230_PALM_EDC_COMMAND>;
00521
00522 template
00523 class SrRobotLib<ETHERCAT_DATA_STRUCTURE_0300_PALM_EDC_STATUS, ETHERCAT_DATA_STRUCTURE_0300_PALM_EDC_COMMAND>;
00524
00525 }
00526
00527
00528
00529
00530
00531