Skip to content

Commit dfe1dbc

Browse files
authored
Merge pull request #24 from HorizonRoboticsInternal/le/error_restart
Wx handle error restart
2 parents 91625f6 + 9b68271 commit dfe1dbc

File tree

4 files changed

+231
-67
lines changed

4 files changed

+231
-67
lines changed

wx_armor/wx_armor/wx_armor_driver.cc

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void WaitUntilPortAvailable(DynamixelWorkbench *dxl_wb,
5757
// reachable. Returns `false` if not all of them are reachable.
5858
auto PingMotors(DynamixelWorkbench *dxl_wb,
5959
const RobotProfile &profile,
60+
bool log_errors_only = false,
6061
int num_trials = 3,
6162
std::chrono::milliseconds sleep_between_trials =
6263
std::chrono::milliseconds(200)) -> bool {
@@ -69,6 +70,9 @@ auto PingMotors(DynamixelWorkbench *dxl_wb,
6970
if (success.count(motor.id) > 0) continue;
7071
if (dxl_wb->ping(motor.id, &log)) {
7172
success.emplace(motor.id);
73+
if (log_errors_only) {
74+
continue;
75+
}
7276
std::string model_name = dxl_wb->getModelName(motor.id);
7377
spdlog::info("Found DYNAMIXEL Motor ID: {}, Model: {}, Name: {}",
7478
motor.id,
@@ -88,10 +92,12 @@ auto PingMotors(DynamixelWorkbench *dxl_wb,
8892
if (success.size() == profile.motors.size()) {
8993
return true;
9094
} else if (i + 1 < num_trials) {
91-
spdlog::warn("Found only {} / {} motors. Will wait for {} ms and retry.",
92-
success.size(),
93-
profile.motors.size(),
94-
sleep_between_trials.count());
95+
if (!log_errors_only) {
96+
spdlog::warn("Found only {} / {} motors. Will wait for {} ms and retry.",
97+
success.size(),
98+
profile.motors.size(),
99+
sleep_between_trials.count());
100+
}
95101
std::this_thread::sleep_for(sleep_between_trials);
96102
}
97103
}
@@ -340,23 +346,36 @@ WxArmorDriver::WxArmorDriver(const std::string &usb_port,
340346

341347
WxArmorDriver::~WxArmorDriver() {}
342348

349+
bool WxArmorDriver::MotorHealthCheck() {
350+
std::unique_lock<std::mutex> handler_lock{io_mutex_};
351+
return PingMotors(&dxl_wb_, profile_, /* log_errors_only */ true,
352+
/* num_trials */ 1);
353+
}
354+
343355
std::optional<SensorData> WxArmorDriver::Read() {
356+
static uint64_t error_count = 0;
344357
std::vector<int32_t> buffer(profile_.joint_ids.size());
345358
const uint8_t num_joints = static_cast<uint8_t>(buffer.size());
346359

347360
SensorData result = SensorData{
348361
.pos = std::vector<float>(num_joints),
349362
.vel = std::vector<float>(num_joints),
350363
.crt = std::vector<float>(num_joints),
364+
.err = std::vector<uint32_t>(num_joints),
351365
};
352366

353367
std::unique_lock<std::mutex> handler_lock{io_mutex_};
354368
const char *log;
355369

356370
if (!dxl_wb_.syncRead(
357371
read_handler_index_, profile_.joint_ids.data(), num_joints, &log)) {
358-
spdlog::warn("Failed to syncRead: {}", log);
372+
if (error_count % 1000 == 0) {
373+
spdlog::warn("Failed to syncRead: {}", log);
374+
}
375+
++error_count;
359376
return std::nullopt;
377+
} else {
378+
error_count = 0;
360379
}
361380

362381
// We use the time here as the timestamp for the latest reading. This is,
@@ -437,6 +456,19 @@ std::vector<float> WxArmorDriver::GetSafetyVelocityLimits() {
437456
return safety_velocity_limits;
438457
}
439458

459+
std::vector<float> WxArmorDriver::GetSafetyCurrentLimits() {
460+
std::vector<float> safety_current_limits;
461+
462+
for (const auto &motor : profile_.motors) {
463+
float limit = motor.current_limit;
464+
if (limit < 1) {
465+
limit = 1200;
466+
}
467+
safety_current_limits.push_back(limit);
468+
}
469+
return safety_current_limits;
470+
}
471+
440472
void WxArmorDriver::SetPosition(const std::vector<float> &position,
441473
float moving_time,
442474
float acc_time) {
@@ -558,6 +590,7 @@ void WxArmorDriver::InitReadHandler() {
558590
read_position_address_ = AddItemToRead("Present_Position");
559591
read_velocity_address_ = AddItemToRead("Present_Velocity");
560592
read_current_address_ = AddItemToRead("Present_Current");
593+
read_error_address_ = AddItemToRead("Hardware_Error_Status");
561594

562595
read_handler_index_ = dxl_wb_.getTheNumberOfSyncReadHandler();
563596
if (!dxl_wb_.addSyncReadHandler(read_start_, read_end_ - read_start_)) {

wx_armor/wx_armor/wx_armor_driver.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ struct SensorData {
6767
std::vector<float> pos{}; // joint position
6868
std::vector<float> vel{}; // joint velocity
6969
std::vector<float> crt{}; // motor electric current of this joint
70+
std::vector<uint32_t> err{}; // per joint error codes
7071

7172
// ┌──────────────────┐
7273
// │ Metadata │
@@ -77,7 +78,7 @@ struct SensorData {
7778
// error, it is only expected to be used as a reference.
7879
int64_t timestamp = 0;
7980

80-
NLOHMANN_DEFINE_TYPE_INTRUSIVE(SensorData, pos, vel, crt, timestamp);
81+
NLOHMANN_DEFINE_TYPE_INTRUSIVE(SensorData, pos, vel, crt, err, timestamp);
8182
};
8283

8384
/**
@@ -154,6 +155,13 @@ class WxArmorDriver {
154155
*/
155156
std::optional<SensorData> Read();
156157

158+
/**
159+
* @brief Check that all motors are health.
160+
*
161+
* @return Returns true if all motors are reachable and false otherwise.
162+
*/
163+
bool MotorHealthCheck();
164+
157165
/**
158166
* @brief Reads the safety velocity limits from RobotProfile and returns it.
159167
*
@@ -162,6 +170,13 @@ class WxArmorDriver {
162170
*/
163171
std::vector<float> GetSafetyVelocityLimits();
164172

173+
/**
174+
* @brief Reads the safety current limits from RobotProfile and returns it.
175+
*
176+
* @return An array containing the safety current limits for each motor [mA].
177+
*/
178+
std::vector<float> GetSafetyCurrentLimits();
179+
165180
/**
166181
* @brief Sets the position of the robot's joints, with a desired moving and
167182
* acceleration time.
@@ -252,6 +267,11 @@ class WxArmorDriver {
252267
*/
253268
void ResetSafetyViolationMode();
254269

270+
/**
271+
* @brief Returns the profile of the robot.
272+
*/
273+
const RobotProfile &Profile() const { return profile_; }
274+
255275
private:
256276
ControlItem AddItemToRead(const std::string &name);
257277

@@ -286,6 +306,7 @@ class WxArmorDriver {
286306
ControlItem read_position_address_;
287307
ControlItem read_velocity_address_;
288308
ControlItem read_current_address_;
309+
ControlItem read_error_address_;
289310

290311
// Union address interval of the above 3. Note that `read_end_` address is
291312
// not inclusive (open interval). We need this so that we can issue command

0 commit comments

Comments
 (0)