00001 00030 //ROS include 00031 #include <ros/ros.h> 00032 00033 //messages 00034 #include <diagnostic_msgs/DiagnosticStatus.h> 00035 #include <diagnostic_msgs/DiagnosticArray.h> 00036 00037 //generic C/C++ include 00038 #include <vector> 00039 #include <string> 00040 #include <sstream> 00041 00042 #include <boost/smart_ptr.hpp> 00043 00044 #include "sr_hand/sr_diagnosticer.h" 00045 00046 using namespace ros; 00047 using namespace shadowrobot; 00048 00049 namespace shadowrobot 00050 { 00051 00052 // 9 is the number of messages sent on the palm: used in 00053 // converting rate to Hz 00054 const double SRDiagnosticer::palm_numb_msg_const = 9.0; 00055 const double SRDiagnosticer::palm_msg_rate_const = 4000.0; 00056 00058 // CONSTRUCTOR/DESTRUCTOR // 00060 00061 SRDiagnosticer::SRDiagnosticer( boost::shared_ptr<SRArticulatedRobot> sr_art_robot, hardware_types hw_type ) : 00062 n_tilde("~"), publish_rate(0.0) 00063 { 00064 sr_articulated_robot = sr_art_robot; 00065 00066 // set publish frequency 00067 double publish_freq; 00068 n_tilde.param("publish_frequency_diagnostics", publish_freq, 1.0); 00069 publish_rate = Rate(publish_freq); 00070 00071 //publishes /diagnostics messages 00072 sr_diagnostics_pub = node.advertise<diagnostic_msgs::DiagnosticArray> ("diagnostics", 2); 00073 00074 hardware_type = hw_type; 00075 } 00076 00077 SRDiagnosticer::~SRDiagnosticer() 00078 { 00079 //if( shadowhand != NULL ) 00080 // delete shadowhand; 00081 } 00082 00084 // PUBLISH METHOD // 00086 void SRDiagnosticer::publish() 00087 { 00088 diagnostic_msgs::DiagnosticArray diag_msg; 00089 00090 std::vector<diagnostic_msgs::DiagnosticStatus> vec_diag_msg; 00091 00092 std::vector<DiagnosticData> diagnostics = sr_articulated_robot->getDiagnostics(); 00093 00094 std::stringstream ss; 00095 00096 for( unsigned int i = 0; i < diagnostics.size(); ++i ) 00097 { 00098 diagnostic_msgs::DiagnosticStatus diag; 00099 00100 std::vector<diagnostic_msgs::KeyValue> keyvalues; 00101 00102 diag.level = diagnostics[i].level; 00103 00104 switch( hardware_type ) 00105 { 00106 case sr_hand_hardware: 00107 diag.name = "srh/" + diagnostics[i].joint_name; 00108 break; 00109 case sr_arm_hardware: 00110 diag.name = "sr_arm/" + diagnostics[i].joint_name; 00111 break; 00112 default: 00113 diag.name = diagnostics[i].joint_name; 00114 break; 00115 } 00116 00117 diagnostic_msgs::KeyValue keyval; 00118 keyval.key = "Target"; 00119 00120 ss.str(""); 00121 ss << diagnostics[i].target; 00122 keyval.value = ss.str(); 00123 keyvalues.push_back(keyval); 00124 00125 keyval.key = "Position"; 00126 ss.str(""); 00127 ss << diagnostics[i].position; 00128 keyval.value = ss.str(); 00129 keyvalues.push_back(keyval); 00130 00131 if( diag.level == 0 ) 00132 diag.message = "OK"; 00133 00134 diag.values = keyvalues; 00135 vec_diag_msg.push_back(diag); 00136 } 00137 00138 //set the standard message 00139 diag_msg.status = vec_diag_msg; 00140 00141 /* //get the data from the hand 00142 for (unsigned int i=0; i<NUM_HAND_JOINTS + 4; ++i) 00143 { 00144 diagnostic_msgs::DiagnosticStatus diag; 00145 std::vector<diagnostic_msgs::KeyValue> keyvalues; 00146 00147 //set level to OK at first, will be updated if we get a flag 00148 //later on. 00149 diag.level = 0; 00150 00151 //name 00152 std::stringstream name; 00153 name << "shadowhand/motors/"; 00154 name << hand_joints[i].joint_name; 00155 diag.name = name.str(); 00156 00157 std::stringstream ss; 00158 std::stringstream warning_summary; 00159 00160 00161 //more information 00162 if (hand_joints[i].a.smartmotor.has_sensors) 00163 { 00164 //check for error_flags 00165 uint64_t uuid = robot_node_id(hand_joints[i].a.smartmotor.nodename); 00166 00167 char name_buff[40]; 00168 snprintf(name_buff, 40, "%Lx", uuid); 00169 diag.hardware_id = name_buff; 00170 00171 hand_protocol_flags fl; 00172 fl = hand_protocol_get_status_flags(uuid); 00173 00174 hand_protocol_config_t hand_config; 00175 hand_config = hand_protocol_get_config(uuid); 00176 00177 //stringstream used everywhere to set strings... 00178 std::stringstream tmp; 00179 00180 diagnostic_msgs::KeyValue keyval; 00181 if (fl.valid) 00182 { 00183 struct hand_protocol_flags_smart_motor f; 00184 f = fl.u.smart_motor; 00185 00187 // ERRORS 00189 if( hand_protocol_dead(uuid) ) 00190 { 00191 warning_summary << "DEAD "; 00192 diag.level = 2; 00193 00194 keyval.key = "DEAD"; 00195 tmp.str(""); 00196 tmp << "The node is DEAD (failed to pong back)."; 00197 keyval.value = tmp.str(); 00198 keyvalues.push_back(keyval); 00199 } 00200 00201 00202 if( f.nfault_pin ) 00203 { 00204 warning_summary << "NFAULT "; 00205 00206 diag.level = 2; 00207 00208 00209 keyval.key = "NFAULT"; 00210 tmp.str(""); 00211 tmp << "The motor is in NFAULT state "; 00212 keyval.value = tmp.str(); 00213 keyvalues.push_back(keyval); 00214 } 00215 00216 00217 00219 // SOME GENERIC WARNINGS 00221 00222 if( f.mode_active ) 00223 { 00224 warning_summary << "IDLE "; 00225 00226 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00227 00228 00229 keyval.key = "IDLE"; 00230 tmp.str(""); 00231 tmp << "The motor is in IDLE state"; 00232 keyval.value = tmp.str(); 00233 keyvalues.push_back(keyval); 00234 } 00235 if( f.mode_config ) 00236 { 00237 warning_summary << "CONFIG "; 00238 00239 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00240 00241 00242 keyval.key = "CONFIG"; 00243 tmp.str(""); 00244 tmp << "The motor is in CONFIG mode"; 00245 keyval.value = tmp.str(); 00246 keyvalues.push_back(keyval); 00247 } 00248 00249 00251 // SETPOINT 00253 keyval.key = "- Setpoints"; 00254 tmp.str(" "); 00255 keyval.value = tmp.str(); 00256 keyvalues.push_back(keyval); 00257 00258 //what's the setpoint set to? 00259 keyval.key = " Setpoint"; 00260 tmp.str(""); 00261 uint16_t sensorId = hand_config->u.smartmotor.setpoint_num; 00262 tmp << get_setpoint_name(sensorId); 00263 keyval.value = tmp.str(); 00264 keyvalues.push_back(keyval); 00265 00266 //is there a SETPOINT error? 00267 if( f.setp_valid ) 00268 { 00269 warning_summary << "SETPOINT "; 00270 00271 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00272 00273 00274 keyval.key = " SETPOINT"; 00275 tmp.str(""); 00276 tmp << "The SETPOINT is invalid"; 00277 keyval.value = tmp.str(); 00278 keyvalues.push_back(keyval); 00279 } 00280 00281 //read the actual value of the target 00282 keyval.key = " Target"; 00283 tmp.str(""); 00284 tmp << robot_read_sensor(&hand_joints[i].joint_target); 00285 keyval.value = tmp.str(); 00286 keyvalues.push_back( keyval ); 00287 00288 //read value of setpoint (to compare with actual target) 00289 struct sensor temp; 00290 keyval.key = " Target from setpoint"; 00291 tmp.str(""); 00292 robot_channel_to_sensor("smart_motor_setpoints", sensorId, &temp); 00293 tmp << robot_read_sensor(&temp); 00294 keyval.value = tmp.str(); 00295 keyvalues.push_back(keyval); 00296 00297 00299 // SENSOR 00301 keyval.key = "- Sensors"; 00302 tmp.str(" "); 00303 keyval.value = tmp.str(); 00304 keyvalues.push_back(keyval); 00305 00306 //what's the sensor set to? 00307 keyval.key = " Sensor"; 00308 tmp.str(""); 00309 sensorId = hand_config->u.smartmotor.sensor_num; 00310 00311 tmp << get_setpoint_name(sensorId); 00312 keyval.value = tmp.str(); 00313 keyvalues.push_back(keyval); 00314 00315 //is there a SENSOR error? 00316 if( f.sensor_valid ) 00317 { 00318 warning_summary << "SENSOR "; 00319 00320 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00321 00322 00323 keyval.key = " SENSOR"; 00324 tmp.str(""); 00325 tmp << "The SENSOR is invalid"; 00326 keyval.value = tmp.str(); 00327 keyvalues.push_back(keyval); 00328 } 00329 00330 //read the actual value of the position 00331 keyval.key = " Position"; 00332 tmp.str(""); 00333 tmp << robot_read_sensor(&hand_joints[i].position); 00334 keyval.value = tmp.str(); 00335 keyvalues.push_back( keyval ); 00336 00337 //read value of sensor (to compare with actual position) 00338 keyval.key = " Position from sensor"; 00339 tmp.str(""); 00340 robot_channel_to_sensor("smart_motor_setpoints", sensorId, &temp); 00341 tmp << robot_read_sensor(&temp); 00342 keyval.value = tmp.str(); 00343 keyvalues.push_back(keyval); 00344 00346 // TEMPERATURE 00348 keyval.key = "- Temperatures"; 00349 tmp.str(" "); 00350 keyval.value = tmp.str(); 00351 keyvalues.push_back(keyval); 00352 00353 //value of the temperature 00354 keyval.key = " temperature"; 00355 float tempVal = robot_read_sensor(&hand_joints[i].a.smartmotor.temperature); 00356 tmp.str(""); 00357 tmp << tempVal; 00358 keyval.value = tmp.str(); 00359 keyvalues.push_back( keyval ); 00360 00361 //Is there a cutout? 00362 if( f.temperature_cutout ) 00363 { 00364 warning_summary << "TEMP "; 00365 00366 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00367 00368 00369 keyval.key = " TEMPERATURE"; 00370 tmp.str(""); 00371 tmp << "The motor reached it's TEMPERATURE cutout value"; 00372 keyval.value = tmp.str(); 00373 keyvalues.push_back(keyval); 00374 } 00375 00376 //value of the temperature cutout? 00377 keyval.key = " max temp"; 00378 tmp.str(""); 00379 tmp << ((float)(hand_config->u.smartmotor.max_motor_temperature)/256.0f); 00380 keyval.value = tmp.str(); 00381 keyvalues.push_back(keyval); 00382 00384 // CURRENT 00386 keyval.key = "- Currents"; 00387 tmp.str(" "); 00388 keyval.value = tmp.str(); 00389 keyvalues.push_back(keyval); 00390 00391 keyval.key = " current"; 00392 00393 char incoming_current[40]; 00394 snprintf(incoming_current, 40, "%Ld mA", robot_read_incoming(&hand_joints[i].a.smartmotor.current)); 00395 keyval.value = incoming_current; 00396 keyvalues.push_back( keyval ); 00397 00398 if( f.current_throttle ) 00399 { 00400 warning_summary << "CURRENT "; 00401 00402 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00403 00404 00405 keyval.key = " CURRENT"; 00406 tmp.str(""); 00407 tmp << "The motor reached it's CURRENT cutout value"; 00408 keyval.value = tmp.str(); 00409 keyvalues.push_back(keyval); 00410 } 00411 00412 //value of the temperature cutout? 00413 keyval.key = " max current"; 00414 tmp.str(""); 00415 tmp << (int)(hand_config->u.smartmotor.max_motor_current); 00416 tmp << "mA"; 00417 keyval.value = tmp.str(); 00418 keyvalues.push_back(keyval); 00419 00421 // FORCE 00423 keyval.key = "- Forces"; 00424 tmp.str(" "); 00425 keyval.value = tmp.str(); 00426 keyvalues.push_back(keyval); 00427 00428 keyval.key = " force"; 00429 char incoming_force[40]; 00430 int16_t torque = (int16_t)robot_read_incoming(&hand_joints[i].a.smartmotor.torque); 00431 00432 // if(torque > 32767) 00433 // torque -= 65536; 00434 int torque_32 =- torque; 00435 snprintf(incoming_force, 40, "%d", torque_32); 00436 keyval.value = incoming_force; 00437 keyvalues.push_back( keyval ); 00438 00439 if( f.force_hard_limit ) 00440 { 00441 warning_summary << "FORCE "; 00442 00443 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00444 00445 00446 keyval.key = " FORCE"; 00447 tmp.str(""); 00448 tmp << "The motor reached it's FORCE cutout value"; 00449 keyval.value = tmp.str(); 00450 keyvalues.push_back(keyval); 00451 } 00452 00453 //value of the force cutout? 00454 keyval.key = " max force"; 00455 tmp.str(""); 00456 tmp << (int)(hand_config->u.smartmotor.safety_cutout_force); 00457 keyval.value = tmp.str(); 00458 keyvalues.push_back(keyval); 00459 00460 if( f.straingauge_ref_limit0 ) 00461 { 00462 warning_summary << "REF0 LIMIT "; 00463 00464 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00465 00466 00467 keyval.key = " REF0_LIMIT"; 00468 tmp.str(""); 00469 tmp << "The straingauge0 is at its limit."; 00470 keyval.value = tmp.str(); 00471 keyvalues.push_back(keyval); 00472 } 00473 if( f.straingauge_ref_limit1 ) 00474 { 00475 warning_summary << "REF1 LIMIT "; 00476 00477 diag.level > 1 ? diag.level = diag.level : diag.level = 1; 00478 00479 00480 keyval.key = " REF1_LIMIT"; 00481 tmp.str(""); 00482 tmp << "The straingauge1 is at its limit."; 00483 keyval.value = tmp.str(); 00484 keyvalues.push_back(keyval); 00485 } 00486 00487 00489 // Contrlr config 00491 keyval.key = "- Controller Configuration"; 00492 tmp.str(" "); 00493 keyval.value = tmp.str(); 00494 keyvalues.push_back(keyval); 00495 00496 //PID 00497 keyval.key = " - PID"; 00498 tmp.str(" "); 00499 keyval.value = tmp.str(); 00500 keyvalues.push_back(keyval); 00501 00502 keyval.key = " P | I | D values"; 00503 tmp.str(""); 00504 tmp << (int)(hand_config->u.smartmotor.sensorP) << " | " 00505 << (int)(hand_config->u.smartmotor.sensorI) << " | " 00506 << (int)(hand_config->u.smartmotor.sensorD); 00507 keyval.value = tmp.str(); 00508 keyvalues.push_back(keyval); 00509 00510 keyval.key = " Imax | Deadband | Offset"; 00511 tmp.str(""); 00512 tmp << (int)(hand_config->u.smartmotor.sensorImax) << " | " 00513 << (int)(hand_config->u.smartmotor.sensorDeadband) << " | " 00514 << (int)(hand_config->u.smartmotor.sensorOffset); 00515 keyval.value = tmp.str(); 00516 keyvalues.push_back(keyval); 00517 00518 //force PID 00519 keyval.key = " - Force PID"; 00520 tmp.str(" "); 00521 keyval.value = tmp.str(); 00522 keyvalues.push_back(keyval); 00523 00524 keyval.key = " force: P | I | D values"; 00525 tmp.str(""); 00526 tmp << (int)(hand_config->u.smartmotor.forceP) << " | " 00527 << (int)(hand_config->u.smartmotor.forceI) << " | " 00528 << (int)(hand_config->u.smartmotor.forceD); 00529 keyval.value = tmp.str(); 00530 keyvalues.push_back(keyval); 00531 00532 keyval.key = " Imax | Deadband | Offset"; 00533 tmp.str(""); 00534 tmp << (int)(hand_config->u.smartmotor.forceImax) << " | " 00535 << (int)(hand_config->u.smartmotor.forceDeadband) << " | " 00536 << (int)(hand_config->u.smartmotor.forceOffset); 00537 keyval.value = tmp.str(); 00538 keyvalues.push_back(keyval); 00539 00541 // Transmission rates 00543 keyval.key = "- Transmission Rates"; 00544 tmp.str(" "); 00545 keyval.value = tmp.str(); 00546 keyvalues.push_back(keyval); 00547 //TRANSMIT RATE 00548 keyval.key = " transmission rate"; 00549 tmp.str(""); 00550 00551 tmp << palm_msg_rate_const/(palm_numb_msg_const*(float)(hand_config->u.smartmotor.tx_freq)) << "Hz"; 00552 keyval.value = tmp.str(); 00553 keyvalues.push_back(keyval); 00554 00555 //DEBUG TRANSMIT RATE 00556 keyval.key = " debug transmission rate"; 00557 tmp.str(""); 00558 tmp << palm_msg_rate_const/(palm_numb_msg_const*(float)(hand_config->u.smartmotor.debug_tx_freq)) << "Hz"; 00559 keyval.value = tmp.str(); 00560 keyvalues.push_back(keyval); 00561 } 00562 } 00563 00564 switch(diag.level) 00565 { 00566 default: 00567 ss << "OK"; 00568 break; 00569 case 1: 00570 ss << "WARNING - " << warning_summary.str(); 00571 break; 00572 case 2: 00573 ss << "ERROR - " << warning_summary.str(); 00574 break; 00575 } 00576 00577 //set the diagnostic message 00578 diag.message = ss.str(); 00579 00580 diag.values = keyvalues; 00581 myVector.push_back(diag); 00582 } 00583 00584 //set the standard message 00585 msg.status = myVector; 00586 */ 00587 //publish the diagnostic data 00588 00589 diag_msg.header.stamp = ros::Time::now(); 00590 sr_diagnostics_pub.publish(diag_msg); 00591 00592 ros::spinOnce(); 00593 publish_rate.sleep(); 00594 } 00595 00596 }// end namespace 00597 00598