Skip to content

Commit e2bb092

Browse files
committed
refactor: add GPIO controller command handling to Dynamixel hardware interface
1 parent 76076c3 commit e2bb092

File tree

4 files changed

+232
-54
lines changed

4 files changed

+232
-54
lines changed

include/dynamixel_hardware_interface/dynamixel/dynamixel.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ class Dynamixel
144144

145145
// bulk write
146146
dynamixel::GroupBulkWrite * group_bulk_write_;
147+
// direct inform for bulk write
148+
std::map<uint8_t /*id*/, IndirectInfo> direct_info_write_;
147149

148150
public:
149151
explicit Dynamixel(const char * path);
@@ -254,8 +256,12 @@ class Dynamixel
254256
DxlError SetBulkWriteHandler(std::vector<uint8_t> id_arr);
255257
DxlError SetDxlValueToBulkWrite();
256258

259+
// Check Indirect Write
260+
DxlError CheckIndirectWriteAvailable(uint8_t id);
261+
257262
// Write - Indirect Address
258263
void ResetIndirectWrite(std::vector<uint8_t> id_arr);
264+
void ResetDirectWrite(std::vector<uint8_t> id_arr);
259265
DxlError AddIndirectWrite(
260266
uint8_t id,
261267
std::string item_name,

include/dynamixel_hardware_interface/dynamixel_hardware_interface.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ class DynamixelHardware : public
244244
std::vector<HandlerVarType> hdl_gpio_sensor_states_;
245245
std::vector<HandlerVarType> hdl_sensor_states_;
246246

247+
///// handler controller variable
248+
std::vector<HandlerVarType> hdl_gpio_controller_commands_;
249+
247250
bool is_set_hdl_{false};
248251

249252
// joint <-> transmission matrix

src/dynamixel/dynamixel.cpp

Lines changed: 172 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,11 @@ bool Dynamixel::checkWriteType()
723723
// Check if Indirect Data Write address and size are different
724724
uint16_t indirect_addr[2]; // [i-1], [i]
725725
uint8_t indirect_size[2]; // [i-1], [i]
726+
727+
if (CheckIndirectWriteAvailable(write_data_list_.at(dxl_index - 1).id) != DxlError::OK) {
728+
return BULK;
729+
}
730+
726731
if (!dxl_info_.GetDxlControlItem(
727732
write_data_list_.at(dxl_index).id, "Indirect Data Write", indirect_addr[1],
728733
indirect_size[1]) ||
@@ -758,6 +763,19 @@ bool Dynamixel::checkWriteType()
758763
return SYNC;
759764
}
760765

766+
DxlError Dynamixel::CheckIndirectWriteAvailable(uint8_t id)
767+
{
768+
uint16_t INDIRECT_ADDR;
769+
uint8_t INDIRECT_SIZE;
770+
if (dxl_info_.GetDxlControlItem(
771+
id, "Indirect Address Write",
772+
INDIRECT_ADDR, INDIRECT_SIZE) == false)
773+
{
774+
return DxlError::CANNOT_FIND_CONTROL_ITEM;
775+
}
776+
return DxlError::OK;
777+
}
778+
761779
DxlError Dynamixel::SetSyncReadItemAndHandler()
762780
{
763781
std::vector<uint8_t> id_arr;
@@ -862,7 +880,7 @@ DxlError Dynamixel::GetDxlValueFromSyncRead(double period_ms)
862880
DxlError Dynamixel::SetBulkReadItemAndHandler()
863881
{
864882
group_bulk_read_ = new dynamixel::GroupBulkRead(port_handler_, packet_handler_);
865-
883+
866884
std::vector<uint8_t> indirect_id_arr;
867885
std::vector<uint8_t> direct_id_arr;
868886

@@ -947,7 +965,7 @@ DxlError Dynamixel::SetBulkReadItemAndHandler()
947965
}
948966
}
949967
}
950-
968+
951969
if (SetBulkReadHandler(indirect_id_arr) != DxlError::OK) {
952970
fprintf(stderr, "Cannot set the BulkRead handler.\n");
953971
return DxlError::BULK_READ_FAIL;
@@ -1330,10 +1348,76 @@ DxlError Dynamixel::SetBulkWriteItemAndHandler()
13301348
id_arr.push_back(it_write_data.id);
13311349
}
13321350

1333-
DynamixelDisable(id_arr);
1334-
ResetIndirectWrite(id_arr);
1351+
group_bulk_write_ = new dynamixel::GroupBulkWrite(port_handler_, packet_handler_);
1352+
1353+
std::vector<uint8_t> indirect_id_arr;
1354+
std::vector<uint8_t> direct_id_arr;
1355+
1356+
std::vector<RWItemList> indirect_write_data_list;
1357+
std::vector<RWItemList> direct_write_data_list;
13351358

13361359
for (auto it_write_data : write_data_list_) {
1360+
if (CheckIndirectWriteAvailable(it_write_data.id) == DxlError::OK) {
1361+
indirect_id_arr.push_back(it_write_data.id);
1362+
indirect_write_data_list.push_back(it_write_data);
1363+
} else {
1364+
direct_id_arr.push_back(it_write_data.id);
1365+
direct_write_data_list.push_back(it_write_data);
1366+
}
1367+
}
1368+
1369+
ResetDirectWrite(direct_id_arr);
1370+
1371+
// Handle direct writes
1372+
for (auto it_write_data : direct_write_data_list) {
1373+
if (it_write_data.item_addr.empty() || it_write_data.item_size.empty()) {
1374+
continue;
1375+
}
1376+
// Calculate min address and max end address
1377+
uint16_t min_addr = it_write_data.item_addr[0];
1378+
uint16_t max_end_addr = it_write_data.item_addr[0] + it_write_data.item_size[0];
1379+
for (size_t item_index = 1; item_index < it_write_data.item_addr.size(); ++item_index) {
1380+
uint16_t addr = it_write_data.item_addr[item_index];
1381+
uint16_t size = it_write_data.item_size[item_index];
1382+
if (addr < min_addr) min_addr = addr;
1383+
if (addr + size > max_end_addr) max_end_addr = addr + size;
1384+
}
1385+
uint8_t total_size = max_end_addr - min_addr;
1386+
1387+
// Check for gaps between items
1388+
std::vector<std::pair<uint16_t, uint16_t>> addr_ranges;
1389+
for (size_t item_index = 0; item_index < it_write_data.item_addr.size(); ++item_index) {
1390+
addr_ranges.push_back({it_write_data.item_addr[item_index],
1391+
it_write_data.item_addr[item_index] + it_write_data.item_size[item_index]});
1392+
}
1393+
std::sort(addr_ranges.begin(), addr_ranges.end());
1394+
1395+
for (size_t i = 0; i < addr_ranges.size() - 1; ++i) {
1396+
if (addr_ranges[i].second != addr_ranges[i + 1].first) {
1397+
fprintf(stderr, "[ID:%03d] Error: Gap detected between items at addresses %d and %d\n",
1398+
it_write_data.id, addr_ranges[i].second, addr_ranges[i + 1].first);
1399+
return DxlError::BULK_WRITE_FAIL;
1400+
}
1401+
}
1402+
1403+
// Store direct write info
1404+
direct_info_write_[it_write_data.id].indirect_data_addr = min_addr;
1405+
direct_info_write_[it_write_data.id].size = total_size;
1406+
direct_info_write_[it_write_data.id].cnt = it_write_data.item_name.size();
1407+
direct_info_write_[it_write_data.id].item_name = it_write_data.item_name;
1408+
direct_info_write_[it_write_data.id].item_size = it_write_data.item_size;
1409+
1410+
fprintf(
1411+
stderr,
1412+
"set bulk write (direct addr) : addr %d, size %d\n",
1413+
min_addr, total_size);
1414+
}
1415+
1416+
// Handle indirect writes
1417+
DynamixelDisable(indirect_id_arr);
1418+
ResetIndirectWrite(indirect_id_arr);
1419+
1420+
for (auto it_write_data : indirect_write_data_list) {
13371421
for (size_t item_index = 0; item_index < it_write_data.item_name.size();
13381422
item_index++)
13391423
{
@@ -1354,7 +1438,7 @@ DxlError Dynamixel::SetBulkWriteItemAndHandler()
13541438
}
13551439
}
13561440

1357-
if (SetBulkWriteHandler(id_arr) < 0) {
1441+
if (SetBulkWriteHandler(indirect_id_arr) < 0) {
13581442
fprintf(stderr, "Cannot set the BulkWrite handler.\n");
13591443
return DxlError::BULK_WRITE_FAIL;
13601444
}
@@ -1386,49 +1470,88 @@ DxlError Dynamixel::SetBulkWriteHandler(std::vector<uint8_t> id_arr)
13861470
IN_ADDR, indirect_info_write_[it_id].size);
13871471
}
13881472

1389-
group_bulk_write_ = new dynamixel::GroupBulkWrite(port_handler_, packet_handler_);
1390-
13911473
return DxlError::OK;
13921474
}
13931475

13941476
DxlError Dynamixel::SetDxlValueToBulkWrite()
13951477
{
13961478
for (auto it_write_data : write_data_list_) {
13971479
uint8_t ID = it_write_data.id;
1398-
uint8_t * param_write_value = new uint8_t[indirect_info_write_[ID].size];
1480+
uint8_t * param_write_value;
13991481
uint8_t added_byte = 0;
14001482

1483+
// Check if this is a direct write
1484+
if (direct_info_write_.find(ID) != direct_info_write_.end()) {
1485+
param_write_value = new uint8_t[direct_info_write_[ID].size];
1486+
1487+
for (uint16_t item_index = 0; item_index < direct_info_write_[ID].cnt; item_index++) {
1488+
double data = *it_write_data.item_data_ptr_vec.at(item_index);
1489+
uint8_t size = direct_info_write_[ID].item_size.at(item_index);
1490+
1491+
if (size == 4) {
1492+
int32_t value = static_cast<int32_t>(data);
1493+
param_write_value[added_byte + 0] = DXL_LOBYTE(DXL_LOWORD(value));
1494+
param_write_value[added_byte + 1] = DXL_HIBYTE(DXL_LOWORD(value));
1495+
param_write_value[added_byte + 2] = DXL_LOBYTE(DXL_HIWORD(value));
1496+
param_write_value[added_byte + 3] = DXL_HIBYTE(DXL_HIWORD(value));
1497+
} else if (size == 2) {
1498+
int16_t value = static_cast<int16_t>(data);
1499+
param_write_value[added_byte + 0] = DXL_LOBYTE(value);
1500+
param_write_value[added_byte + 1] = DXL_HIBYTE(value);
1501+
} else if (size == 1) {
1502+
param_write_value[added_byte] = static_cast<uint8_t>(data);
1503+
printf("[ID:%03d] Add Direct Write Item : [%s][%d][%d]\n", ID,
1504+
direct_info_write_[ID].item_name.at(item_index).c_str(),
1505+
direct_info_write_[ID].indirect_data_addr,
1506+
size);
1507+
}
1508+
added_byte += size;
1509+
}
14011510

1402-
for (uint16_t item_index = 0; item_index < indirect_info_write_[ID].cnt; item_index++) {
1403-
double data = *it_write_data.item_data_ptr_vec.at(item_index);
1404-
if (indirect_info_write_[ID].item_name.at(item_index) == "Goal Position") {
1405-
int32_t goal_position = dxl_info_.ConvertRadianToValue(ID, data);
1406-
param_write_value[added_byte + 0] = DXL_LOBYTE(DXL_LOWORD(goal_position));
1407-
param_write_value[added_byte + 1] = DXL_HIBYTE(DXL_LOWORD(goal_position));
1408-
param_write_value[added_byte + 2] = DXL_LOBYTE(DXL_HIWORD(goal_position));
1409-
param_write_value[added_byte + 3] = DXL_HIBYTE(DXL_HIWORD(goal_position));
1410-
} else if (indirect_info_write_[ID].item_name.at(item_index) == "Goal Velocity") {
1411-
int32_t goal_velocity = dxl_info_.ConvertVelocityRPSToValueRPM(data);
1412-
param_write_value[added_byte + 0] = DXL_LOBYTE(DXL_LOWORD(goal_velocity));
1413-
param_write_value[added_byte + 1] = DXL_HIBYTE(DXL_LOWORD(goal_velocity));
1414-
param_write_value[added_byte + 2] = DXL_LOBYTE(DXL_HIWORD(goal_velocity));
1415-
param_write_value[added_byte + 3] = DXL_HIBYTE(DXL_HIWORD(goal_velocity));
1416-
} else if (indirect_info_write_[ID].item_name.at(item_index) == "Goal Current") {
1417-
int16_t goal_current = dxl_info_.ConvertEffortToCurrent(ID, data);
1418-
param_write_value[added_byte + 0] = DXL_LOBYTE(goal_current);
1419-
param_write_value[added_byte + 1] = DXL_HIBYTE(goal_current);
1511+
if (group_bulk_write_->addParam(
1512+
ID,
1513+
direct_info_write_[ID].indirect_data_addr,
1514+
direct_info_write_[ID].size,
1515+
param_write_value) != true)
1516+
{
1517+
printf("[ID:%03d] groupBulkWrite addparam failed\n", ID);
1518+
return DxlError::BULK_WRITE_FAIL;
1519+
}
1520+
} else {
1521+
// Handle indirect write
1522+
param_write_value = new uint8_t[indirect_info_write_[ID].size];
1523+
1524+
for (uint16_t item_index = 0; item_index < indirect_info_write_[ID].cnt; item_index++) {
1525+
double data = *it_write_data.item_data_ptr_vec.at(item_index);
1526+
if (indirect_info_write_[ID].item_name.at(item_index) == "Goal Position") {
1527+
int32_t goal_position = dxl_info_.ConvertRadianToValue(ID, data);
1528+
param_write_value[added_byte + 0] = DXL_LOBYTE(DXL_LOWORD(goal_position));
1529+
param_write_value[added_byte + 1] = DXL_HIBYTE(DXL_LOWORD(goal_position));
1530+
param_write_value[added_byte + 2] = DXL_LOBYTE(DXL_HIWORD(goal_position));
1531+
param_write_value[added_byte + 3] = DXL_HIBYTE(DXL_HIWORD(goal_position));
1532+
} else if (indirect_info_write_[ID].item_name.at(item_index) == "Goal Velocity") {
1533+
int32_t goal_velocity = dxl_info_.ConvertVelocityRPSToValueRPM(data);
1534+
param_write_value[added_byte + 0] = DXL_LOBYTE(DXL_LOWORD(goal_velocity));
1535+
param_write_value[added_byte + 1] = DXL_HIBYTE(DXL_LOWORD(goal_velocity));
1536+
param_write_value[added_byte + 2] = DXL_LOBYTE(DXL_HIWORD(goal_velocity));
1537+
param_write_value[added_byte + 3] = DXL_HIBYTE(DXL_HIWORD(goal_velocity));
1538+
} else if (indirect_info_write_[ID].item_name.at(item_index) == "Goal Current") {
1539+
int16_t goal_current = dxl_info_.ConvertEffortToCurrent(ID, data);
1540+
param_write_value[added_byte + 0] = DXL_LOBYTE(goal_current);
1541+
param_write_value[added_byte + 1] = DXL_HIBYTE(goal_current);
1542+
}
1543+
added_byte += indirect_info_write_[ID].item_size.at(item_index);
14201544
}
1421-
added_byte += indirect_info_write_[ID].item_size.at(item_index);
1422-
}
14231545

1424-
if (group_bulk_write_->addParam(
1425-
ID,
1426-
indirect_info_write_[ID].indirect_data_addr,
1427-
indirect_info_write_[ID].size,
1428-
param_write_value) != true)
1429-
{
1430-
printf("[ID:%03d] groupBulkWrite addparam failed\n", ID);
1431-
return DxlError::BULK_WRITE_FAIL;
1546+
if (group_bulk_write_->addParam(
1547+
ID,
1548+
indirect_info_write_[ID].indirect_data_addr,
1549+
indirect_info_write_[ID].size,
1550+
param_write_value) != true)
1551+
{
1552+
printf("[ID:%03d] groupBulkWrite addparam failed\n", ID);
1553+
return DxlError::BULK_WRITE_FAIL;
1554+
}
14321555
}
14331556
}
14341557

@@ -1482,4 +1605,17 @@ DxlError Dynamixel::AddIndirectWrite(
14821605

14831606
return DxlError::OK;
14841607
}
1608+
1609+
void Dynamixel::ResetDirectWrite(std::vector<uint8_t> id_arr)
1610+
{
1611+
IndirectInfo temp;
1612+
temp.indirect_data_addr = 0;
1613+
temp.size = 0;
1614+
temp.cnt = 0;
1615+
temp.item_name.clear();
1616+
temp.item_size.clear();
1617+
for (auto it_id : id_arr) {
1618+
direct_info_write_[it_id] = temp;
1619+
}
1620+
}
14851621
} // namespace dynamixel_hardware_interface

0 commit comments

Comments
 (0)