Edit on GitHub
Step 3: Leader and Follower Example

- This tutorial shows you how to read data from one Dynamixel and write the read value to another Dynamixel using the Dynamixel Easy SDK.
NOTE: It assumes that you have already installed and built the SDK.
Make py file
- Create a new Python source file Open it with your editor.
$ touch tutorial_step3.py
Check the Port Names
- Before running the code, check the port name of the connected Dynamixel.
- For General
- OpenRB-150:
ttyACM0: USB ACM device - U2D2:
FTDI USB Serial Device converter now attached to ttyUSB0$ sudo dmesg | grep tty
- OpenRB-150:
Source Code Description
from dynamixel_easy_sdk import *
def main():
connector = Connector("/dev/ttyACM0", 57600)
leader_motor = connector.createMotor(1)
follower_motor = connector.createMotor(2)
min_position = leader_motor.getMinPositionLimit() + 100
max_position = leader_motor.getMaxPositionLimit() - 100
leader_motor.disableTorque()
follower_motor.disableTorque()
follower_motor.setOperatingMode(OperatingMode.POSITION)
follower_motor.enableTorque()
while (True):
present_position = leader_motor.getPresentPosition()
print(f"Leader Position: {present_position} ", end='\r')
if (present_position < min_position):
leader_motor.enableTorque()
leader_motor.setGoalPosition(min_position)
while (True):
present_position = leader_motor.getPresentPosition()
if (present_position >= min_position):
break
leader_motor.disableTorque()
elif (present_position > max_position):
leader_motor.enableTorque()
leader_motor.setGoalPosition(max_position)
while (True):
present_position = leader_motor.getPresentPosition()
if (present_position <= max_position):
break
leader_motor.disableTorque()
follower_motor.setGoalPosition(present_position)
if __name__ == "__main__":
main()
Import Library
- Import
dynamixel_easy_sdk.from dynamixel_easy_sdk import *
Create Connector and Motor Object
- Create a
Connectorobject with port name and baud rate to manage the communication.def main(): connector = Connector("/dev/ttyACM0", 57600) - Create a
Motorobject for each Dynamixel servo you want to control with its ID, using thecreateMotormethod of theConnectorclass. - Create motor objects while carefully distinguishing between the leader and follower IDs.
leader_motor = connector.createMotor(1) follower_motor = connector.createMotor(2)
Set Position Limits
- Get the position limits of the leader motor using the
getMinPositionLimitandgetMaxPositionLimitmethods.min_position = leader_motor.getMinPositionLimit() + 100 max_position = leader_motor.getMaxPositionLimit() - 100
Set Operating Mode to Position Control Mode
- Use the methods provided by the
Motorclass to control the Dynamixel servo. - Set the operating mode of follower motor to position control mode.
leader_motor.disableTorque() follower_motor.disableTorque() follower_motor.setOperatingMode(OperatingMode.POSITION) follower_motor.enableTorque()
Leader and Follower Control Loop
- In a loop, read the present position of the leader motor using the
getPresentPositionmethod.while (True): present_position = leader_motor.getPresentPosition() print(f"Leader Position: {present_position} ", end='\r') - If the leader motor’s position exceeds the defined range, move it back within the range.
if (present_position < min_position): leader_motor.enableTorque() leader_motor.setGoalPosition(min_position) while (True): present_position = leader_motor.getPresentPosition() if (present_position >= min_position): break leader_motor.disableTorque() elif (present_position > max_position): leader_motor.enableTorque() leader_motor.setGoalPosition(max_position) while (True): present_position = leader_motor.getPresentPosition() if (present_position <= max_position): break leader_motor.disableTorque() - Set the goal position of the follower motor to the present position of the leader motor.
follower_motor.setGoalPosition(present_position)
Error Handling
- When an error occurs,
DxlRuntimeErroris raised. - You can catch this error using a try-except block.
try: motor1.getPresentPosition() except DxlRuntimeError as e: print(e) DxlRuntimeErrorcontainsDxlErrorEnum that provides detailed information about the error.try: motor1.getPresentPosition() except DxlRuntimeError as e: if e.dxl_error == DxlError.SDK_COMM_RX_FAIL: print("Transmission failed.") elif e.dxl_error == DxlError.SDK_COMM_RX_FAIL: print("Receive failed.")
NOTE: It assumes that you have already installed and built the SDK.
Make cpp file
- Create a new C++ source file Open it with your editor.
$ touch tutorial_step3.cpp
Check the Port Names
- Before running the code, check the port name of the connected Dynamixel.
- For General
- OpenRB-150:
ttyACM0: USB ACM device - U2D2:
FTDI USB Serial Device converter now attached to ttyUSB0$ sudo dmesg | grep tty
- OpenRB-150:
Source Code Description
#include "dynamixel_easy_sdk/dynamixel_easy_sdk.hpp"
int main(){
dynamixel::Connector connector("/dev/ttyACM0", 57600);
std::unique_ptr<dynamixel::Motor> leader_motor = connector.createMotor(1);
std::unique_ptr<dynamixel::Motor> follower_motor = connector.createMotor(2);
int min_position = leader_motor->getMinPositionLimit().value() + 100;
int max_position = leader_motor->getMaxPositionLimit().value() - 100;
leader_motor->disableTorque();
follower_motor->disableTorque();
follower_motor->setOperatingMode(dynamixel::Motor::OperatingMode::POSITION);
follower_motor->enableTorque();
while (true) {
int present_position = leader_motor->getPresentPosition().value();
std::cout << "Leader Motor Present Position: " << present_position << std::endl;
if (present_position < min_position) {
leader_motor->enableTorque();
leader_motor->setGoalPosition(min_position);
while(true){
present_position = leader_motor->getPresentPosition().value();
if(present_position >= min_position) break;
}
leader_motor->disableTorque();
} else if (present_position > max_position) {
leader_motor->enableTorque();
leader_motor->setGoalPosition(max_position);
while(true){
present_position = leader_motor->getPresentPosition().value();
if(present_position <= max_position) break;
}
leader_motor->disableTorque();
}
follower_motor->setGoalPosition(present_position);
}
}
Add Header Files
- Add
dynamixel_easy_sdk/dynamixel_easy_sdk.hppto the top of your CPP file. This class is included in the Dynamixel SDK package.#include "dynamixel_easy_sdk/dynamixel_easy_sdk.hpp"
Create Connector and Motor Object
- Create a
Connectorobject with port name and baud rate to manage the communication.int main(){ dynamixel::Connector connector("/dev/ttyACM0", 57600); - Create a
Motorobject for each Dynamixel servo you want to control, using thecreateMotormethod of theConnectorclass. - This method takes the motor ID as an argument and returns a unique pointer to a
Motorinstance. (shared_ptr is also available) - Create motor objects while carefully distinguishing between the leader and follower IDs.
std::unique_ptr<dynamixel::Motor> leader_motor = connector.createMotor(1); std::unique_ptr<dynamixel::Motor> follower_motor = connector.createMotor(2); - This process throws a
DxlRuntimeErrorif the object creation fails.
Set Position Limits
- Get the position limits of the leader motor using the
getMinPositionLimitandgetMaxPositionLimitmethods.int min_position = leader_motor->getMinPositionLimit().value() + 100; int max_position = leader_motor->getMaxPositionLimit().value() - 100;
Set Operating Mode to Position Control Mode
- Use the methods provided by the
Motorclass to control the Dynamixel servo. - Set the operating mode of follower motor to position control mode.
leader_motor->disableTorque(); follower_motor->disableTorque(); follower_motor->setOperatingMode(dynamixel::Motor::OperatingMode::POSITION); follower_motor->enableTorque();
Leader and Follower Control Loop
- In a loop, read the present position of the leader motor using the
getPresentPositionmethod.while (true) { int present_position = leader_motor->getPresentPosition().value(); std::cout << "Leader Motor Present Position: " << present_position << std::endl; - If the leader motor’s position exceeds the defined range, move it back within the range.
if (present_position < min_position) { leader_motor->enableTorque(); leader_motor->setGoalPosition(min_position); while(true){ present_position = leader_motor->getPresentPosition().value(); if(present_position >= min_position) break; } leader_motor->disableTorque(); } else if (present_position > max_position) { leader_motor->enableTorque(); leader_motor->setGoalPosition(max_position); while(true){ present_position = leader_motor->getPresentPosition().value(); if(present_position <= max_position) break; } leader_motor->disableTorque(); } - Set the goal position of the follower motor to the present position of the leader motor.
follower_motor->setGoalPosition(present_position); } }
Error Handling
- To ensure your code is robust, every method that sends a command to the motor returns a Result object that encapsulates values and errors.
- This object lets you safely check for any communication or device errors before proceeding.
- You can check for communication errors and device(dynamixel) errors using the Result object.
-
If you use
value()when error occurred without checking for errors, it may throw an exception.Example
auto result_uint32 = leader_motor->getMinPositionLimit(); if (!result_uint32.isSuccess()) { std::cerr << dynamixel::getErrorMessage(result_uint32.error()) << std::endl; return 1; } int min_position = result_uint32.value();
Compile and Run
- You can compile and run the code using the following commands
$ g++ tutorial_step3.cpp -o tutorial_step3 -l dxl_x64_cpp $ ./tutorial_step3

