@@ -57,6 +57,7 @@ void WaitUntilPortAvailable(DynamixelWorkbench *dxl_wb,
57
57
// reachable. Returns `false` if not all of them are reachable.
58
58
auto PingMotors (DynamixelWorkbench *dxl_wb,
59
59
const RobotProfile &profile,
60
+ bool log_errors_only = false ,
60
61
int num_trials = 3 ,
61
62
std::chrono::milliseconds sleep_between_trials =
62
63
std::chrono::milliseconds (200 )) -> bool {
@@ -69,6 +70,9 @@ auto PingMotors(DynamixelWorkbench *dxl_wb,
69
70
if (success.count (motor.id ) > 0 ) continue ;
70
71
if (dxl_wb->ping (motor.id , &log)) {
71
72
success.emplace (motor.id );
73
+ if (log_errors_only) {
74
+ continue ;
75
+ }
72
76
std::string model_name = dxl_wb->getModelName (motor.id );
73
77
spdlog::info (" Found DYNAMIXEL Motor ID: {}, Model: {}, Name: {}" ,
74
78
motor.id ,
@@ -88,10 +92,12 @@ auto PingMotors(DynamixelWorkbench *dxl_wb,
88
92
if (success.size () == profile.motors .size ()) {
89
93
return true ;
90
94
} 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
+ }
95
101
std::this_thread::sleep_for (sleep_between_trials);
96
102
}
97
103
}
@@ -340,23 +346,36 @@ WxArmorDriver::WxArmorDriver(const std::string &usb_port,
340
346
341
347
WxArmorDriver::~WxArmorDriver () {}
342
348
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
+
343
355
std::optional<SensorData> WxArmorDriver::Read () {
356
+ static uint64_t error_count = 0 ;
344
357
std::vector<int32_t > buffer (profile_.joint_ids .size ());
345
358
const uint8_t num_joints = static_cast <uint8_t >(buffer.size ());
346
359
347
360
SensorData result = SensorData{
348
361
.pos = std::vector<float >(num_joints),
349
362
.vel = std::vector<float >(num_joints),
350
363
.crt = std::vector<float >(num_joints),
364
+ .err = std::vector<uint32_t >(num_joints),
351
365
};
352
366
353
367
std::unique_lock<std::mutex> handler_lock{io_mutex_};
354
368
const char *log;
355
369
356
370
if (!dxl_wb_.syncRead (
357
371
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;
359
376
return std::nullopt ;
377
+ } else {
378
+ error_count = 0 ;
360
379
}
361
380
362
381
// We use the time here as the timestamp for the latest reading. This is,
@@ -437,6 +456,19 @@ std::vector<float> WxArmorDriver::GetSafetyVelocityLimits() {
437
456
return safety_velocity_limits;
438
457
}
439
458
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
+
440
472
void WxArmorDriver::SetPosition (const std::vector<float > &position,
441
473
float moving_time,
442
474
float acc_time) {
@@ -558,6 +590,7 @@ void WxArmorDriver::InitReadHandler() {
558
590
read_position_address_ = AddItemToRead (" Present_Position" );
559
591
read_velocity_address_ = AddItemToRead (" Present_Velocity" );
560
592
read_current_address_ = AddItemToRead (" Present_Current" );
593
+ read_error_address_ = AddItemToRead (" Hardware_Error_Status" );
561
594
562
595
read_handler_index_ = dxl_wb_.getTheNumberOfSyncReadHandler ();
563
596
if (!dxl_wb_.addSyncReadHandler (read_start_, read_end_ - read_start_)) {
0 commit comments