@@ -723,6 +723,11 @@ bool Dynamixel::checkWriteType()
723
723
// Check if Indirect Data Write address and size are different
724
724
uint16_t indirect_addr[2 ]; // [i-1], [i]
725
725
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
+
726
731
if (!dxl_info_.GetDxlControlItem (
727
732
write_data_list_.at (dxl_index).id , " Indirect Data Write" , indirect_addr[1 ],
728
733
indirect_size[1 ]) ||
@@ -758,6 +763,19 @@ bool Dynamixel::checkWriteType()
758
763
return SYNC;
759
764
}
760
765
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
+
761
779
DxlError Dynamixel::SetSyncReadItemAndHandler ()
762
780
{
763
781
std::vector<uint8_t > id_arr;
@@ -862,7 +880,7 @@ DxlError Dynamixel::GetDxlValueFromSyncRead(double period_ms)
862
880
DxlError Dynamixel::SetBulkReadItemAndHandler ()
863
881
{
864
882
group_bulk_read_ = new dynamixel::GroupBulkRead (port_handler_, packet_handler_);
865
-
883
+
866
884
std::vector<uint8_t > indirect_id_arr;
867
885
std::vector<uint8_t > direct_id_arr;
868
886
@@ -947,7 +965,7 @@ DxlError Dynamixel::SetBulkReadItemAndHandler()
947
965
}
948
966
}
949
967
}
950
-
968
+
951
969
if (SetBulkReadHandler (indirect_id_arr) != DxlError::OK) {
952
970
fprintf (stderr, " Cannot set the BulkRead handler.\n " );
953
971
return DxlError::BULK_READ_FAIL;
@@ -1330,10 +1348,76 @@ DxlError Dynamixel::SetBulkWriteItemAndHandler()
1330
1348
id_arr.push_back (it_write_data.id );
1331
1349
}
1332
1350
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;
1335
1358
1336
1359
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) {
1337
1421
for (size_t item_index = 0 ; item_index < it_write_data.item_name .size ();
1338
1422
item_index++)
1339
1423
{
@@ -1354,7 +1438,7 @@ DxlError Dynamixel::SetBulkWriteItemAndHandler()
1354
1438
}
1355
1439
}
1356
1440
1357
- if (SetBulkWriteHandler (id_arr ) < 0 ) {
1441
+ if (SetBulkWriteHandler (indirect_id_arr ) < 0 ) {
1358
1442
fprintf (stderr, " Cannot set the BulkWrite handler.\n " );
1359
1443
return DxlError::BULK_WRITE_FAIL;
1360
1444
}
@@ -1386,49 +1470,88 @@ DxlError Dynamixel::SetBulkWriteHandler(std::vector<uint8_t> id_arr)
1386
1470
IN_ADDR, indirect_info_write_[it_id].size );
1387
1471
}
1388
1472
1389
- group_bulk_write_ = new dynamixel::GroupBulkWrite (port_handler_, packet_handler_);
1390
-
1391
1473
return DxlError::OK;
1392
1474
}
1393
1475
1394
1476
DxlError Dynamixel::SetDxlValueToBulkWrite ()
1395
1477
{
1396
1478
for (auto it_write_data : write_data_list_) {
1397
1479
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;
1399
1481
uint8_t added_byte = 0 ;
1400
1482
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
+ }
1401
1510
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);
1420
1544
}
1421
- added_byte += indirect_info_write_[ID].item_size .at (item_index);
1422
- }
1423
1545
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
+ }
1432
1555
}
1433
1556
}
1434
1557
@@ -1482,4 +1605,17 @@ DxlError Dynamixel::AddIndirectWrite(
1482
1605
1483
1606
return DxlError::OK;
1484
1607
}
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
+ }
1485
1621
} // namespace dynamixel_hardware_interface
0 commit comments