Skip to content

Commit 76076c3

Browse files
committed
refactor: enhance Dynamixel hardware interface with improved mapping and read logic
- Added new mapping functions for command and state interfaces using unordered maps. - Refactored read logic to support direct and indirect reading, improving error handling and data processing. - Updated initialization and synchronization methods for better clarity and efficiency. - Removed redundant definitions and streamlined state handling in the interface.
1 parent 7bd884c commit 76076c3

File tree

5 files changed

+309
-142
lines changed

5 files changed

+309
-142
lines changed

include/dynamixel_hardware_interface/dynamixel/dynamixel.hpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ class Dynamixel
126126
std::vector<RWItemList> read_data_list_;
127127

128128
// sync read
129-
dynamixel::GroupFastSyncRead * group_sync_read_;
129+
dynamixel::GroupSyncRead * group_sync_read_;
130130
// indirect inform for sync read
131131
std::map<uint8_t /*id*/, IndirectInfo> indirect_info_read_;
132132

133133
// bulk read
134-
dynamixel::GroupFastBulkRead * group_bulk_read_;
134+
dynamixel::GroupBulkRead * group_bulk_read_;
135135

136136
// write item (sync or bulk) variable
137137
bool write_type_;
@@ -206,8 +206,12 @@ class Dynamixel
206206
// BulkRead
207207
DxlError SetBulkReadItemAndHandler();
208208
DxlError SetBulkReadHandler(std::vector<uint8_t> id_arr);
209+
DxlError AddDirectRead(uint8_t id, std::string item_name, uint16_t item_addr, uint8_t item_size);
209210
DxlError GetDxlValueFromBulkRead(double period_ms);
210211

212+
// Check Indirect Read
213+
DxlError CheckIndirectReadAvailable(uint8_t id);
214+
211215
// Read - Indirect Address
212216
void ResetIndirectRead(std::vector<uint8_t> id_arr);
213217
DxlError AddIndirectRead(
@@ -225,10 +229,17 @@ class Dynamixel
225229
const std::vector<std::shared_ptr<double>> & data_ptrs,
226230
std::function<uint32_t(uint8_t, uint16_t, uint8_t)> get_data_func);
227231

232+
DxlError ProcessDirectReadData(
233+
uint8_t id,
234+
const std::vector<uint16_t> & item_addrs,
235+
const std::vector<uint8_t> & item_sizes,
236+
const std::vector<std::shared_ptr<double>> & data_ptrs,
237+
std::function<uint32_t(uint8_t, uint16_t, uint8_t)> get_data_func);
238+
228239
// Read - Communication
229240
DxlError ProcessReadCommunication(
230-
dynamixel::GroupFastSyncRead * group_sync_read,
231-
dynamixel::GroupFastBulkRead * group_bulk_read,
241+
dynamixel::GroupSyncRead * group_sync_read,
242+
dynamixel::GroupBulkRead * group_bulk_read,
232243
dynamixel::PortHandler * port_handler,
233244
double period_ms,
234245
bool is_sync);

include/dynamixel_hardware_interface/dynamixel_hardware_interface.hpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <vector>
2323
#include <map>
2424
#include <unordered_map>
25+
#include <functional>
2526

2627
#include "rclcpp/rclcpp.hpp"
2728
#include "ament_index_cpp/get_package_share_directory.hpp"
@@ -44,9 +45,6 @@
4445

4546
#include "std_srvs/srv/set_bool.hpp"
4647

47-
#define PRESENT_POSITION_INDEX 0
48-
#define PRESENT_VELOCITY_INDEX 1
49-
#define PRESENT_EFFORT_INDEX 2
5048

5149
namespace dynamixel_hardware_interface
5250
{
@@ -356,18 +354,38 @@ class DynamixelHardware : public
356354
double revoluteToPrismatic(double revolute_value);
357355

358356
double prismaticToRevolute(double prismatic_value);
357+
358+
void MapInterfaces(
359+
size_t outer_size,
360+
size_t inner_size,
361+
std::vector<HandlerVarType> &outer_handlers,
362+
const std::vector<HandlerVarType> &inner_handlers,
363+
double **matrix,
364+
const std::unordered_map<std::string, std::vector<std::string>> &iface_map,
365+
const std::string &conversion_iface = "",
366+
const std::string &conversion_name = "",
367+
std::function<double(double)> conversion = nullptr);
359368
};
360369

361370
// Conversion maps between ROS2 and Dynamixel interface names
362-
inline const std::unordered_map<std::string, std::string> ros2_to_dxl_cmd_map = {
363-
{hardware_interface::HW_IF_POSITION, "Goal Position"},
364-
{hardware_interface::HW_IF_VELOCITY, "Goal Velocity"},
365-
{hardware_interface::HW_IF_EFFORT, "Goal Current"}
371+
inline const std::unordered_map<std::string, std::vector<std::string>> ros2_to_dxl_cmd_map = {
372+
{hardware_interface::HW_IF_POSITION, {"Goal Position"}},
373+
{hardware_interface::HW_IF_VELOCITY, {"Goal Velocity"}},
374+
{hardware_interface::HW_IF_EFFORT, {"Goal Current"}}
375+
};
376+
377+
// Mapping for Dynamixel command interface names to ROS2 state interface names
378+
inline const std::unordered_map<std::string, std::vector<std::string>> dxl_to_ros2_cmd_map = {
379+
{"Goal Position", {hardware_interface::HW_IF_POSITION}},
380+
{"Goal Velocity", {hardware_interface::HW_IF_VELOCITY}},
381+
{"Goal Current", {hardware_interface::HW_IF_EFFORT}}
366382
};
367-
inline const std::unordered_map<std::string, std::string> dxl_to_ros2_cmd_map = {
368-
{"Goal Position", hardware_interface::HW_IF_POSITION},
369-
{"Goal Velocity", hardware_interface::HW_IF_VELOCITY},
370-
{"Goal Current", hardware_interface::HW_IF_EFFORT}
383+
384+
// Mapping for ROS2 state interface names to Dynamixel state interface names
385+
inline const std::unordered_map<std::string, std::vector<std::string>> ros2_to_dxl_state_map = {
386+
{hardware_interface::HW_IF_POSITION, {"Present Position"}},
387+
{hardware_interface::HW_IF_VELOCITY, {"Present Velocity"}},
388+
{hardware_interface::HW_IF_EFFORT, {"Present Current", "Present Load"}}
371389
};
372390

373391
} // namespace dynamixel_hardware_interface

param/dxl_model/dynamixel.model

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ Number Name
4747
220 omy_hat.model
4848
230 omy_end.model
4949
536 sensorxel_joy.model
50+
600 sensorxel_joy.model

src/dynamixel/dynamixel.cpp

Lines changed: 138 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,10 @@ bool Dynamixel::checkReadType()
678678
uint16_t indirect_addr[2]; // [i-1], [i]
679679
uint8_t indirect_size[2]; // [i-1], [i]
680680

681+
if (CheckIndirectReadAvailable(read_data_list_.at(dxl_index - 1).id) != DxlError::OK) {
682+
return BULK;
683+
}
684+
681685
if (!dxl_info_.GetDxlControlItem(
682686
read_data_list_.at(dxl_index).id, "Indirect Data Read", indirect_addr[1],
683687
indirect_size[1]) ||
@@ -816,7 +820,7 @@ DxlError Dynamixel::SetSyncReadHandler(std::vector<uint8_t> id_arr)
816820
IN_ADDR, indirect_info_read_[id_arr.at(0)].size);
817821

818822
group_sync_read_ =
819-
new dynamixel::GroupFastSyncRead(
823+
new dynamixel::GroupSyncRead(
820824
port_handler_, packet_handler_,
821825
IN_ADDR, indirect_info_read_[id_arr.at(0)].size);
822826

@@ -857,15 +861,64 @@ DxlError Dynamixel::GetDxlValueFromSyncRead(double period_ms)
857861

858862
DxlError Dynamixel::SetBulkReadItemAndHandler()
859863
{
860-
std::vector<uint8_t> id_arr;
864+
group_bulk_read_ = new dynamixel::GroupBulkRead(port_handler_, packet_handler_);
865+
866+
std::vector<uint8_t> indirect_id_arr;
867+
std::vector<uint8_t> direct_id_arr;
868+
869+
std::vector<RWItemList> indirect_read_data_list;
870+
std::vector<RWItemList> direct_read_data_list;
871+
861872
for (auto it_read_data : read_data_list_) {
862-
id_arr.push_back(it_read_data.id);
873+
if (CheckIndirectReadAvailable(it_read_data.id) == DxlError::OK) {
874+
indirect_id_arr.push_back(it_read_data.id);
875+
indirect_read_data_list.push_back(it_read_data);
876+
} else {
877+
direct_id_arr.push_back(it_read_data.id);
878+
direct_read_data_list.push_back(it_read_data);
879+
}
863880
}
864881

865-
DynamixelDisable(id_arr);
866-
ResetIndirectRead(id_arr);
882+
for (auto it_read_data : direct_read_data_list) {
883+
if (it_read_data.item_addr.empty() || it_read_data.item_size.empty()) {
884+
continue;
885+
}
886+
// Calculate min address and max end address
887+
uint16_t min_addr = it_read_data.item_addr[0];
888+
uint16_t max_end_addr = it_read_data.item_addr[0] + it_read_data.item_size[0];
889+
for (size_t item_index = 1; item_index < it_read_data.item_addr.size(); ++item_index) {
890+
uint16_t addr = it_read_data.item_addr[item_index];
891+
uint16_t size = it_read_data.item_size[item_index];
892+
if (addr < min_addr) min_addr = addr;
893+
if (addr + size > max_end_addr) max_end_addr = addr + size;
894+
}
895+
uint8_t total_size = max_end_addr - min_addr;
896+
// Concatenate all item names with '+'
897+
std::string group_item_names;
898+
for (size_t i = 0; i < it_read_data.item_name.size(); ++i) {
899+
group_item_names += it_read_data.item_name[i];
900+
if (i + 1 < it_read_data.item_name.size()) group_item_names += " + ";
901+
}
902+
// Call AddDirectRead once per id
903+
if (AddDirectRead(
904+
it_read_data.id,
905+
group_item_names,
906+
min_addr,
907+
total_size) != DxlError::OK)
908+
{
909+
fprintf(stderr, "Cannot set the BulkRead handler.\n");
910+
return DxlError::BULK_READ_FAIL;
911+
}
912+
fprintf(
913+
stderr,
914+
"set bulk read (direct addr) : addr %d, size %d\n",
915+
min_addr, total_size);
916+
}
867917

868-
for (auto it_read_data : read_data_list_) {
918+
DynamixelDisable(indirect_id_arr);
919+
ResetIndirectRead(indirect_id_arr);
920+
921+
for (auto it_read_data : indirect_read_data_list) {
869922
for (size_t item_index = 0; item_index < it_read_data.item_name.size();
870923
item_index++)
871924
{
@@ -880,17 +933,22 @@ DxlError Dynamixel::SetBulkReadItemAndHandler()
880933
stderr, "[ID:%03d] Add Indirect Address Read Item : [%s]\n",
881934
it_read_data.id,
882935
it_read_data.item_name.at(item_index).c_str());
883-
} else {
936+
} else if(result == DxlError::SET_BULK_READ_FAIL) {
884937
fprintf(
885938
stderr, "[ID:%03d] Failed to Indirect Address Read Item : [%s], %d\n",
886939
it_read_data.id,
887940
it_read_data.item_name.at(item_index).c_str(),
888941
result);
942+
} else if(result == DxlError::CANNOT_FIND_CONTROL_ITEM) {
943+
fprintf(
944+
stderr, "[ID:%03d] 'Indirect Address Read' is not defined in control table, Cannot set Indirect Address Read for : [%s]\n",
945+
it_read_data.id,
946+
it_read_data.item_name.at(item_index).c_str());
889947
}
890948
}
891949
}
892-
893-
if (SetBulkReadHandler(id_arr) != DxlError::OK) {
950+
951+
if (SetBulkReadHandler(indirect_id_arr) != DxlError::OK) {
894952
fprintf(stderr, "Cannot set the BulkRead handler.\n");
895953
return DxlError::BULK_READ_FAIL;
896954
}
@@ -919,11 +977,9 @@ DxlError Dynamixel::SetBulkReadHandler(std::vector<uint8_t> id_arr)
919977
fprintf(
920978
stderr,
921979
"set bulk read (indirect addr) : addr %d, size %d\n",
922-
IN_ADDR, indirect_info_read_[id_arr.at(0)].size);
980+
IN_ADDR, indirect_info_read_[it_id].size);
923981
}
924982

925-
group_bulk_read_ = new dynamixel::GroupFastBulkRead(port_handler_, packet_handler_);
926-
927983
for (auto it_id : id_arr) {
928984
uint8_t ID = it_id;
929985
uint16_t ADDR = indirect_info_read_[ID].indirect_data_addr;
@@ -941,6 +997,17 @@ DxlError Dynamixel::SetBulkReadHandler(std::vector<uint8_t> id_arr)
941997
return DxlError::OK;
942998
}
943999

1000+
DxlError Dynamixel::AddDirectRead(uint8_t id, std::string item_name, uint16_t item_addr, uint8_t item_size)
1001+
{
1002+
if (group_bulk_read_->addParam(id, item_addr, item_size) == true) {
1003+
fprintf(stderr, "[ID:%03d] Add BulkRead item : [%s][%d][%d]\n", id, item_name.c_str(), item_addr, item_size);
1004+
} else {
1005+
fprintf(stderr, "[ID:%03d] Failed to BulkRead item : [%s][%d][%d]\n", id, item_name.c_str(), item_addr, item_size);
1006+
return DxlError::SET_BULK_READ_FAIL;
1007+
}
1008+
return DxlError::OK;
1009+
}
1010+
9441011
DxlError Dynamixel::GetDxlValueFromBulkRead(double period_ms)
9451012
{
9461013
DxlError comm_result = ProcessReadCommunication(
@@ -953,22 +1020,33 @@ DxlError Dynamixel::GetDxlValueFromBulkRead(double period_ms)
9531020
uint8_t id = it_read_data.id;
9541021
uint16_t indirect_addr = indirect_info_read_[id].indirect_data_addr;
9551022

956-
ProcessReadData(
957-
id,
958-
indirect_addr,
959-
indirect_info_read_[id].item_name,
960-
indirect_info_read_[id].item_size,
961-
it_read_data.item_data_ptr_vec,
962-
[this](uint8_t id, uint16_t addr, uint8_t size) {
963-
return group_bulk_read_->getData(id, addr, size);
964-
});
1023+
if (CheckIndirectReadAvailable(id) != DxlError::OK) {
1024+
ProcessDirectReadData(
1025+
id,
1026+
it_read_data.item_addr,
1027+
it_read_data.item_size,
1028+
it_read_data.item_data_ptr_vec,
1029+
[this](uint8_t id, uint16_t addr, uint8_t size) {
1030+
return group_bulk_read_->getData(id, addr, size);
1031+
});
1032+
} else {
1033+
ProcessReadData(
1034+
id,
1035+
indirect_addr,
1036+
indirect_info_read_[id].item_name,
1037+
indirect_info_read_[id].item_size,
1038+
it_read_data.item_data_ptr_vec,
1039+
[this](uint8_t id, uint16_t addr, uint8_t size) {
1040+
return group_bulk_read_->getData(id, addr, size);
1041+
});
1042+
}
9651043
}
9661044
return DxlError::OK;
9671045
}
9681046

9691047
DxlError Dynamixel::ProcessReadCommunication(
970-
dynamixel::GroupFastSyncRead * group_sync_read,
971-
dynamixel::GroupFastBulkRead * group_bulk_read,
1048+
dynamixel::GroupSyncRead * group_sync_read,
1049+
dynamixel::GroupBulkRead * group_bulk_read,
9721050
dynamixel::PortHandler * port_handler,
9731051
double period_ms,
9741052
bool is_sync)
@@ -1055,18 +1133,50 @@ DxlError Dynamixel::ProcessReadData(
10551133
return DxlError::OK;
10561134
}
10571135

1136+
DxlError Dynamixel::ProcessDirectReadData(
1137+
uint8_t id,
1138+
const std::vector<uint16_t> & item_addrs,
1139+
const std::vector<uint8_t> & item_sizes,
1140+
const std::vector<std::shared_ptr<double>> & data_ptrs,
1141+
std::function<uint32_t(uint8_t, uint16_t, uint8_t)> get_data_func)
1142+
{
1143+
for (size_t item_index = 0; item_index < item_addrs.size(); item_index++) {
1144+
uint16_t current_addr = item_addrs[item_index];
1145+
uint8_t size = item_sizes[item_index];
1146+
1147+
uint32_t dxl_getdata = get_data_func(id, current_addr, size);
1148+
1149+
*data_ptrs[item_index] = static_cast<double>(dxl_getdata);
1150+
}
1151+
return DxlError::OK;
1152+
}
10581153

10591154
void Dynamixel::ResetIndirectRead(std::vector<uint8_t> id_arr)
10601155
{
10611156
IndirectInfo temp;
1062-
temp.cnt = temp.size = 0;
1157+
temp.indirect_data_addr = 0;
1158+
temp.size = 0;
1159+
temp.cnt = 0;
10631160
temp.item_name.clear();
10641161
temp.item_size.clear();
10651162
for (auto it_id : id_arr) {
10661163
indirect_info_read_[it_id] = temp;
10671164
}
10681165
}
10691166

1167+
DxlError Dynamixel::CheckIndirectReadAvailable(uint8_t id)
1168+
{
1169+
uint16_t INDIRECT_ADDR;
1170+
uint8_t INDIRECT_SIZE;
1171+
if (dxl_info_.GetDxlControlItem(
1172+
id, "Indirect Address Read",
1173+
INDIRECT_ADDR, INDIRECT_SIZE) == false)
1174+
{
1175+
return DxlError::CANNOT_FIND_CONTROL_ITEM;
1176+
}
1177+
return DxlError::OK;
1178+
}
1179+
10701180
DxlError Dynamixel::AddIndirectRead(
10711181
uint8_t id,
10721182
std::string item_name,
@@ -1273,7 +1383,7 @@ DxlError Dynamixel::SetBulkWriteHandler(std::vector<uint8_t> id_arr)
12731383
fprintf(
12741384
stderr,
12751385
"set bulk write (indirect addr) : addr %d, size %d\n",
1276-
IN_ADDR, indirect_info_write_[id_arr.at(0)].size);
1386+
IN_ADDR, indirect_info_write_[it_id].size);
12771387
}
12781388

12791389
group_bulk_write_ = new dynamixel::GroupBulkWrite(port_handler_, packet_handler_);
@@ -1336,7 +1446,9 @@ DxlError Dynamixel::SetDxlValueToBulkWrite()
13361446
void Dynamixel::ResetIndirectWrite(std::vector<uint8_t> id_arr)
13371447
{
13381448
IndirectInfo temp;
1339-
temp.cnt = temp.size = 0;
1449+
temp.indirect_data_addr = 0;
1450+
temp.size = 0;
1451+
temp.cnt = 0;
13401452
temp.item_name.clear();
13411453
temp.item_size.clear();
13421454
for (auto it_id : id_arr) {

0 commit comments

Comments
 (0)