Skip to content

Commit b176fe2

Browse files
committed
stuck joint recovery
1 parent 31b923d commit b176fe2

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

mep3_hardware/include/mep3_hardware/dynamixel_hardware_interface/dynamixel_hardware.hpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include <map>
2626
#include <vector>
2727
#include <deque>
28+
#include <optional>
29+
#include <chrono>
2830

2931
#include "mep3_hardware/dynamixel_hardware_interface/visibility_control.hpp"
3032
#include "rclcpp/macros.hpp"
@@ -34,7 +36,7 @@ using hardware_interface::return_type;
3436

3537
namespace dynamixel_hardware
3638
{
37-
struct JointValue
39+
struct JointState
3840
{
3941
double position{0.0};
4042
double velocity{0.0};
@@ -43,12 +45,21 @@ struct JointValue
4345
double temperature{0.0};
4446
bool overloaded;
4547
std::deque<double> previous_efforts_{};
48+
std::optional<std::chrono::time_point<std::chrono::system_clock>> last_max_effort_{};
49+
};
50+
51+
struct JointCommand
52+
{
53+
double position{0.0};
54+
double velocity{0.0};
55+
double effort{0.0};
56+
double initial_position_{0.0};
4657
};
4758

4859
struct Joint
4960
{
50-
JointValue state{};
51-
JointValue command{};
61+
JointState state{};
62+
JointCommand command{};
5263
};
5364

5465
enum class ControlMode {
@@ -111,7 +122,8 @@ class DynamixelHardware
111122
bool use_dummy_{false};
112123
double offset_{0};
113124
bool keep_read_write_thread_{true};
114-
unsigned int effort_filter_ {0};
125+
unsigned int effort_average_ {0};
126+
std::chrono::milliseconds recovery_timeout_{250};
115127
};
116128
} // namespace dynamixel_hardware
117129

mep3_hardware/src/dynamixel_hardware_interface/dynamixel_hardware.cpp

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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 ]",

mep3_hardware/test/dynamixel/description.urdf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
<param name="baud_rate">115200</param>
99
<param name="use_dummy">false</param>
1010
<param name="offset">0.0</param>
11-
<param name="effort_filter">2</param>
11+
<param name="effort_average">2</param>
12+
<param name="recovery_timeout">100</param>
1213
</hardware>
1314
<joint name="joint1">
1415
<param name="id">5</param>

0 commit comments

Comments
 (0)