00001
00002 #include "riq_hand_ethercat_hardware/riq_hand.h"
00003 #include "riq_hand_ethercat_hardware/riq_hand_state.h"
00004 #include "riq_hand_ethercat_hardware/riq_hand_command.h"
00005
00006 #include <iomanip>
00007
00008 #include <boost/static_assert.hpp>
00009
00010 #include <ros/console.h>
00011
00012 #include <math.h>
00013 #include <algorithm>
00014
00015
00016 PLUGINLIB_REGISTER_CLASS(11, riq_hand_ethercat_hardware::RIQHand, EthercatDevice);
00017
00018 namespace riq_hand_ethercat_hardware
00019 {
00020
00021 RIQHandDiagnostics::RIQHandDiagnostics() :
00022 al_status_good_(false)
00023 {
00024
00025 }
00026
00027 void RIQHand::sizeAssert()
00028 {
00029 BOOST_STATIC_ASSERT(sizeof(RIQHandStateEcat) == STATUS_SIZE);
00030 BOOST_STATIC_ASSERT(sizeof(RIQHandCommandEcat) == COMMAND_SIZE);
00031 }
00032
00033 RIQHand::RIQHand() :
00034 state_cycle_count_(0),
00035 should_publish_(true),
00036 needs_watchdog_reset_(true),
00037 needs_reset_(false),
00038 needs_reset_countdown_(0),
00039 latched_fault_code_(RIQHandStateEcat::NO_FAULT),
00040 after_reset_countdown_(0),
00041 after_watchdog_reset_countdown_(0),
00042 halted_(false)
00043 {
00044
00045 }
00046
00047 RIQHand::~RIQHand()
00048 {
00049 delete sh_->get_fmmu_config();
00050 delete sh_->get_pd_config();
00051 }
00052
00053 void RIQHand::construct(EtherCAT_SlaveHandler *sh, int &start_address)
00054 {
00055 EthercatDevice::construct(sh, start_address);
00056
00057 command_size_ = COMMAND_SIZE;
00058 status_size_ = STATUS_SIZE;
00059
00060 EtherCAT_FMMU_Config *fmmu = new EtherCAT_FMMU_Config(2);
00061 (*fmmu)[0] = EC_FMMU(start_address,
00062 command_size_,
00063 0x00,
00064 0x07,
00065 COMMAND_PHY_ADDR,
00066 0x00,
00067 false,
00068 true,
00069 true);
00070
00071 start_address += command_size_;
00072
00073 (*fmmu)[1] = EC_FMMU(start_address,
00074 status_size_,
00075 0x00,
00076 0x07,
00077 STATUS_PHY_ADDR,
00078 0x00,
00079 true,
00080 false,
00081 true);
00082
00083 start_address += status_size_;
00084
00085 sh->set_fmmu_config(fmmu);
00086
00087
00088 EtherCAT_PD_Config *pd = new EtherCAT_PD_Config(2);
00089
00090
00091
00092 (*pd)[0] =
00093 EC_SyncMan (
00094 COMMAND_PHY_ADDR,
00095 command_size_,
00096 EC_BUFFERED,
00097 EC_WRITTEN_FROM_MASTER,
00098
00099
00100 true,
00101 true,
00102 false,
00103 false,
00104 false,
00105 false,
00106 EC_FIRST_BUFFER,
00107 true);
00108
00109
00110
00111
00112
00113 (*pd)[1] =
00114 EC_SyncMan (
00115 STATUS_PHY_ADDR,
00116 status_size_,
00117 EC_BUFFERED,
00118 EC_READ_FROM_MASTER,
00119
00120
00121 true,
00122 false,
00123 false,
00124 false,
00125 false,
00126 false,
00127 EC_FIRST_BUFFER,
00128 true);
00129
00130
00131 sh->set_pd_config(pd);
00132
00133
00134 EtherCAT_MbxConfig *mbx = new EtherCAT_MbxConfig;
00135
00136
00137 mbx->SM0 =
00138 EC_SyncMan(
00139 MBX_COMMAND_PHY_ADDR,
00140 MBX_COMMAND_SIZE,
00141 EC_QUEUED,
00142 EC_WRITTEN_FROM_MASTER,
00143 true,
00144 false,
00145 false,
00146 false,
00147 false,
00148 false,
00149 EC_FIRST_BUFFER,
00150 true);
00151
00152
00153
00154 mbx->SM1 =
00155 EC_SyncMan(
00156 MBX_STATUS_PHY_ADDR,
00157 MBX_STATUS_SIZE,
00158 EC_QUEUED,
00159 EC_READ_FROM_MASTER,
00160 true,
00161 false,
00162 false,
00163 false,
00164 false,
00165 false,
00166 EC_FIRST_BUFFER,
00167 true);
00168
00169
00170 sh->set_mbx_config(mbx);
00171
00172
00173
00174 }
00175
00176 int RIQHand::initialize(pr2_hardware_interface::HardwareInterface *, bool)
00177 {
00178 ROS_DEBUG("Device #%02d: RIQ Hand (%#08x)", sh_->get_ring_position(), sh_->get_product_code());
00179
00180 if (use_ros_)
00181 {
00182 ros::NodeHandle nh;
00183
00184
00185 commandSubscriber_ = nh.subscribe("riq_hand_command", 2, &RIQHand::commandCallback, this);
00186
00187
00188 publisher_.init(nh, "riq_hand_state", 1);
00189 }
00190
00191 return 0;
00192 }
00193
00194 void RIQHand::commandCallback(const riq_msgs::RIQHandCommand::ConstPtr& msg)
00195 {
00196 command_mutex_.lock();
00197 new_command_ = *msg;
00198 command_mutex_.unlock();
00199 }
00200
00201
00202 unsigned RIQHand::scaleAndSaturate255(double value)
00203 {
00204 value = double(value)*255.0;
00205 value = roundf(value);
00206 value = std::max(0.0, std::min( 255.0, value ) );
00207 return unsigned(value);
00208 }
00209
00210 void RIQHand::packCommand(unsigned char *buffer, bool halt, bool reset)
00211 {
00212
00213 if (command_mutex_.try_lock())
00214 {
00215 command_ = new_command_;
00216 command_mutex_.unlock();
00217 }
00218
00219
00220 if (reset)
00221 {
00222 needs_watchdog_reset_ = true;
00223 latched_fault_code_ = 0;
00224 if (needs_reset_)
00225 {
00226
00227 needs_reset_countdown_ = 10;
00228 needs_reset_ = false;
00229 }
00230 }
00231
00232 RIQHandCommandEcat *command = (RIQHandCommandEcat *)(buffer);
00233 RIQActionRequest &action_request(command->action_request_);
00234
00235 command->zero();
00236
00237 if (needs_reset_countdown_ > 0)
00238 {
00239 --needs_reset_countdown_;
00240 action_request.initialize_ = 0;
00241 }
00242 else
00243 {
00244 action_request.initialize_ = 1;
00245 }
00246
00247 switch(command_.action)
00248 {
00249 case riq_msgs::RIQHandCommand::OPEN :
00250 action_request.grip_ = RIQActionRequest::GRIP_OPEN;
00251 break;
00252 case riq_msgs::RIQHandCommand::CLOSE :
00253 action_request.grip_ = RIQActionRequest::GRIP_CLOSE;
00254 break;
00255 case riq_msgs::RIQHandCommand::STOP :
00256 action_request.grip_ = RIQActionRequest::GRIP_STOP;
00257 break;
00258 default:
00259 action_request.grip_ = RIQActionRequest::GRIP_STOP;
00260 }
00261
00262 switch(command_.mode)
00263 {
00264 case riq_msgs::RIQHandCommand::CYLINDRICAL:
00265 action_request.mode_ = RIQActionRequest::CYLINDRICAL_MODE;
00266 break;
00267 case riq_msgs::RIQHandCommand::PINCH:
00268 action_request.mode_ = RIQActionRequest::PINCH_MODE;
00269 break;
00270 case riq_msgs::RIQHandCommand::SPHERIOD:
00271 action_request.mode_ = RIQActionRequest::SPHERIOD_MODE;
00272 break;
00273 case riq_msgs::RIQHandCommand::SCISSORS:
00274 action_request.mode_ = RIQActionRequest::SCISSORS_MODE;
00275 break;
00276 }
00277
00278 command->force_ = scaleAndSaturate255(command_.force);
00279 command->velocity_ = scaleAndSaturate255(command_.velocity);
00280
00281 if (halt)
00282 {
00283 action_request.grip_ = RIQActionRequest::GRIP_STOP;
00284 }
00285 halted_ = halt;
00286
00287 command->safety_shutdown_.timeout_ = RIQSafetyShutdown::SHUTDOWN_TIMEOUT_10240ms;
00288 }
00289
00290
00291 bool RIQHand::unpackState(unsigned char *this_buffer, unsigned char *prev_buffer)
00292 {
00293
00294 const RIQHandStateEcat *state = (const RIQHandStateEcat *)(this_buffer + command_size_);
00295 const RIQHandStateEcat *prev_state = (const RIQHandStateEcat *)(prev_buffer + command_size_);
00296 const RIQGripperStatus &gripper_status(state->gripper_status_);
00297 const RIQObjectStatus &object_status(state->object_status_);
00298
00299 if (++state_cycle_count_ >= STATE_PUBLISH_PERIOD)
00300 {
00301 state_cycle_count_ = 0;
00302 should_publish_ = true;
00303 }
00304
00305 if (should_publish_ && use_ros_ && publisher_.trylock())
00306 {
00307 should_publish_ = false;
00308
00309 riq_msgs::RIQHandState &msg(publisher_.msg_);
00310 riq_msgs::RIQActuatorState &thumb(msg.thumb);
00311 riq_msgs::RIQActuatorState &right(msg.right_finger);
00312 riq_msgs::RIQActuatorState &left(msg.left_finger);
00313 riq_msgs::RIQActuatorState &scissors(msg.scissors);
00314
00315 msg.operational =
00316 (gripper_status.initialization_ == 1) &&
00317 (state->fault_status_ != RIQHandStateEcat::NO_FAULT) &&
00318 !halted_;
00319
00320
00321 msg.status = gripper_status.status_;
00322 msg.mode = gripper_status.mode_;
00323 msg.grip = gripper_status.grip_;
00324 msg.object = object_status.detected_;
00325
00326 thumb.object_detected = object_status.thumb_detected_;
00327 right.object_detected = object_status.right_finger_detected_;
00328 left.object_detected = object_status.left_finger_detected_;
00329 scissors.object_detected = object_status.scissors_detected_;
00330
00331 thumb.position = RIQHandStateEcat::convertPosition(state->thumb_position_);
00332 right.position = RIQHandStateEcat::convertPosition(state->right_finger_position_);
00333 left.position = RIQHandStateEcat::convertPosition(state->left_finger_position_);
00334 scissors.position = RIQHandStateEcat::convertPosition(state->scissors_position_);
00335
00336 thumb.current = RIQHandStateEcat::convertCurrent(state->thumb_current_);
00337 right.current = RIQHandStateEcat::convertCurrent(state->right_finger_current_);
00338 left.current = RIQHandStateEcat::convertCurrent(state->left_finger_current_);
00339 scissors.current = RIQHandStateEcat::convertCurrent(state->scissors_current_);
00340
00341 publisher_.unlockAndPublish();
00342 }
00343
00344 bool rv = true;
00345
00346 if (needs_watchdog_reset_)
00347 {
00348 after_watchdog_reset_countdown_ = 100;
00349 }
00350 else if (after_watchdog_reset_countdown_ > 0)
00351 {
00352 --after_watchdog_reset_countdown_;
00353 if ((prev_state->fault_status_ == RIQHandStateEcat::FAULT_COMMUNICATION_TIMEOUT) &&
00354 (state->fault_status_ == RIQHandStateEcat::NO_FAULT))
00355 {
00356 ROS_INFO("Communication fault cleared at %d", after_watchdog_reset_countdown_);
00357 }
00358 }
00359
00360 if (needs_reset_countdown_ > 0)
00361 {
00362 after_reset_countdown_ = 100;
00363 }
00364 else if (after_reset_countdown_ > 0)
00365 {
00366 --after_reset_countdown_;
00367 bool was_major_fault =
00368 (prev_state->fault_status_ == RIQHandStateEcat::FAULT_MAJOR_SCISSORS_DISPLACEMENT) ||
00369 (prev_state->fault_status_ == RIQHandStateEcat::FAULT_MAJOR_SCISSORS_DISPLACEMENT);
00370 if (was_major_fault && (state->fault_status_ == RIQHandStateEcat::NO_FAULT))
00371 {
00372 ROS_INFO("Major fault cleared at %d", after_reset_countdown_);
00373 }
00374 }
00375
00376
00377 if (!halted_ && (state->fault_status_ != RIQHandStateEcat::NO_FAULT))
00378 {
00379 switch (state->fault_status_)
00380 {
00381 case RIQHandStateEcat::FAULT_COMMUNICATION_TIMEOUT:
00382
00383 if (after_watchdog_reset_countdown_ == 0)
00384 {
00385 rv = false;
00386 latched_fault_code_ = state->fault_status_;
00387 ROS_ERROR("Watchdog");
00388 }
00389 break;
00390 case RIQHandStateEcat::FAULT_INSUFFICIENT_SUPPLY_VOLTAGE:
00391 rv = false;
00392 latched_fault_code_ = state->fault_status_;
00393 break;
00394 case RIQHandStateEcat::FAULT_MAJOR_SCISSORS_DISPLACEMENT:
00395 case RIQHandStateEcat::FAULT_MAJOR_FINGER_DISPLACEMENT:
00396
00397 if (after_reset_countdown_ == 0)
00398 {
00399 needs_reset_ = true;
00400 rv = false;
00401 latched_fault_code_ = state->fault_status_;
00402 }
00403 break;
00404 default:
00405
00406 break;
00407 }
00408 }
00409
00410 return rv;
00411 }
00412
00413
00414
00415 void RIQHand::disableWatchdog(EtherCAT_SlaveHandler *sh)
00416 {
00417
00418
00419 EthercatDirectCom com(EtherCAT_DataLinkLayer::instance());
00420 static const unsigned WATCHDOG_TIME_PDI_ADDR = 0x410;
00421 static const unsigned WATCHDOG_TIME_PROCESS_DATA_ADDR = 0x420;
00422 uint16_t timeout = 0;
00423 if (writeData(&com, sh, WATCHDOG_TIME_PDI_ADDR, &timeout, 2, FIXED_ADDR) != 0)
00424 {
00425 ROS_ERROR("Error disabling PDI watchdog\n");
00426 }
00427 timeout = 0;
00428 if (writeData(&com, sh, WATCHDOG_TIME_PROCESS_DATA_ADDR, &timeout, 2, FIXED_ADDR) != 0)
00429 {
00430 ROS_ERROR("Error disabling process data watchdog\n");
00431 }
00432 }
00433
00434
00435 void RIQHand::collectDiagnostics(EthercatCom *com)
00436 {
00437 EthercatDevice::collectDiagnostics(com);
00438
00439 ECatALStatusAll al_status;
00440 bool al_status_good = al_status.readData(com,sh_);
00441
00442 { boost::unique_lock<boost::mutex> lock(diagnostics_mutex_);
00443 collect_diagnostics_.al_status_good_ = al_status_good;
00444 collect_diagnostics_.al_status_ = al_status;
00445 }
00446
00447
00448
00449
00450
00451
00452 if (needs_watchdog_reset_)
00453 {
00454 if (!al_status_good)
00455 {
00456
00457
00458
00459 }
00460 else if (al_status.status_code_.error_code_ == ECatALStatusCode::SYNC_MANAGER_WATCHDOG)
00461 {
00462
00463 ECatALControl al_control;
00464 al_control.raw_ = 0;
00465 al_control.ack_error_ = 1;
00466 al_control.state_ = ECatStates::OP;
00467 if (al_control.writeData(com, sh_))
00468 {
00469
00470
00471 needs_watchdog_reset_ = false;
00472 }
00473 else
00474 {
00475
00476 }
00477 }
00478 else
00479 {
00480
00481
00482 needs_watchdog_reset_ = false;
00483 }
00484 }
00485 }
00486
00487
00488 void RIQHand::diagnostics(diagnostic_updater::DiagnosticStatusWrapper &d, unsigned char *buffer)
00489 {
00490 const RIQHandStateEcat *status = (const RIQHandStateEcat *)(buffer + command_size_);
00491 const RIQHandCommandEcat *command = (const RIQHandCommandEcat *)(buffer);
00492
00493
00494 if (diagnostics_mutex_.try_lock())
00495 {
00496 publish_diagnostics_ = collect_diagnostics_;
00497 diagnostics_mutex_.unlock();
00498 }
00499
00500 stringstream str;
00501 str << "EtherCAT Device #" << setw(2) << setfill('0') << sh_->get_ring_position() << " (RIQHand)";
00502 d.name = str.str();
00503 d.summary(d.OK, "OK");
00504 char serial[32];
00505 snprintf(serial, sizeof(serial), "%05d-%05d", sh_->get_product_code(), sh_->get_serial());
00506 d.hardware_id = serial;
00507
00508 d.clear();
00509 d.addf("Product code", "RIQ Hand (%d), Revision %d",
00510 sh_->get_product_code(), sh_->get_revision());
00511 d.addf("Serial Number", "%s", serial);
00512
00513 const RIQGripperStatus &gripper_status(status->gripper_status_);
00514 d.addf("Initialization", "%s (%d)", (gripper_status.initialization_ ? "Initialized" : "Reset"),
00515 int(gripper_status.initialization_) );
00516 d.addf("Gripper Mode", "%s (%d)", gripper_status.modeString(), gripper_status.mode_);
00517 d.addf("Gripper Status", "%s (%d)", gripper_status.statusString(), gripper_status.status_);
00518 bool in_scissors_mode = gripper_status.inScissorsMode();
00519
00520 const RIQObjectStatus &object_status(status->object_status_);
00521 d.addf("Object Detected", "%s (%d)",
00522 object_status.detectedString(in_scissors_mode),
00523 object_status.detected_);
00524
00525 d.addf("Fault", "%s (%d)", status->faultString(), int(status->fault_status_));
00526
00527 if (latched_fault_code_ != 0)
00528 {
00529
00530
00531 d.mergeSummary(d.ERROR, RIQHandStateEcat::faultString(latched_fault_code_));
00532 }
00533 else if (status->fault_status_ != status->NO_FAULT)
00534 {
00535
00536 d.mergeSummary(d.WARN, status->faultString());
00537 }
00538
00539 d.addf("Thumb position", "%f (%u)",
00540 status->convertPosition(status->thumb_position_),
00541 unsigned(status->thumb_position_));
00542 d.addf("Thumb position", "%fmA (%u)",
00543 1000.0 * status->convertCurrent(status->thumb_current_),
00544 unsigned(status->thumb_current_));
00545
00546 d.addf("Right finger position", "%f (%u)",
00547 status->convertPosition(status->right_finger_position_),
00548 unsigned(status->right_finger_position_));
00549 d.addf("Right finger current", "%fmA (%u)",
00550 1000.0 * status->convertCurrent(status->right_finger_current_),
00551 unsigned(status->right_finger_current_));
00552
00553 d.addf("Left finger position", "%f (%u)",
00554 status->convertPosition(status->left_finger_position_),
00555 unsigned(status->left_finger_position_));
00556 d.addf("Left finger current", "%fmA (%u)",
00557 1000.0 * status->convertCurrent(status->left_finger_current_),
00558 unsigned(status->left_finger_current_));
00559
00560 d.addf("Scissors position", "%f (%u)",
00561 status->convertPosition(status->scissors_position_),
00562 unsigned(status->scissors_position_));
00563 d.addf("Scissors current", "%fmA (%u)",
00564 1000.0 * status->convertCurrent(status->scissors_current_),
00565 unsigned(status->scissors_current_));
00566
00567
00568 const RIQActionRequest &action_request(command->action_request_);
00569
00570 d.addf("Initialization request", "%s (%d)",
00571 (action_request.initialize_ ? "Initialize" : "Reset"),
00572 unsigned(action_request.initialize_));
00573 d.addf("Mode request", "%s (%d)", action_request.modeString(),
00574 unsigned(action_request.mode_));
00575 d.addf("Grip request", "%s (%d)", action_request.gripString(),
00576 unsigned(action_request.grip_));
00577 d.addf("Force", "%f (%d)", (double(command->force_)/255.0),
00578 unsigned(command->force_));
00579 d.addf("Velocity", "%f (%d)", (double(command->velocity_)/255.0),
00580 unsigned(command->velocity_));
00581
00582
00583 if (publish_diagnostics_.al_status_good_)
00584 {
00585 const ECatALStatusAll &al_status(publish_diagnostics_.al_status_);
00586 d.addf("AL Status", "%s : %s",
00587 (al_status.status_.error_?"Error":"Good"),
00588 al_status.status_code_.errorCodeString());
00589 d.addf("AL State", "%s (%d)",
00590 al_status.status_.stateString(),
00591 al_status.status_.state_);
00592 }
00593 else
00594 {
00595 d.addf("AL Status", "INVALID");
00596 }
00597
00598
00599
00600 EthercatDevice::ethercatDiagnostics(d, 1);
00601 }
00602
00603
00604 };