Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0c29a54
api update in cpp linux 64bit
GyuH13 Aug 29, 2025
ed28160
Add exception in input param of getAllMotors
GyuH13 Aug 31, 2025
73c37dc
Use Makefile macro for control table path instead of hardcoding
GyuH13 Sep 1, 2025
be4e0a7
remove duplicate model_list
GyuH13 Sep 1, 2025
c530947
fix indentation
GyuH13 Sep 1, 2025
2ecc213
make getmotor function return unique_ptr
GyuH13 Sep 1, 2025
c469d8b
apply guard clause to improve readability
GyuH13 Sep 1, 2025
9865753
delete tab
GyuH13 Sep 8, 2025
f28c620
apply broadcastPing to getAllmotors function
GyuH13 Sep 9, 2025
f67d1d9
makefile typo error
GyuH13 Sep 9, 2025
f0485ca
add example
GyuH13 Sep 9, 2025
6ed0156
lint
GyuH13 Sep 9, 2025
fb3609a
Bump
GyuH13 Sep 9, 2025
c7ecd45
add const return in dxl Result object
GyuH13 Sep 9, 2025
a39c5d0
Remove changebaudrate
GyuH13 Sep 9, 2025
c75d8e7
header guard fix
GyuH13 Sep 9, 2025
ca75cf2
Make drive mode setup function to use parameter
GyuH13 Sep 11, 2025
2cc597e
example code update
GyuH13 Sep 11, 2025
080fb44
add motor group
GyuH13 Sep 18, 2025
1276415
add motor group
GyuH13 Sep 18, 2025
4ddebcf
remove example
GyuH13 Sep 23, 2025
7fa6d53
add pid gain function
GyuH13 Sep 29, 2025
cef960a
add current function
GyuH13 Sep 29, 2025
baad93e
unified motor object with motor proxy
GyuH13 Oct 10, 2025
bfb62ef
change function name which is named getMotor to createMotor
GyuH13 Oct 10, 2025
3ef96ec
remove motor header in group_executor.hpp
GyuH13 Oct 10, 2025
0af6a8a
lint
GyuH13 Oct 14, 2025
970dddf
bump
GyuH13 Oct 14, 2025
5a4733f
bump
GyuH13 Oct 15, 2025
aaff0f1
remove protocol arg in connector
GyuH13 Oct 15, 2025
b87a605
add error checking
GyuH13 Oct 16, 2025
90d55c6
change file structure
GyuH13 Oct 16, 2025
1f812ea
modified makefile
GyuH13 Oct 16, 2025
0052c5c
bump
GyuH13 Oct 16, 2025
160e3b9
change name of package to Easy SDK
GyuH13 Oct 16, 2025
0a4f971
reflect review
GyuH13 Oct 21, 2025
693076c
reflect review
GyuH13 Oct 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ros-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ name: CI
# Specifies the events that trigger the workflow
on:
push:
branches: [ main, humble ]
branches: [ main, humble, jazzy ]
pull_request:
branches: [ main, humble ]
branches: [ main, humble, jazzy ]

# Defines a set of jobs to be run as part of the workflow
jobs:
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "DynamixelSDK c++"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 3.8.4
PROJECT_NUMBER = 4.0.0

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
5 changes: 5 additions & 0 deletions ReleaseNote.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Dynamixel SDK Release Notes

4.0.0 (2025-10-14)
------------------
* Update Dynamixel Easy SDK in C++ Linux 64bit
* Contributors: Hyungyu Kim

3.8.4 (2025-05-28)
------------------
* Deprecate ament_include_dependency usage in CMakeLists.txt
Expand Down
23 changes: 21 additions & 2 deletions c++/build/linux64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ SYMLINK = ln -s
MKDIR = mkdir
CC = gcc
CX = g++
CCFLAGS = -O2 -O3 -DLINUX -D_GNU_SOURCE -Wall -c $(INCLUDES) $(FORMAT) -fPIC -g
CXFLAGS = -O2 -O3 -DLINUX -D_GNU_SOURCE -Wall -c $(INCLUDES) $(FORMAT) -fPIC -g
CONTROL_TABLE_PATH_FLAG = -DCONTROL_TABLE_PATH=\"$(INSTALL_ROOT)/share/dynamixel_sdk/control_table\"
CCFLAGS = -O2 -O3 -DLINUX -D_GNU_SOURCE -Wall -c $(INCLUDES) $(FORMAT) -fPIC -g $(CONTROL_TABLE_PATH_FLAG)
CXFLAGS = -O2 -O3 -DLINUX -D_GNU_SOURCE -Wall -c $(INCLUDES) $(FORMAT) -fPIC -g $(CONTROL_TABLE_PATH_FLAG)
FORMAT = -m64
INCLUDES += -I$(DIR_DXL)/include/dynamixel_sdk
INCLUDES += -I$(DIR_DXL)/include

#---------------------------------------------------------------------
# Required external libraries
Expand All @@ -60,6 +62,11 @@ SOURCES = src/dynamixel_sdk/group_bulk_read.cpp \
src/dynamixel_sdk/protocol1_packet_handler.cpp \
src/dynamixel_sdk/protocol2_packet_handler.cpp \
src/dynamixel_sdk/port_handler_linux.cpp \
src/dynamixel_easy_sdk/connector.cpp \
src/dynamixel_easy_sdk/control_table.cpp \
src/dynamixel_easy_sdk/motor.cpp \
src/dynamixel_easy_sdk/dynamixel_error.cpp \
src/dynamixel_easy_sdk/group_executor.cpp


OBJECTS=$(addsuffix .o,$(addprefix $(DIR_OBJS)/,$(basename $(notdir $(SOURCES)))))
Expand Down Expand Up @@ -89,6 +96,13 @@ install: $(TARGET)
@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/include/dynamixel_sdk || $(MKDIR) $(INSTALL_ROOT)/include/dynamixel_sdk
$(CP_ALL) $(DIR_DXL)/include/dynamixel_sdk/* $(INSTALL_ROOT)/include/dynamixel_sdk

@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/include/dynamixel_easy_sdk || $(MKDIR) $(INSTALL_ROOT)/include/dynamixel_easy_sdk
$(CP_ALL) $(DIR_DXL)/include/dynamixel_easy_sdk/* $(INSTALL_ROOT)/include/dynamixel_easy_sdk

# copy the control_table directory into the share directory
@$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/share/dynamixel_sdk || $(MKDIR) -p $(INSTALL_ROOT)/share/dynamixel_sdk
$(CP_ALL) $(DIR_DXL)/../control_table $(INSTALL_ROOT)/share/dynamixel_sdk/

$(LD_CONFIG)

uninstall:
Expand All @@ -99,6 +113,8 @@ uninstall:

$(RM) $(INSTALL_ROOT)/include/dynamixel_sdk/dynamixel_sdk.h
$(RM_ALL) $(INSTALL_ROOT)/include/dynamixel_sdk/*
$(RM_ALL) $(INSTALL_ROOT)/include/dynamixel_easy_sdk/*
$(RM_ALL) $(INSTALL_ROOT)/share/dynamixel_sdk/control_table

reinstall: uninstall install

Expand All @@ -119,6 +135,9 @@ $(DIR_OBJS)/%.o: $(DIR_DXL)/src/dynamixel_sdk/%.c
$(DIR_OBJS)/%.o: $(DIR_DXL)/src/dynamixel_sdk/%.cpp
$(CX) $(CXFLAGS) -c $? -o $@

$(DIR_OBJS)/%.o: $(DIR_DXL)/src/dynamixel_easy_sdk/%.cpp
$(CX) $(CXFLAGS) -c $? -o $@

#---------------------------------------------------------------------
# END OF MAKEFILE
#---------------------------------------------------------------------
62 changes: 62 additions & 0 deletions c++/include/dynamixel_easy_sdk/connector.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2025 ROBOTIS CO., LTD.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Hyungyu Kim

#ifndef DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_CONNECTOR_HPP_
#define DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_CONNECTOR_HPP_

#include <memory>
#include <string>
#include <vector>

#include "dynamixel_sdk/dynamixel_sdk.h"
#include "dynamixel_easy_sdk/dynamixel_error.hpp"
#include "dynamixel_easy_sdk/motor.hpp"
#include "dynamixel_easy_sdk/group_executor.hpp"

namespace dynamixel
{
class Connector
{
public:
Connector(const std::string & port_name, int baud_rate);

virtual ~Connector();

std::unique_ptr<Motor> createMotor(uint8_t id);
std::vector<std::unique_ptr<Motor>> createAllMotors(int start_id = 0, int end_id = 252);
std::unique_ptr<GroupExecutor> createGroupExecutor();

Result<void, DxlError> write1ByteData(uint8_t id, uint16_t address, uint8_t value);
Result<void, DxlError> write2ByteData(uint8_t id, uint16_t address, uint16_t value);
Result<void, DxlError> write4ByteData(uint8_t id, uint16_t address, uint32_t value);

Result<uint8_t, DxlError> read1ByteData(uint8_t id, uint16_t address);
Result<uint16_t, DxlError> read2ByteData(uint8_t id, uint16_t address);
Result<uint32_t, DxlError> read4ByteData(uint8_t id, uint16_t address);

Result<void, DxlError> reboot(uint8_t id);
Result<uint16_t, DxlError> ping(uint8_t id);
Result<void, DxlError> factoryReset(uint8_t id, uint8_t option);

PortHandler * getPortHandler() const {return port_handler_.get();}
PacketHandler * getPacketHandler() const {return packet_handler_;}

private:
std::unique_ptr<PortHandler> port_handler_;
PacketHandler * packet_handler_;
};
} // namespace dynamixel
#endif /* DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_CONNECTOR_HPP_ */
45 changes: 45 additions & 0 deletions c++/include/dynamixel_easy_sdk/control_table.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2025 ROBOTIS CO., LTD.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Hyungyu Kim

#ifndef DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_CONTROL_TABLE_HPP_
#define DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_CONTROL_TABLE_HPP_

#include <cstdint>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>

#include "dynamixel_easy_sdk/dynamixel_error.hpp"

namespace dynamixel
{
struct ControlTableItem
{
uint16_t address;
uint8_t size;
};

class ControlTable
{
public:
static const std::map<uint16_t, std::string> ParsingModelList();
static const std::string getModelName(uint16_t model_number);
static const std::map<std::string, ControlTableItem> & getControlTable(uint16_t model_number);
};
} // namespace dynamixel
#endif /* DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_CONTROL_TABLE_HPP_ */
26 changes: 26 additions & 0 deletions c++/include/dynamixel_easy_sdk/dynamixel_easy_sdk.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2025 ROBOTIS CO., LTD.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Hyungyu Kim

#ifndef DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_DYNAMIXEL_EASY_SDK_HPP_
#define DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_DYNAMIXEL_EASY_SDK_HPP_


#include "dynamixel_easy_sdk/connector.hpp"
#include "dynamixel_easy_sdk/dynamixel_error.hpp"
#include "dynamixel_easy_sdk/motor.hpp"
#include "dynamixel_easy_sdk/group_executor.hpp"

#endif /* DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_DYNAMIXEL_EASY_SDK_HPP_ */
145 changes: 145 additions & 0 deletions c++/include/dynamixel_easy_sdk/dynamixel_error.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright 2025 ROBOTIS CO., LTD.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: Hyungyu Kim

#ifndef DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_DYNAMIXEL_ERROR_HPP_
#define DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_DYNAMIXEL_ERROR_HPP_

#include <variant>
#include <stdexcept>
#include <string>

namespace dynamixel
{
enum class DxlError
{
SDK_COMM_SUCCESS = 0, // tx or rx packet communication success
SDK_COMM_PORT_BUSY = -1000, // Port is busy (in use)
SDK_COMM_TX_FAIL = -1001, // Failed transmit instruction packet
SDK_COMM_RX_FAIL = -1002, // Failed get status packet
SDK_COMM_TX_ERROR = -2000, // Incorrect instruction packet
SDK_COMM_RX_WAITING = -3000, // Now receiving status packet
SDK_COMM_RX_TIMEOUT = -3001, // There is no status packet
SDK_COMM_RX_CORRUPT = -3002, // Incorrect status packet
SDK_COMM_NOT_AVAILABLE = -9000,
SDK_ERRNUM_RESULT_FAIL = 1, // Failed to process the instruction packet.
SDK_ERRNUM_INSTRUCTION = 2, // Instruction error
SDK_ERRNUM_CRC = 3, // CRC check error
SDK_ERRNUM_DATA_RANGE = 4, // Data range error
SDK_ERRNUM_DATA_LENGTH = 5, // Data length error
SDK_ERRNUM_DATA_LIMIT = 6, // Data limit error
SDK_ERRNUM_ACCESS = 7, // Access error
EASY_SDK_FUNCTION_NOT_SUPPORTED = 11, // API does not support this function
EASY_SDK_MOTOR_TORQUE_OFF = 12, // Motor torque is off
EASY_SDK_OPERATING_MODE_MISMATCH = 13, // Operating mode is not appropriate for this function
EASY_SDK_ADD_PARAM_FAIL = 21, // Failed to add parameter
EASY_SDK_COMMAND_IS_EMPTY = 22, // No command to execute
EASY_SDK_DUPLICATE_ID = 23, // Duplicate ID in staged commands
EASY_SDK_FAIL_TO_GET_DATA = 24 // Failed to get data from motor
};

template<typename T, typename E>
class Result
{
private:
std::variant<T, E> result;

public:
Result() = default;
Result(const T & return_value)
: result(return_value)
{}

Result(const E & error)
: result(error)
{}

bool isSuccess() const
{
return std::holds_alternative<T>(result);
}

T & value()
{
if (!isSuccess()) {throw std::logic_error("Result has no value.");}
return std::get<T>(result);
}
const T & value() const
{
if (!isSuccess()) {throw std::logic_error("Result has no value.");}
return std::get<T>(result);
}

E & error()
{
if (isSuccess()) {throw std::logic_error("Result has no error.");}
return std::get<E>(result);
}

const E & error() const
{
if (isSuccess()) {throw std::logic_error("Result has no error.");}
return std::get<E>(result);
}
};

template<typename E>
class Result<void, E>
{
private:
std::variant<std::monostate, E> result;

public:
Result()
: result(std::monostate{})
{}

Result(const E & error)
: result(error)
{}

bool isSuccess() const
{
return std::holds_alternative<std::monostate>(result);
}

E & error()
{
if (!std::holds_alternative<E>(result)) {
throw std::logic_error("Result has no error.");
}
return std::get<E>(result);
}

const E & error() const
{
if (!std::holds_alternative<E>(result)) {
throw std::logic_error("Result has no error.");
}
return std::get<E>(result);
}
};

class DxlRuntimeError : public std::runtime_error
{
public:
explicit DxlRuntimeError(const std::string & message)
: std::runtime_error(message) {}
};

std::string getErrorMessage(DxlError error_code);
} // namespace dynamixel

#endif /* DYNAMIXEL_SDK_INCLUDE_DYNAMIXEL_EASY_SDK_DYNAMIXEL_ERROR_HPP_ */
Loading