Giới thiệu định dạng mô tả robot URDF
URDF (Unified Robot Description Format) là chuẩn mã hoá XML dùng để khai báo cấu trúc hình học, khối lượng và mối liên kết động học giữa các thành phần cơ khí của robot. Thay vì vẽ thủ công, kỹ sư sử dụng văn bản cấu trúc để định nghĩa từng khối rigid body và cách chúng tương tác với nhau thông qua khớp nối.
Cấu trúc tệp tin cơ bản
<?xml version="1.0" encoding="utf-8"?>
<!-- Định nghĩa root element chứa toàn bộ mô hình -->
<robot name="tên_mô_hình">
<!-- Nội dung LINK và JOINT sẽ nằm ở đây -->
</robot>
Thành phần xây dựng chính
- LINK (Thanh liên kết): Đại diện cho một khối vật thể rắn cố định hoặc chuyển động. Mỗi LINK sở hữu hệ toạ độ riêng, có thể kèm theo dữ liệu hình học phục vụ hiển thị (visual), tính toán va chạm (collision) và tham số quán tính (inertial).
- JOINT (Khớp nối): Đóng vai trò như bản lề hoặc thanh trượt, kết nối hai LINK lại với nhau. JOINT quy định phương thức chuyển động tương đối (xoay hay tịnh tiến), trục quay, giới hạn góc/quãng đường và vị trí xuất phát.
Thẻ con của LINK
<visual>: Định nghĩa bề ngoài hiển thị trên màn hình bao gồm:<geometry>: Khối hình học cơ bản như<box>,<cylinder>,<sphere>hoặc file<mesh>(dạng .DAE, .STL).<origin>: Xác định tâm hình học so với gốc LINK (xyz) và hướng xoay Euler (rpytính bằng radian).<material>: Thuộc tính màu sắc, ánh sáng thông qua mã RGBA (Alpha đại diện cho độ trong suốt).
<collision>và<inertial>: Thường được tối ưu hoá riêng cho bước mô phỏng động lực học để giảm tải tính toán.
Định nghĩa JOINT
Thuộc tính type quyết định đặc tính khớp:
revolute: Khớp quay tròn một trục, có giới hạn góc tối thiểu/tối đa.continuous: Khớp quay vô hạn (ví dụ bánh xe).fixed: Khớp dính cố định, không có chuyển động tương đối.prismatic: Khớp trượt tuyến tính dọc một trục.planar / floating: Cho phép tự do di chuyển phẳng hoặc 6 bậc tự do.
Chi nhánh con quan trọng gồm parent (khớp gốc), child (khớp đầu), origin (vị trí tương đối) và axis (trục quay đơn vị).
Minh họa mã nguồn URDF
<?xml version="1.0" encoding="utf-8"?>
<robot name="demo_robot">
<!-- Khối thân xe chính -->
<link name="chassis">
<visual>
<origin xyz="0 0 0.06" rpy="0 0 0"/>
<geometry>
<cylinder length="0.15" radius="0.12"/>
</geometry>
<material name="silver">
<color rgba="0.7 0.7 0.8 1.0" />
</material>
</visual>
</link>
<!-- Khối gắn cảm biến phía trên -->
<link name="sensor_mount">
<visual>
<origin xyz="0 0 0" rpy="0 0 0"/>
<geometry>
<box size="0.04 0.04 0.02"/>
</geometry>
<material name="dark_gray">
<color rgba="0.2 0.2 0.2 1.0" />
</material>
</visual>
</link>
<!-- Kết nối cố định giữa hai khối -->
<joint name="body_connect" type="fixed">
<parent link="chassis"/>
<child link="sensor_mount"/>
<origin xyz="0 0 0.085" rpy="0 0 0"/>
</joint>
</robot>
Cài đặt không gian làm việc ROS 2
Chuẩn bị môi trường module hóa bằng lệnh terminal:
# Tạo thư mục workspace và vào src
mkdir -p demo_ws/src
cd demo_ws/src
# Khởi tạo package mô tả robot (dùng ament_python)
ros2 pkg create demo_robot_description --build-type ament_python
Chuẩn bị thư mục dự án
Sắp xếp cây thư mục bên trong package vừa tạo để giữ tính ngăn nắp:
├── demo_robot_description
│ ├── __init__.py
│ └── urdf
│ └── robot_model.urdf
Dán đoạn mã XML ở phần trước vào tệp robot_model.urdf.
Xây dựng kịch bản khởi động (Launch)
Tạo thư mục launch/ và file run_viewer.launch.py. Kịch bản này sẽ khởi tạo ba node nền tảng:
import os
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import Command, LaunchConfiguration
from launch_ros.actions import Node
from launch_ros.parameter_descriptions import ParameterValue
from launch_ros.substitutions import FindPackageShare
def generate_launch_description():
pkg_name = "demo_robot_description"
urdf_file = "robot_model.urdf"
pkg_share = FindPackageShare(package=pkg_name).find(pkg_name)
urdf_path = os.path.join(pkg_share, 'urdf', urdf_file)
# Đọc raw content từ file urdf thay vì tham chiếu path
with open(urdf_path, 'r') as inf:
robot_content = inf.read()
ld = LaunchDescription()
# Node quản lý trạng thái khớp (hiển thị GUI kéo trượt)
pub_joint_state = Node(
package='joint_state_publisher_gui',
executable='joint_state_publisher_gui',
name='state_controller'
)
# Node phát hành mô hình robot lên topic /robot_description và broadcast TF
pub_robot_state = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
name='state_publisher',
parameters=[{
'robot_description': ParameterValue(robot_content, value_type=str)
}]
)
# Node mở cửa sổ RViz2
viewer_rviz = Node(
package='rviz2',
executable='rviz2',
name='visualization_ui',
output='screen'
)
ld.add_action(pub_joint_state)
ld.add_action(pub_robot_state)
ld.add_action(viewer_rviz)
return ld
Lưu ý: joint_state_publisher_gui cung cấp giao diện kéo thả để kiểm tra khớp động, khác với phiên bản joint_state_publisher chỉ publish dữ liệu tĩnh. Đảm bảo đã cài gói ros-$ROS_DISTRO-joint-state-publisher-gui.
Cập nhật cấu hình gói Python
Chỉnh sửa setup.py để trỏ đúng đường dẫn resource khi đóng gói:
from setuptools import setup
from glob import glob
import os
package_name = 'demo_robot_description'
setup(
name=package_name,
version='1.0.0',
packages=[package_name],
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/*.launch.py')),
(os.path.join('share', package_name, 'urdf'), glob('urdf/*')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='developer',
maintainer_email='dev@example.com',
description='Gói mô tả hình học robot demo',
license='MIT',
tests_require=[],
entry_points={'console_scripts': []},
)
Biên dịch và kiểm thử giao diện hiển thị
Quay ra thư mục gốc workspace, compile và trigger:
colcon build
source install/setup.bash
ros2 launch demo_robot_description run_viewer.launch.py
Khi RViz2 bật lên, thực hiện các bước định hướng view:
- Vào menu Global Options, gán
Fixed Framethành tên gốc của robot (ví dụ:chassis). - Hiệu chỉnh
Grid Reference Frametrùng với khung tham chiếu trên. - Mở panel Add New → tìm và thêm module
RobotModel. - Trong thuộc tính RobotModel, đổi
Robot Descriptiontopic sang/robot_description.
Kích hoạt xong, bạn sẽ thấy khối cylinder màu bạc và hộp nhỏ phía trên được render chính xác theo tỷ lệ.URDF cũng cho phép broadcast hệ toạ độ (TF tree) động, giúp dễ dàng kiểm tra sự lệch trục hoặc khoảng cách giữa các liên kết khi tinh chỉnh giá trị origin.