@@ -60,26 +60,31 @@ namespace dynamixel_hardware
6060 joint_ids_.resize (info_.joints .size (), 0 );
6161
6262 try {
63- effort_filter_ = std::stoi (info_.hardware_parameters .at (" effort_filter " ));
64- RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " effort_filter : %d" , effort_filter_ );
63+ effort_average_ = std::stoi (info_.hardware_parameters .at (" effort_average " ));
64+ RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " effort_average : %d samples " , effort_average_ );
6565 } catch (const std::out_of_range& e) {
66- RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " effort_filter : %d [default]" , effort_filter_ );
66+ RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " effort_average : %d samples [default]" , effort_average_ );
6767 }
6868
6969 for (uint i = 0 ; i < info_.joints .size (); i++)
7070 {
7171 joint_ids_[i] = std::stoi (info_.joints [i].parameters .at (" id" ));
72+ // Command
73+ joints_[i].command .position = std::numeric_limits<double >::quiet_NaN ();
74+ joints_[i].command .velocity = std::numeric_limits<double >::quiet_NaN ();
75+ joints_[i].command .effort = std::numeric_limits<double >::quiet_NaN ();
76+ // State
7277 joints_[i].state .position = std::numeric_limits<double >::quiet_NaN ();
7378 joints_[i].state .velocity = std::numeric_limits<double >::quiet_NaN ();
7479 joints_[i].state .effort = std::numeric_limits<double >::quiet_NaN ();
7580 joints_[i].state .voltage = std::numeric_limits<double >::quiet_NaN ();
7681 joints_[i].state .temperature = std::numeric_limits<double >::quiet_NaN ();
82+ // Bookkeeping
83+ joints_[i].command .initial_position_ = std::numeric_limits<double >::quiet_NaN ();
7784 joints_[i].state .overloaded = false ;
7885 joints_[i].state .previous_efforts_ = std::deque<double >();
79- joints_[i].state .previous_efforts_ .resize (effort_filter_);
80- joints_[i].command .position = std::numeric_limits<double >::quiet_NaN ();
81- joints_[i].command .velocity = std::numeric_limits<double >::quiet_NaN ();
82- joints_[i].command .effort = std::numeric_limits<double >::quiet_NaN ();
86+ joints_[i].state .previous_efforts_ .resize (effort_average_);
87+ joints_[i].state .last_max_effort_ .reset ();
8388 RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " joint_id %d: %d" , i, joint_ids_[i]);
8489 }
8590
@@ -101,6 +106,13 @@ namespace dynamixel_hardware
101106 RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " usb_port: %s" , usb_port.c_str ());
102107 RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " baud_rate: %d" , baud_rate);
103108
109+ try {
110+ recovery_timeout_ = std::chrono::milliseconds (stoi (info_.hardware_parameters .at (" recovery_timeout" )));
111+ RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " recovery_timeout: %ld ms" , recovery_timeout_.count ());
112+ } catch (const std::out_of_range& e) {
113+ RCLCPP_INFO (rclcpp::get_logger (kDynamixelHardware ), " recovery_timeout: %ld ms [default]" , recovery_timeout_.count ());
114+ }
115+
104116 if (!dynamixel_workbench_.init (usb_port.c_str (), baud_rate, &log))
105117 {
106118 RCLCPP_FATAL (rclcpp::get_logger (kDynamixelHardware ), " %s" , log);
@@ -271,6 +283,11 @@ namespace dynamixel_hardware
271283 }
272284
273285 read_from_hardware ();
286+ for (uint i = 0 ; i < joints_.size (); i++)
287+ {
288+ // Save initial position for recovery
289+ joints_[i].command .initial_position_ = joints_[i].state .position ;
290+ }
274291 reset_command ();
275292 write_to_hardware ();
276293
@@ -450,6 +467,7 @@ namespace dynamixel_hardware
450467
451468 int16_t load = (present_data[4 ] | ((0x3 & present_data[5 ]) << 8 ));
452469 bool overload = (unsigned ) load > TORQUE_LOAD_MAX;
470+ bool max_torque = (unsigned ) load == TORQUE_LOAD_MAX;
453471 // data[5] third bit determines effort sign
454472 if (present_data[5 ] & 0x4 )
455473 load = -load;
@@ -465,7 +483,7 @@ namespace dynamixel_hardware
465483
466484 if (!overload) {
467485 double effort = dynamixel_workbench_.convertValue2Current (load);
468- if (joints_[i].state .previous_efforts_ .size () >= effort_filter_ ) {
486+ if (joints_[i].state .previous_efforts_ .size () >= effort_average_ ) {
469487 joints_[i].state .previous_efforts_ .pop_front ();
470488 }
471489 joints_[i].state .previous_efforts_ .push_back (effort);
@@ -478,6 +496,27 @@ namespace dynamixel_hardware
478496 joints_[i].state .effort = std::numeric_limits<double >::infinity ();
479497 }
480498
499+ if (max_torque) {
500+ if (joints_[i].state .last_max_effort_ .has_value ()) {
501+ const auto time_delta = std::chrono::system_clock::now () - joints_[i].state .last_max_effort_ .value ();
502+ const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(time_delta);
503+ if (duration > recovery_timeout_) {
504+ RCLCPP_WARN (
505+ rclcpp::get_logger (kDynamixelHardware ),
506+ " Recovering stuck joint %s to initial position %.3lf" ,
507+ info_.joints [i].name .c_str (),
508+ joints_[i].command .initial_position_
509+ );
510+ joints_[i].command .position = joints_[i].command .initial_position_ ;
511+ joints_[i].state .effort = std::numeric_limits<double >::infinity ();
512+ }
513+ } else {
514+ joints_[i].state .last_max_effort_ = std::chrono::system_clock::now ();
515+ }
516+ } else {
517+ joints_[i].state .last_max_effort_ .reset ();
518+ }
519+
481520 // RCLCPP_WARN(
482521 // rclcpp::get_logger(kDynamixelHardware),
483522 // "DYNAMIXEL [ position: %6.2f rad | speed: %6.2f rad/s | load: %6.2f mA | voltage: %6.2f V | temperature: %6.2f C ]",
0 commit comments