$search
00001 00027 #include <ros/ros.h> 00028 00029 #include "sr_hand/hand/real_shadowhand.h" 00030 //our robot code 00031 #include <robot/config.h> 00032 #include <robot/robot.h> 00033 #include <robot/hand_protocol.h> 00034 #include <robot/hand.h> 00035 #ifdef FINGER 00036 #define LAST_HAND_JOINT NUM_FINGER_JOINTS 00037 #else 00038 #define LAST_HAND_JOINT START_OF_ARM 00039 #endif 00040 00041 namespace shadowrobot 00042 { 00043 RealShadowhand::RealShadowhand() : 00044 SRArticulatedRobot() 00045 { 00046 /* We need to attach the program to the robot, or fail if we cannot. */ 00047 if( robot_init() < 0 ) 00048 { 00049 ROS_FATAL("Robot interface broken\n"); 00050 ROS_BREAK(); 00051 } 00052 00053 /* We need to attach the program to the hand as well, or fail if we cannot. */ 00054 if( hand_init() < 0 ) 00055 { 00056 ROS_FATAL("Hand interface broken\n"); 00057 ROS_BREAK(); 00058 } 00059 00060 initializeMap(); 00061 00062 self_test = boost::shared_ptr<self_test::TestRunner>(new self_test::TestRunner()); 00063 00064 self_test->add("Pretest", this, &RealShadowhand::pretest); 00065 self_test->add("Number of messages Received", this, &RealShadowhand::test_messages); 00066 self_test->add("Posttest", this, &RealShadowhand::posttest); 00067 } 00068 00069 RealShadowhand::~RealShadowhand() 00070 { 00071 } 00072 00073 void RealShadowhand::initializeMap() 00074 { 00075 joints_map_mutex.lock(); 00076 parameters_map_mutex.lock(); 00077 00078 JointData tmpData; 00079 00080 tmpData.position = 0.0; 00081 tmpData.target = 0.0; 00082 tmpData.temperature = 0.0; 00083 tmpData.current = 0.0; 00084 tmpData.force = 0.0; 00085 tmpData.flags = ""; 00086 00087 for( unsigned int i = 0; i < LAST_HAND_JOINT; i++ ) 00088 { 00089 std::string name = hand_joints[i].joint_name; 00090 tmpData.jointIndex = i; 00091 00092 joints_map[name] = tmpData; 00093 00094 ROS_DEBUG("NAME[%d]: %s ", i, name.c_str()); 00095 } 00096 00097 parameters_map["d"] = PARAM_d; 00098 parameters_map["i"] = PARAM_i; 00099 parameters_map["p"] = PARAM_p; 00100 parameters_map["target"] = PARAM_target; 00101 parameters_map["sensor"] = PARAM_sensor; 00102 00103 parameters_map["valve"] = PARAM_valve; 00104 parameters_map["dead"] = PARAM_deadband; 00105 parameters_map["deadband"] = PARAM_deadband; 00106 parameters_map["imax"] = PARAM_imax; 00107 parameters_map["offset"] = PARAM_output_offset; 00108 parameters_map["shift"] = PARAM_shift; 00109 parameters_map["max"] = PARAM_output_max; 00110 00112 parameters_map["motor_maxforce"] = PARAM_motor_maxforce; 00113 parameters_map["motor_safeforce"] = PARAM_motor_safeforce; 00114 00115 parameters_map["force_p"] = PARAM_force_p; 00116 parameters_map["force_i"] = PARAM_force_i; 00117 parameters_map["force_d"] = PARAM_force_d; 00118 00119 parameters_map["force_imax"] = PARAM_force_imax; 00120 parameters_map["force_out_shift"] = PARAM_force_out_shift; 00121 parameters_map["force_deadband"] = PARAM_force_deadband; 00122 parameters_map["force_offset"] = PARAM_force_offset; 00123 00124 parameters_map["sensor_imax"] = PARAM_sensor_imax; 00125 parameters_map["sensor_out_shift"] = PARAM_sensor_out_shift; 00126 parameters_map["sensor_deadband"] = PARAM_sensor_deadband; 00127 parameters_map["sensor_offset"] = PARAM_sensor_offset; 00128 parameters_map["max_temp"] = PARAM_max_temperature; 00129 parameters_map["max_temperature"] = PARAM_max_temperature; 00130 parameters_map["max_current"] = PARAM_max_current; 00131 00132 parameters_map_mutex.unlock(); 00133 joints_map_mutex.unlock(); 00134 } 00135 00136 short RealShadowhand::sendupdate( std::string joint_name, double target ) 00137 { 00138 joints_map_mutex.lock(); 00139 00140 //search the sensor in the hash_map 00141 JointsMap::iterator iter = joints_map.find(joint_name); 00142 00143 if( iter != joints_map.end() ) 00144 { 00145 JointData tmpData = joints_map.find(joint_name)->second; 00146 int index_hand_joints = tmpData.jointIndex; 00147 00148 //trim to the correct range 00149 if( target < hand_joints[index_hand_joints].min_angle ) 00150 target = hand_joints[index_hand_joints].min_angle; 00151 if( target > hand_joints[index_hand_joints].max_angle ) 00152 target = hand_joints[index_hand_joints].max_angle; 00153 00154 //here we update the actual hand angles 00155 robot_update_sensor(&hand_joints[index_hand_joints].joint_target, target); 00156 joints_map_mutex.unlock(); 00157 return 0; 00158 } 00159 00160 ROS_DEBUG("Joint %s not found", joint_name.c_str()); 00161 00162 joints_map_mutex.unlock(); 00163 return -1; 00164 } 00165 00166 JointData RealShadowhand::getJointData( std::string joint_name ) 00167 { 00168 joints_map_mutex.lock(); 00169 00170 JointsMap::iterator iter = joints_map.find(joint_name); 00171 00172 //joint not found 00173 if( iter == joints_map.end() ) 00174 { 00175 ROS_ERROR("Joint %s not found.", joint_name.c_str()); 00176 JointData noData; 00177 noData.position = 0.0; 00178 noData.target = 0.0; 00179 noData.temperature = 0.0; 00180 noData.current = 0.0; 00181 noData.force = 0.0; 00182 noData.flags = ""; 00183 noData.jointIndex = 0; 00184 00185 joints_map_mutex.unlock(); 00186 return noData; 00187 } 00188 00189 //joint found 00190 JointData tmpData = iter->second; 00191 int index = tmpData.jointIndex; 00192 00193 tmpData.position = robot_read_sensor(&hand_joints[index].position); 00194 tmpData.target = robot_read_sensor(&hand_joints[index].joint_target); 00195 00196 //more information 00197 if( hand_joints[index].a.smartmotor.has_sensors ) 00198 { 00199 tmpData.temperature = robot_read_sensor(&hand_joints[index].a.smartmotor.temperature); 00200 tmpData.current = robot_read_sensor(&hand_joints[index].a.smartmotor.current); 00201 tmpData.force = robot_read_sensor(&hand_joints[index].a.smartmotor.torque); 00202 tmpData.flags = ""; 00203 } 00204 00205 joints_map[joint_name] = tmpData; 00206 00207 joints_map_mutex.unlock(); 00208 return tmpData; 00209 } 00210 00211 SRArticulatedRobot::JointsMap RealShadowhand::getAllJointsData() 00212 { 00213 //update the map for each joints 00214 for( JointsMap::const_iterator it = joints_map.begin(); it != joints_map.end(); ++it ) 00215 getJointData(it->first); 00216 00217 //hack for C6M2 with 4 fingers with coupling J1+J2=J0 00218 //copy J0/2 to J1 and J2 for FF MF RF LF 00219 joints_map_mutex.lock(); 00220 00221 std::string fingername("FF"); 00222 00223 JointsMap::iterator it_j0 = joints_map.find(fingername+"J0"); 00224 JointsMap::iterator it_j1 = joints_map.find(fingername+"J1"); 00225 JointsMap::iterator it_j2 = joints_map.find(fingername+"J2"); 00226 it_j1->second.target = it_j0->second.target/2.0; 00227 it_j2->second.target = it_j0->second.target/2.0; 00228 00229 fingername.assign("MF"); 00230 it_j0 = joints_map.find(fingername+"J0"); 00231 it_j1 = joints_map.find(fingername+"J1"); 00232 it_j2 = joints_map.find(fingername+"J2"); 00233 it_j1->second.target = it_j0->second.target/2.0; 00234 it_j2->second.target = it_j0->second.target/2.0; 00235 00236 fingername.assign("RF"); 00237 it_j0 = joints_map.find(fingername+"J0"); 00238 it_j1 = joints_map.find(fingername+"J1"); 00239 it_j2 = joints_map.find(fingername+"J2"); 00240 it_j1->second.target = it_j0->second.target/2.0; 00241 it_j2->second.target = it_j0->second.target/2.0; 00242 00243 fingername.assign("LF"); 00244 it_j0 = joints_map.find(fingername+"J0"); 00245 it_j1 = joints_map.find(fingername+"J1"); 00246 it_j2 = joints_map.find(fingername+"J2"); 00247 it_j1->second.target = it_j0->second.target/2.0; 00248 it_j2->second.target = it_j0->second.target/2.0; 00249 00250 joints_map_mutex.unlock(); 00251 00252 JointsMap tmp = JointsMap(joints_map); 00253 00254 //return the map 00255 return tmp; 00256 } 00257 00258 short RealShadowhand::setContrl( std::string contrlr_name, JointControllerData ctrlr_data ) 00259 { 00260 parameters_map_mutex.lock(); 00261 00262 struct controller_config myConfig; 00263 memset(&myConfig, 0, sizeof(myConfig)); 00264 00265 //set the nodename from contrlr_name 00266 myConfig.nodename = contrlr_name.c_str(); 00267 00268 controller_read_from_hardware(&myConfig); 00269 ROS_DEBUG("%s", controller_to_string(&myConfig)); 00270 00271 for( unsigned int i = 0; i < ctrlr_data.data.size(); ++i ) 00272 { 00273 std::string name = ctrlr_data.data[i].name; 00274 ParametersMap::iterator iter = parameters_map.find(name); 00275 00276 //parameter not found 00277 if( iter == parameters_map.end() ) 00278 { 00279 ROS_ERROR("Parameter %s not found.", name.c_str()); 00280 continue; 00281 } 00282 00283 //parameter found 00284 controller_update_param(&myConfig, (controller_param)iter->second, ctrlr_data.data[i].value.c_str()); 00285 } 00286 00287 parameters_map_mutex.unlock(); 00288 00289 int result_ctrlr = controller_write_to_hardware(&myConfig); 00290 if( result_ctrlr ) 00291 { 00292 ROS_ERROR("Failed to update contrlr (%s)", myConfig.nodename ); 00293 return -1; 00294 } 00295 00296 return 0; 00297 } 00298 00299 JointControllerData RealShadowhand::getContrl( std::string contrlr_name ) 00300 { 00301 struct controller_config myConfig; 00302 memset(&myConfig, 0, sizeof(myConfig)); 00303 00304 //set the nodename from contrlr_name 00305 myConfig.nodename = contrlr_name.c_str(); 00306 00307 controller_read_from_hardware(&myConfig); 00308 00309 JointControllerData tmp_data; 00310 00311 ROS_WARN("The get contrlr function is not implemented in the real shadowhand."); 00312 00313 return tmp_data; 00314 00315 } 00316 00317 short RealShadowhand::setConfig( std::vector<std::string> myConfig ) 00318 { 00319 ROS_WARN("The set config function is not implemented in the real shadowhand."); 00320 00321 /* 00322 hand_protocol_config_t cfg; 00323 hand_protocol_get_config(cfg); 00324 00325 //set the transmit rate value 00326 int value = msg->rate_value; 00327 cfg->u.palm.tx_freq[num]=value; 00328 00329 //send the config to the palm. 00330 hand_protocol_set_config(cfg); 00331 */ 00332 00333 return 0; 00334 } 00335 00336 void RealShadowhand::getConfig( std::string joint_name ) 00337 { 00338 ROS_WARN("The get config function is not yet implement in the real shadow hand."); 00339 } 00340 00341 std::vector<DiagnosticData> RealShadowhand::getDiagnostics() 00342 { 00343 //it's alright to do the tests when we're publishing the diagnostics 00344 self_test->checkTest(); 00345 00346 std::vector<DiagnosticData> returnVector; 00347 00348 DiagnosticData tmpData; 00349 std::stringstream ss; 00350 00351 //get the data from the hand 00352 for( unsigned int index = 0; index < START_OF_ARM; ++index ) 00353 { 00354 tmpData.joint_name = std::string(hand_joints[index].joint_name); 00355 tmpData.level = 0; 00356 00357 tmpData.position = robot_read_sensor(&hand_joints[index].position); 00358 tmpData.target = robot_read_sensor(&hand_joints[index].joint_target); 00359 00360 //more information 00361 if( hand_joints[index].a.smartmotor.has_sensors ) 00362 { 00363 //reads the number of received sensor msgs from the debug node. 00364 int res; 00365 if( *(&hand_joints[index].a.smartmotor.debug_nodename) != NULL) 00366 { 00367 std::string debug_node_name = *(&hand_joints[index].a.smartmotor.debug_nodename); 00368 00369 //get all the debug values 00370 std::map<const std::string, const unsigned int>::const_iterator iter; 00371 for(iter = debug_values::names_and_offsets.begin(); 00372 iter != debug_values::names_and_offsets.end(); ++iter) 00373 { 00374 struct sensor sensor_tmp; 00375 00376 res = robot_channel_to_sensor(debug_node_name.c_str(), iter->second, &sensor_tmp); 00377 tmpData.debug_values[iter->first] = robot_read_incoming(&sensor_tmp); 00378 } 00379 } 00380 // else 00381 // ROS_ERROR_STREAM(tmpData.joint_name << ": no debug sensor" ); 00382 //reads temperature current and force. 00383 tmpData.temperature = robot_read_sensor(&hand_joints[index].a.smartmotor.temperature); 00384 tmpData.current = robot_read_sensor(&hand_joints[index].a.smartmotor.current); 00385 tmpData.force = robot_read_sensor(&hand_joints[index].a.smartmotor.torque); 00386 00387 //check for error_flags 00388 00389 struct hand_protocol_flags fl; 00390 uint64_t uuid = robot_node_id(hand_joints[index].a.smartmotor.nodename); 00391 fl = hand_protocol_get_status_flags(uuid); 00392 if( fl.valid ) 00393 { 00394 ss.clear(); 00395 struct hand_protocol_flags_smart_motor f; 00396 f = fl.u.smart_motor; 00397 00398 bool at_least_one_error_flag = false; 00399 if( f.nfault_pin ) 00400 { 00401 at_least_one_error_flag = true; 00402 ss << "NFAULT "; 00403 ROS_WARN( "[%s]: NFAULT", hand_joints[index].joint_name ); 00404 } 00405 if( f.temperature_cutout ) 00406 { 00407 at_least_one_error_flag = true; 00408 ss << "TEMP "; 00409 } 00410 if( f.current_throttle ) 00411 { 00412 at_least_one_error_flag = true; 00413 ss << "CURRENT "; 00414 } 00415 if( f.force_hard_limit ) 00416 { 00417 at_least_one_error_flag = true; 00418 ss << "FORCE "; 00419 } 00420 if( hand_protocol_dead(uuid) ) 00421 { 00422 at_least_one_error_flag = true; 00423 ss << "DEAD "; 00424 } 00425 00426 //if a flag is up, then print a warning as well 00427 if( at_least_one_error_flag ) 00428 { 00429 ROS_WARN( "[%s]: %s", hand_joints[index].joint_name, (ss.str()).c_str()); 00430 tmpData.level = 1; 00431 } 00432 00433 tmpData.flags = ss.str(); 00434 } 00435 } 00436 00437 returnVector.push_back(tmpData); 00438 } 00439 return returnVector; 00440 } 00441 00443 // TESTS // 00445 void RealShadowhand::pretest(diagnostic_updater::DiagnosticStatusWrapper& status) 00446 { 00447 ROS_INFO("Preparing the environment to run self tests."); 00448 00449 //lock all the mutexes to make sure we're not publishing other messages 00450 joints_map_mutex.lock(); 00451 parameters_map_mutex.lock(); 00452 controllers_map_mutex.lock(); 00453 00454 //TODO: set the palm transmit rate to max? 00455 00456 sleep(1); 00457 00458 status.summary(diagnostic_msgs::DiagnosticStatus::OK, "Pretest completed successfully."); 00459 } 00460 00461 void RealShadowhand::posttest(diagnostic_updater::DiagnosticStatusWrapper& status) 00462 { 00463 ROS_INFO("Restoring the environment after the self tests."); 00464 00465 //test finished, unlocking all the mutexes 00466 joints_map_mutex.unlock(); 00467 parameters_map_mutex.unlock(); 00468 controllers_map_mutex.unlock(); 00469 00470 //TODO: reset the palm transmit rate to previous state? 00471 00472 status.summary(diagnostic_msgs::DiagnosticStatus::OK, "Postest completed successfully."); 00473 } 00474 00475 void RealShadowhand::test_messages(diagnostic_updater::DiagnosticStatusWrapper& status) 00476 { 00477 ROS_WARN("Starting the test: Number of messages Received"); 00478 00479 std::pair<unsigned char, std::string> test_result; 00480 test_result.first = diagnostic_msgs::DiagnosticStatus::OK; 00481 00482 for(unsigned int index_freq=0; index_freq < sr_self_tests::msgs_frequency_size; ++index_freq) 00483 { 00484 ros::Rate test_rate(sr_self_tests::msgs_frequency[index_freq]); 00485 for(unsigned int index_joint=0; index_joint < sr_self_tests::joints_to_test_size; ++index_joint) 00486 { 00487 std::pair<unsigned char, std::string> tmp_test_result; 00488 tmp_test_result = test_messages_routine(sr_self_tests::joints_to_test[index_joint], sr_self_tests::nb_targets_to_send, test_rate); 00489 00490 if( tmp_test_result.first == diagnostic_msgs::DiagnosticStatus::ERROR) 00491 test_result.first = diagnostic_msgs::DiagnosticStatus::ERROR; 00492 00493 std::stringstream ss; 00494 ss << "\n[" << sr_self_tests::msgs_frequency[index_freq] << "Hz]: "; 00495 ss << tmp_test_result.second; 00496 00497 test_result.second += ss.str(); 00498 } 00499 } 00500 status.summary(test_result.first, test_result.second); 00501 } 00502 00503 std::pair<unsigned char, std::string> RealShadowhand::test_messages_routine(std::string joint_name, unsigned int repeat, ros::Rate rate) 00504 { 00505 std::pair<unsigned char, std::string> test_result; 00506 00507 //id should be motor board number 00508 std::string ID = "1"; 00509 self_test->setID(ID.c_str()); 00510 00511 unsigned int nb_msgs_sent = 0; 00512 unsigned int nb_msgs_received = 0; 00513 00514 //sending lots of data to one joint 00515 JointsMap::iterator iter_joints_map = joints_map.find(joint_name); 00516 00517 struct sensor sensor_msgs_received; 00518 00519 if( iter_joints_map == joints_map.end() ) 00520 { 00521 std::stringstream ss; 00522 ss << "No messages sent: couldn't find joint "<<joint_name; 00523 00524 test_result.first = diagnostic_msgs::DiagnosticStatus::ERROR; 00525 test_result.second = ss.str(); 00526 return test_result; 00527 } 00528 00529 //OK joint found 00530 JointData tmpData = joints_map.find(joint_name)->second; 00531 int index_hand_joints = tmpData.jointIndex; 00532 float target = hand_joints[index_hand_joints].min_angle; 00533 00534 //testing a joint which doesn't have a smartmotor 00535 if( !hand_joints[index_hand_joints].a.smartmotor.has_sensors ) 00536 { 00537 std::stringstream ss; 00538 ss << "No messages sent: joint["<<joint_name<<"] doesn't have any motor attached"; 00539 00540 test_result.first = diagnostic_msgs::DiagnosticStatus::ERROR; 00541 test_result.second = ss.str(); 00542 return test_result; 00543 } 00544 00545 ROS_DEBUG("Checking the current number of received messages"); 00546 00547 int res; 00548 std::string debug_node_name = *(&hand_joints[index_hand_joints].a.smartmotor.debug_nodename); 00549 std::map<const std::string, const unsigned int>::const_iterator iter_debug_values = debug_values::names_and_offsets.find("Num sensor Msgs received"); 00550 00551 res = robot_channel_to_sensor(debug_node_name.c_str(), iter_debug_values->second, &sensor_msgs_received); 00552 00553 //check the number of messages already received when starting the test 00554 nb_msgs_received = robot_read_incoming(&sensor_msgs_received) - nb_msgs_received; 00555 00556 sleep(1); 00557 00558 //check if no other messages have been received 00559 if( nb_msgs_received != robot_read_incoming(&sensor_msgs_received)) 00560 { 00561 std::stringstream ss; 00562 ss << "New messages were received on the joint[" << joint_name.c_str() << "]." ; 00563 test_result.first = diagnostic_msgs::DiagnosticStatus::ERROR; 00564 test_result.second = ss.str(); 00565 00566 return test_result; 00567 } 00568 //ok still the same number of messages 00569 00570 ROS_DEBUG("Sending lots of messages."); 00571 00572 for(; nb_msgs_sent < repeat; ++nb_msgs_sent) 00573 { 00574 //send values to the sensor 00575 robot_update_sensor(&hand_joints[index_hand_joints].joint_target, target); 00576 rate.sleep(); 00577 ROS_DEBUG_STREAM("msg "<< nb_msgs_sent<< "/"<<sr_self_tests::nb_targets_to_send); 00578 } 00579 00580 ROS_DEBUG("Done sending the messages."); 00581 //wait for all the messages to be received? 00582 sleep(0.5); 00583 00584 ROS_DEBUG("Reading the number of received messages."); 00585 //compute the number of messages received during the test 00586 nb_msgs_received = robot_read_incoming(&sensor_msgs_received) - nb_msgs_received; 00587 00588 if( nb_msgs_sent == nb_msgs_received) 00589 { 00590 std::stringstream ss; 00591 ss << nb_msgs_sent << " messages sent, all received"; 00592 test_result.first = diagnostic_msgs::DiagnosticStatus::OK; 00593 test_result.second = ss.str(); 00594 return test_result; 00595 } 00596 else 00597 { 00598 std::stringstream ss; 00599 ss << nb_msgs_sent << " messages sent, "<<nb_msgs_received << " messages received"; 00600 test_result.first = diagnostic_msgs::DiagnosticStatus::ERROR; 00601 test_result.second = ss.str(); 00602 return test_result; 00603 } 00604 } 00605 } //end namespace 00606 00607 /* For the emacs weenies in the crowd. 00608 Local Variables: 00609 c-basic-offset: 2 00610 End: 00611 */