Edit on GitHub
Step 4: OMX Teleoperation Example

- This tutorial shows an example of OMX teleoperation using the Dynamixel Easy SDK.
- With an OMX leader and follower, you can create your own teleoperation system in just a few lines of code.
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_step4.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_leader("/dev/ttyACM1", 1000000);
dynamixel::Connector connector_follower("/dev/ttyACM0", 1000000);
std::unique_ptr<dynamixel::Motor> leader_motor1 = connector_leader.createMotor(1);
std::unique_ptr<dynamixel::Motor> leader_motor2 = connector_leader.createMotor(2);
std::unique_ptr<dynamixel::Motor> leader_motor3 = connector_leader.createMotor(3);
std::unique_ptr<dynamixel::Motor> leader_motor4 = connector_leader.createMotor(4);
std::unique_ptr<dynamixel::Motor> leader_motor5 = connector_leader.createMotor(5);
std::unique_ptr<dynamixel::Motor> leader_motor_gripper = connector_leader.createMotor(6);
std::unique_ptr<dynamixel::Motor> follower_motor1 = connector_follower.createMotor(11);
std::unique_ptr<dynamixel::Motor> follower_motor2 = connector_follower.createMotor(12);
std::unique_ptr<dynamixel::Motor> follower_motor3 = connector_follower.createMotor(13);
std::unique_ptr<dynamixel::Motor> follower_motor4 = connector_follower.createMotor(14);
std::unique_ptr<dynamixel::Motor> follower_motor5 = connector_follower.createMotor(15);
std::unique_ptr<dynamixel::Motor> follower_motor_gripper = connector_follower.createMotor(16);
follower_motor1->enableTorque();
follower_motor2->enableTorque();
follower_motor3->enableTorque();
follower_motor4->enableTorque();
follower_motor5->enableTorque();
follower_motor_gripper->enableTorque();
while (true) {
int present_position1 = leader_motor1->getPresentPosition().value();
int present_position2 = leader_motor2->getPresentPosition().value();
int present_position3 = leader_motor3->getPresentPosition().value();
int present_position4 = leader_motor4->getPresentPosition().value();
int present_position5 = leader_motor5->getPresentPosition().value();
int present_position_gripper = leader_motor_gripper->getPresentPosition().value();
follower_motor1->setGoalPosition(present_position1);
follower_motor2->setGoalPosition(present_position2);
follower_motor3->setGoalPosition(present_position3);
follower_motor4->setGoalPosition(present_position4);
follower_motor5->setGoalPosition(present_position5);
follower_motor_gripper->setGoalPosition(present_position_gripper);
}
}
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. - In OMX, two separate OpenRB adapters are used for the leader and follower motors, so create two
Connectorobjects with different port names. - On OMX, the default baud rate is 1,000,000.
- Port names may vary depending on your system configuration.
int main(){ dynamixel::Connector connector_leader("/dev/ttyACM1", 1000000); dynamixel::Connector connector_follower("/dev/ttyACM0", 1000000); - Create a
Motorobjects for each Dynamixels, using thecreateMotormethod of theConnectorclass. - In OMX, the leader motors have IDs 1 to 6, and the follower motors have IDs 11 to 16.
std::unique_ptr<dynamixel::Motor> leader_motor1 = connector_leader.createMotor(1); std::unique_ptr<dynamixel::Motor> leader_motor2 = connector_leader.createMotor(2); std::unique_ptr<dynamixel::Motor> leader_motor3 = connector_leader.createMotor(3); std::unique_ptr<dynamixel::Motor> leader_motor4 = connector_leader.createMotor(4); std::unique_ptr<dynamixel::Motor> leader_motor5 = connector_leader.createMotor(5); std::unique_ptr<dynamixel::Motor> leader_motor_gripper = connector_leader.createMotor(6); std::unique_ptr<dynamixel::Motor> follower_motor1 = connector_follower.createMotor(11); std::unique_ptr<dynamixel::Motor> follower_motor2 = connector_follower.createMotor(12); std::unique_ptr<dynamixel::Motor> follower_motor3 = connector_follower.createMotor(13); std::unique_ptr<dynamixel::Motor> follower_motor4 = connector_follower.createMotor(14); std::unique_ptr<dynamixel::Motor> follower_motor5 = connector_follower.createMotor(15); std::unique_ptr<dynamixel::Motor> follower_motor_gripper = connector_follower.createMotor(16);
Enable Follower Torque
- Enable the torque of the follower motors for teleoperation.
follower_motor1->enableTorque(); follower_motor2->enableTorque(); follower_motor3->enableTorque(); follower_motor4->enableTorque(); follower_motor5->enableTorque(); follower_motor_gripper->enableTorque();
Leader and Follower Control Loop
- In a loop, read the present position of the leader motors using the
getPresentPositionmethod and set the goal position of the follower motors to the same value using thesetGoalPositionmethod.while (true) { int present_position1 = leader_motor1->getPresentPosition().value(); int present_position2 = leader_motor2->getPresentPosition().value(); int present_position3 = leader_motor3->getPresentPosition().value(); int present_position4 = leader_motor4->getPresentPosition().value(); int present_position5 = leader_motor5->getPresentPosition().value(); int present_position_gripper = leader_motor_gripper->getPresentPosition().value(); follower_motor1->setGoalPosition(present_position1); follower_motor2->setGoalPosition(present_position2); follower_motor3->setGoalPosition(present_position3); follower_motor4->setGoalPosition(present_position4); follower_motor5->setGoalPosition(present_position5); follower_motor_gripper->setGoalPosition(present_position_gripper); } }
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_int32 = leader_motor->getPresentPosition(); if (!result_int32.isSuccess()) { std::cerr << dynamixel::getErrorMessage(result_int32.error()) << std::endl; return 1; } int present_position = result_int32.value();
Compile and Run
- You can compile and run the code using the following commands
$ g++ dxl_tutorial_4.cpp -o dxl_tutorial_4 -l dxl_x64_cpp $ ./dxl_tutorial_4

