Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
3 changes: 2 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ RUN mkdir -p ${COLCON_WS}/src && \
git clone -b jazzy https://github.com/ROBOTIS-GIT/dynamixel_hardware_interface.git && \
git clone -b jazzy https://github.com/ROBOTIS-GIT/dynamixel_interfaces.git && \
git clone -b jazzy https://github.com/ROBOTIS-GIT/DynamixelSDK.git && \
git clone -b jazzy https://github.com/ROBOTIS-GIT/dynamixel_hardware_interface_demos.git
git clone -b jazzy https://github.com/ROBOTIS-GIT/dynamixel_hardware_interface_demos.git && \
git clone -b jazzy https://github.com/ros2/rmw_zenoh.git

RUN cd ${COLCON_WS} && \
apt-get update && \
Expand Down
4 changes: 4 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ services:
rttime: -1
memlock: 8428281856
network_mode: host
ipc: host
pid: host
environment:
- DISPLAY=${DISPLAY}
- QT_X11_NO_MITSHM=1
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commented-out RMW_IMPLEMENTATION environment variable lacks documentation explaining when or why a user should uncomment it. Consider adding a comment above this line explaining the purpose and usage of rmw_zenoh.

Suggested change
- QT_X11_NO_MITSHM=1
- QT_X11_NO_MITSHM=1
# Uncomment the line below to use the Zenoh-based ROS 2 RMW implementation (rmw_zenoh_cpp)
# instead of the default middleware, if rmw_zenoh_cpp is installed in the image.

Copilot uses AI. Check for mistakes.
# - RMW_IMPLEMENTATION=rmw_zenoh_cpp
volumes:
- /dev:/dev
- /dev/shm:/dev/shm
- ./workspace:/workspace
- /tmp/.X11-unix:/tmp/.X11-unix:rw
- /tmp/.docker.xauth:/tmp/.docker.xauth:rw
Expand Down
5 changes: 5 additions & 0 deletions dynamixel_hardware_interface_demos/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Changelog for package dynamixel_hardware_interface_demos
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.0.4 (2025-12-15)
------------------
* Introduced dynamixel_hardware_interface_example_2 package for using the dynamixel_hardware_interface with imu sensor
* Contributors: Woojin Wie

0.0.3 (2025-09-12)
------------------
* Updated package.xml to include dynamixel_hardware_interface_example_1
Expand Down
1 change: 1 addition & 0 deletions dynamixel_hardware_interface_demos/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<buildtool_depend>ament_cmake</buildtool_depend>
<exec_depend>dynamixel_hardware_interface_example</exec_depend>
<exec_depend>dynamixel_hardware_interface_example_1</exec_depend>
<exec_depend>dynamixel_hardware_interface_example_2</exec_depend>
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The package.xml version is 0.0.3, but the CHANGELOG indicates this is version 0.0.4. The package version should be updated to 0.0.4 to match the changelog entry and the new functionality being added.

Copilot uses AI. Check for mistakes.
<export>
<build_type>ament_cmake</build_type>
</export>
Expand Down
4 changes: 4 additions & 0 deletions dynamixel_hardware_interface_example/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Changelog for package dynamixel_hardware_interface_example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.0.4 (2025-12-15)
------------------
* None

0.0.3 (2025-09-12)
------------------
* Introduced xacro arguments for port_name and baud_rate
Expand Down
2 changes: 1 addition & 1 deletion dynamixel_hardware_interface_example/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name=package_name,
version='0.0.3',
version='0.0.4',
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version in setup.py has been updated to 0.0.4, but the corresponding package.xml file still has version 0.0.3. These versions should be synchronized to avoid confusion during package distribution and dependency resolution.

Suggested change
version='0.0.4',
version='0.0.3',

Copilot uses AI. Check for mistakes.
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages', ['resource/' + package_name]),
Expand Down
4 changes: 4 additions & 0 deletions dynamixel_hardware_interface_example_1/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Changelog for package dynamixel_hardware_interface_example_1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.0.4 (2025-12-15)
------------------
* None

0.0.3 (2025-09-12)
------------------
* Introduced dynamixel_hardware_interface_example_1 package for dual ros2_control
Expand Down
2 changes: 1 addition & 1 deletion dynamixel_hardware_interface_example_1/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name=package_name,
version='0.0.3',
version='0.0.4',
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version in setup.py has been updated to 0.0.4, but the corresponding package.xml file still has version 0.0.3. These versions should be synchronized to avoid confusion during package distribution and dependency resolution.

Suggested change
version='0.0.4',
version='0.0.3',

Copilot uses AI. Check for mistakes.
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages', ['resource/' + package_name]),
Expand Down
8 changes: 8 additions & 0 deletions dynamixel_hardware_interface_example_2/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package dynamixel_hardware_interface_example_2
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.0.4 (2025-12-15)
------------------
* Added example package for using the dynamixel_hardware_interface with imu sensor
* Contributors: Woojin Wie
19 changes: 19 additions & 0 deletions dynamixel_hardware_interface_example_2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Dynamixel Hardware Interface Example 2 (IMU ros2_control)

This example shows a single `ros2_control` system that uses `dynamixel_hardware_interface` to read an IMU (ID 1) and publish its data through an `imu_sensor_broadcaster`. The robot description is built from `config/dynamixel_system.urdf.xacro`, which wraps the ros2_control configuration defined in `config/dynamixel_system.ros2_control.xacro`.

## Usage

Build and source your workspace, then launch:

```bash
ros2 launch dynamixel_hardware_interface_example_2 hardware.launch.py \
port_name:=/dev/ttyUSB0 \
baud_rate:=4000000
```

### Launch arguments
- `port_name` (default `/dev/ttyUSB0`): Serial port connected to the Dynamixel IMU.
- `baud_rate` (default `4000000`): Baud rate for the port.
- `description_file` (default `dynamixel_system.urdf.xacro`): Xacro to generate the robot description.
- `prefix` (default empty): Optional prefix for joint/frame names.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="dynamixel_system_ros2_control" params="name port_name baud_rate">
<ros2_control name="${name}" type="system">
<hardware>
<plugin>dynamixel_hardware_interface/DynamixelHardware</plugin>
<param name="port_name">${port_name}</param>
<param name="baud_rate">${baud_rate}</param>
<param name="dynamixel_model_folder">/param/dxl_model</param>
<param name="number_of_joints">0</param>
<param name="number_of_transmissions">0</param>
<param name="disable_torque_at_init">true</param>
<param name="error_timeout_ms">1000</param>
<param name="dynamixel_state_pub_msg_name">dynamixel_hardware_interface/dxl_state</param>
<param name="get_dynamixel_data_srv_name">dynamixel_hardware_interface/get_dxl_data</param>
<param name="set_dynamixel_data_srv_name">dynamixel_hardware_interface/set_dxl_data</param>
<param name="reboot_dxl_srv_name">dynamixel_hardware_interface/reboot_dxl</param>
<param name="set_dxl_torque_srv_name">dynamixel_hardware_interface/set_dxl_torque</param>
</hardware>

<sensor name="imu">
<state_interface name="linear_acceleration.x"/>
<state_interface name="linear_acceleration.y"/>
<state_interface name="linear_acceleration.z"/>
<state_interface name="angular_velocity.x"/>
<state_interface name="angular_velocity.y"/>
<state_interface name="angular_velocity.z"/>
<state_interface name="orientation.w"/>
<state_interface name="orientation.x"/>
<state_interface name="orientation.y"/>
<state_interface name="orientation.z"/>
</sensor>

<gpio name="imu">
<param name="type">sensor</param>
<param name="ID">1</param>
<state_interface name="linear_acceleration.x"/>
<state_interface name="linear_acceleration.y"/>
<state_interface name="linear_acceleration.z"/>
<state_interface name="angular_velocity.x"/>
<state_interface name="angular_velocity.y"/>
<state_interface name="angular_velocity.z"/>
<state_interface name="orientation.w"/>
<state_interface name="orientation.x"/>
<state_interface name="orientation.y"/>
<state_interface name="orientation.z"/>
<param name="Return Delay Time">0</param>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The parameter name Return Delay Time contains spaces, which is unconventional for ROS parameters. The standard convention is to use snake_case (e.g., return_delay_time). If the dynamixel_hardware_interface plugin supports it, please consider renaming this parameter for consistency and improved maintainability.

</gpio>
</ros2_control>
</xacro:macro>
</robot>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="dynamixel_system">
<xacro:arg name="prefix" default="" />
<xacro:arg name="baud_rate" default="4000000" />
<xacro:arg name="port_name" default="/dev/ttyUSB0" />
<xacro:include filename="dynamixel_system.ros2_control.xacro" />

<xacro:dynamixel_system_ros2_control name="dynamixel_system" port_name="$(arg port_name)" baud_rate="$(arg baud_rate)"/>

<link name="$(arg prefix)base_link"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

To resolve the missing imu_link TF frame required by ros2_controllers.yaml, you need to define the link and a joint connecting it to the robot's structure, for example, base_link.


  <link name="$(arg prefix)imu_link"/>

  <joint name="imu_joint" type="fixed">
    <parent link="$(arg prefix)base_link"/>
    <child link="$(arg prefix)imu_link"/>
    <origin xyz="0 0 0.1" rpy="0 0 0"/>
  </joint>

</robot>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**:
controller_manager:
ros__parameters:
update_rate: 500 # Hz

joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster

imu_sensor_broadcaster:
type: imu_sensor_broadcaster/IMUSensorBroadcaster

/**:
imu_sensor_broadcaster:
ros__parameters:
sensor_name: "imu"
frame_id: imu_link
Comment on lines +1 to +16

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This YAML file is invalid because the /**: key is duplicated. YAML does not allow duplicate keys at the same level, which will cause parsing errors. Please structure the parameters under their respective node and controller names.

controller_manager:
  ros__parameters:
    update_rate: 500  # Hz

    joint_state_broadcaster:
      type: joint_state_broadcaster/JointStateBroadcaster

    imu_sensor_broadcaster:
      type: imu_sensor_broadcaster/IMUSensorBroadcaster

imu_sensor_broadcaster:
  ros__parameters:
    sensor_name: "imu"
    frame_id: imu_link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The frame_id is set to imu_link, but this link is not defined in the dynamixel_system.urdf.xacro file. This will lead to TF (Transform) errors at runtime because the transform for imu_link will not be published. Please add the imu_link and a corresponding joint to your URDF.

132 changes: 132 additions & 0 deletions dynamixel_hardware_interface_example_2/launch/hardware.launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env python3
#
# 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: Woojin Wie


from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import Command, FindExecutable, LaunchConfiguration, PathJoinSubstitution

from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare


def generate_launch_description():
# Declare arguments
declared_arguments = []

declared_arguments.append(
DeclareLaunchArgument(
'prefix',
default_value='""',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The default value for the prefix argument is "", which is a string containing two double quotes. This will result in link names like ""base_link. To specify an empty prefix by default, the value should be an empty string ''.

Suggested change
default_value='""',
default_value='',

description='Prefix of the joint names'
)
)

declared_arguments.append(
DeclareLaunchArgument(
'description_file',
default_value='dynamixel_system.urdf.xacro',
description='URDF/XACRO description file with the robot.',
)
)

declared_arguments.append(
DeclareLaunchArgument(
'port_name',
default_value='/dev/ttyUSB0',
description='Port name for the Dynamixel device.',
)
)

declared_arguments.append(
DeclareLaunchArgument(
'baud_rate',
default_value='4000000',
description='Baudrate for the Dynamixel port.',
)
)

description_file = LaunchConfiguration('description_file')
prefix = LaunchConfiguration('prefix')
port_name = LaunchConfiguration('port_name')
baud_rate = LaunchConfiguration('baud_rate')

robot_controllers = PathJoinSubstitution(
[
FindPackageShare('dynamixel_hardware_interface_example_2'),
'config',
'ros2_controllers.yaml',
]
)

control_node = Node(
package='controller_manager',
executable='ros2_control_node',
parameters=[robot_controllers],
output='both',
)

robot_description_content = Command(
[
PathJoinSubstitution([FindExecutable(name='xacro')]),
' ',
PathJoinSubstitution(
[
FindPackageShare('dynamixel_hardware_interface_example_2'),
'config',
description_file,
]
),
' ',
'prefix:=',
prefix,
' ',
'port_name:=',
port_name,
' ',
'baud_rate:=',
baud_rate,
]
)

robot_description = {'robot_description': robot_description_content}

robot_controller_spawner = Node(
package='controller_manager',
executable='spawner',
arguments=[
'joint_state_broadcaster',
'imu_sensor_broadcaster',
],
parameters=[robot_description],
)

robot_state_publisher_node = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
output='both',
parameters=[robot_description],
)

nodes = [
control_node,
robot_controller_spawner,
robot_state_publisher_node,
]

return LaunchDescription(declared_arguments + nodes)
26 changes: 26 additions & 0 deletions dynamixel_hardware_interface_example_2/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>dynamixel_hardware_interface_example_2</name>
<version>0.0.4</version>
<description>
Example package with configuration and launch files for using the dynamixel_hardware_interface.
</description>
<maintainer email="[email protected]">Pyo</maintainer>
<license>Apache 2.0</license>
<author email="[email protected]">Woojin Wie</author>

<exec_depend>joint_state_publisher</exec_depend>
<exec_depend>controller_manager</exec_depend>
<exec_depend>dynamixel_hardware_interface</exec_depend>
<exec_depend>robot_state_publisher</exec_depend>
<exec_depend>xacro</exec_depend>
<exec_depend>joint_state_broadcaster</exec_depend>
<exec_depend>imu_sensor_broadcaster</exec_depend>
<exec_depend>rviz2</exec_depend>
<exec_depend>rviz_imu_plugin</exec_depend>

<export>
<build_type>ament_python</build_type>
</export>
</package>
4 changes: 4 additions & 0 deletions dynamixel_hardware_interface_example_2/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[develop]
script_dir=$base/lib/dynamixel_hardware_interface_example_2
[install]
install_scripts=$base/lib/dynamixel_hardware_interface_example_2
29 changes: 29 additions & 0 deletions dynamixel_hardware_interface_example_2/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from glob import glob
import os

from setuptools import find_packages
from setuptools import setup

package_name = 'dynamixel_hardware_interface_example_2'

setup(
name=package_name,
version='0.0.3',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The package version here is '0.0.3', which is inconsistent with the version '0.0.4' specified in package.xml and CHANGELOG.rst. Please align the versions to ensure correct packaging and dependency resolution.

Suggested change
version='0.0.3',
version='0.0.4',

Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version in setup.py (0.0.3) does not match the version in package.xml (0.0.4). These versions should be synchronized to avoid confusion during package distribution and dependency resolution.

Suggested change
version='0.0.3',
version='0.0.4',

Copilot uses AI. Check for mistakes.
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages', ['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name, 'launch'), glob('launch/*.py')),
(os.path.join('share', package_name, 'config'), glob('config/*')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='Pyo',
maintainer_email='[email protected]',
description='Dynamixel Hardware Interface Example (imu sensor) ROS 2 package.',
license='Apache 2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [],
},
)
Loading