Skip to main content

Command Palette

Search for a command to run...

11. Mô Phỏng Robot trong ROS - Phần 2

Updated
9 min read
11. Mô Phỏng Robot trong ROS - Phần 2

Hãy cùng tiếp tục chương trước bằng việc dùng Xacro để cải tiến mô tả robot (URDF) và thêm nhiều thuộc tính hơn để mô phỏng và điều khiển robot trong Gazebo. Code ở phần này nhìn có vẻ dài dòng (vì XML luôn yêu cầu các thẻ mở và đóng) nhưng thực ra rất dễ hiểu.

Xacro là gì?

Trong phần trước, chúng ta đã tạo một URDF để mô tả tất cả các liên kết và khớp nối của một robot di động. Tuy nhiên, bạn có thể nhận thấy một số điểm dư thừa trong URDF này, ví dụ: 4 bánh xe có các thành phần gần như giống hệt nhau (ngoại trừ tên và vị trí). Đối với một robot phức tạp hơn, sẽ có nhiều thành phần lặp đi lặp lại hơn nữa và sẽ khiến URDF trở nên cồng kềnh và khó bảo trì. Đó là lý do tại sao Xacro ra đời. Xacro là viết tắt của XML Macro cho phép bạn sử dụng macro trong URDF để tăng tính mô đun và giảm những đoạn mã thừa. Lưu ý rằng Xacro không phải là một giải pháp thay thế cho URDF mà chỉ là một cách viết khác vì cuối cùng, Xacro sẽ được (tự động) chuyển đổi thành URDF trong khi được sử dụng.

Để hiểu cú pháp Xacro, hãy tạo một tệp mô tả mới trong thư mục urdf và đặt tên là mobile_robot.urdf.xacro. Toàn bộ tập tin nằm ở đây và sau đây là giải thích cho các phần chính. Hai dòng đầu tiên tương tự như mobile_robot.urdf, ngoại trừ trong thẻ robot, có dòng xmlns:xacro="http://www.ros.org/wiki/xacro" dùng để định nghĩa không gian tên (namespace) XML cho tệp để có thể đọc được các thẻ (tag) đúng cách.

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="mobile_robot">

Có ba đặc tính chúng ta có thể sử dụng với Xacro: property, math, and macro.

Xacro Property

Trong xacro, bạn có thể định nghĩa một hằng số làm một property (thuộc tính) và dùng nó khi nào cần. Ví dụ: trong đoạn mã bên dưới, ba thuộc tính có tên: chiều cao, chiều rộng và chiều sâu (height, width, depth) được tạo với các giá trị lần lượt là 0.4, 0.4 và 0.1 (mét). Sau đó, chúng được sử dụng trong cả thẻ visual và thẻ collision trong liên kết (link) chassis. Để sử dụng property chỉ cần đặt nó vào trong dấu đô la và dấu ngoặc nhọn, ví dụ: <box size="${height} ${width} ${depth}"/>. visualcollision là gì sẽ được giải thích ở bên dưới.

<xacro:property name="height" value="0.4" /> <!-- [m] -->
<xacro:property name="width" value="0.4" /> <!-- [m] -->
<xacro:property name="depth" value="0.1" /> <!-- [m] -->

<!--Chassis-->
<link name="chassis">
  <visual>
    <geometry>
      <box size="${height} ${width} ${depth}"/>
    </geometry>
  </visual>
  <collision>
    <geometry>
      <box size="${height} ${width} ${depth}"/>
    </geometry>
  </collision>
  <inertial>
    <mass value="1.0"/> <!-- [kg] -->
    <inertia ixx="0.014167" ixy="0.0" ixz="0.0" iyy="0.026667" iyz="0.0" izz="0.014167"/>
  </inertial>
</link>

Xacro Macro và Math

Bây giờ đến các bánh xe. Chúng ta đã tạo 4 mô tả riêng cho 4 bánh xe trong URDF từ chương trước, nhưng bây giờ chỉ cần dùng 1 macro để mô tả một bánh xe chung và sau đó sử dụng các tham số để định nghĩa 4 bánh xe sau trong 4 dòng. Bạn có thể coi việc viết macro giống như tạo một hàm với các đối số.

<xacro:property name="wheel_height" value="0.04" /> <!-- [m] -->
<xacro:property name="wheel_radius" value="0.06" /> <!-- [m] -->

<!-- Wheel macro-->
<xacro:macro name="wheel" params="name reflect_x reflect_y reflect_r reflect_axis">

  <!-- Wheel link -->
  <link name="${name}_wheel">
    <visual>
      <geometry>
        <cylinder length="${wheel_height}" radius="${wheel_radius}"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <collision>
      <geometry>
        <cylinder length="${wheel_height}" radius="${wheel_radius}"/>
      </geometry>
    </collision>
    <inertial>
      <mass value="0.3"/>  <!-- [kg] -->
      <inertia ixx="0.00031" ixy="0.0" ixz="0.0" iyy="0.00031" iyz="0.0" izz="0.00054"/>
    </inertial>
  </link>

  <!-- Wheel joint -->
  <joint name="${name}_wheel_joint" type="continuous">
    <parent link="chassis"/>
    <child link="${name}_wheel"/>
    <origin xyz="${reflect_x*height/2} ${reflect_y*(width/2+0.025)} 0" rpy="${reflect_r*1.5707} 0 0"/>
    <axis xyz="0 0 ${reflect_axis}"/>
  </joint>
</xacro:macro>

Trong đoạn code trên, macro bánh xe (wheel) được định nghĩa với với 5 đối số: name, reflect_x, reflect_y, reflect_r,reflect_axis. name được sử dụng cho tên của liên kết và khớp. reflect_x, reflect_y, reflect_r,reflect_axis được dùng cho vị trí của các khớp. Trong phần định nghĩa khớp nối (joint), bạn có thể thấy các phép toán cơ bản (cộng, trừ, nhân, chia) cũng có thể được sử dụng trong xacro, ví dụ: <origin xyz="${reflect_x*height/2} ${reflect_y*(width/2+0.025)} 0" rpy="${reflect_r*1.5707} 0 0"/>.

Khi đã có macro bánh xe này, việc khởi tạo các bánh xe rất đơn giản. Bên dưới là định nghĩa (trong 1 dòng duy nhất) của bánh xe đằng trước bên phải. Bạn có thể kiểm tra xem mô tả này có khớp với URDF cũ hay không bằng cách thay thế các đối số tương ứng trong xacro ở trên bằng các giá trị ở bên dưới. Và hãy tự thử thêm ba bánh còn lại nhé!

<xacro:wheel name="front_right" reflect_x="1" reflect_y="-1" reflect_r="1" reflect_axis="-1"/>

Những Thuộc Tính Va Chạm và Vật Lý

Những gì chúng ta làm cho đến nay là để mô tả các đặc điểm trực quan của robot, nghĩa là việc nó trông như thế nào. Tuy nhiên, để cho phép phát hiện va chạm và mô phỏng robot trong Gazebo một cách thực tế hơn, chúng ta cần thêm các thuộc tính khác.

Collision (Va Chạm)

Bạn có thể đã thấy các thẻ collision trong các liên kết chassiswheel. Các thuộc tính của collision là (trích dẫn trực tiếp từ ROS wiki):

  • collision là phần tử con trực tiếp của link, ở cùng cấp độ với thẻ visual.

  • Hình dạng (shape) của collision được định nghĩa bằng thẻ geometry giống như cách thực hiện trong thẻ visual.

Ở đây, các collision có dạng hình học (geometry) giống hệt như các link. Điều này đúng trong nhiều trường hợp nhưng nếu robot của bạn có các hình dạng phức tạp hơn hoặc nếu bạn muốn thể tích của collision to hơn để đảm bảo an toàn thì chúng phải được điều chỉnh cho phù hợp.

Các Thuộc Tính Vật Lý

Trong các nền tảng mô phỏng 3D như Gazebo sẽ luôn có các công cụ (gọi là physical engine) để mô phỏng các đặc tính vật lý trong thế giới thực như trọng lực, ma sát, độ cứng, v.v. Do đó, chúng ta cũng cần thêm một số thuộc tính vật lý quan trọng vào URDF của mình. Một trong số đó là quán tính. Mọi phần tử liên kết được mô phỏng đều cần một thẻ quán tính mà bạn có thể thấy trong các link khung (chassis) và bánh xe (wheel) ở trên. Nó là một thành phần con của thẻ link và cung cấp hai thông tin: mass, khối lượng (tính bằng kilôgam) và inertia, mômen quán tính. Dành cho những bạn chưa biết "Momen quán tính, ký hiệu là I, là một đại lượng vật lý đặc trưng cho mức quán tính của các vật thể trong chuyển động quay, tương tự như khối lượng trong chuyển động thẳng" (nguồn).

inertia được xác định bởi một ma trận 3x3 nhưng ma trận đối xứng nên nó có thể được biểu diễn bằng 6 phần tử (in đậm).

moment-of-inertia.jpg

Đối với các hình dạng đơn giản (hình hộp, hình trụ, hình cầu) như trong robot di động của chúng ta, ma trận quán tính có thể được tính bằng cách sử dụng các công thức từ danh sách này. Bảng bên dưới có chỉ ra công thức tính ma trận quán tính cho khung (hình hộp) và bánh xe (hình trụ). Bạn có thể thay các giá trị vào và tính xem có khớp với mã mô tả ở trên hay không. Đối với các mô hình phức tạp hơn, thông tin này có thể được trích xuất trực tiếp từ phần mềm 3D như MeshLab.

inertia-matrix.jpg

Có thể thêm nhiều đặc tính vật lý khác như ma sát, độ cứng và giảm chấn (chi tiết hơn tại đây). Tuy nhiên, vì chúng ta muốn mô phỏng trong Gazebo nên có thể thêm các thuộc tính này bằng thẻ gazebo. Để cho đơn giản, ở đây mình chỉ dùng thẻ material (vật liệu) màu xanh lam cho bánh xe nhưng bạn có thể thêm nhiều thành phần khác (chi tiết tại đây) để mô phỏng chân thực hơn.

  <gazebo reference="${name}_wheel">
    <material>Gazebo/Blue</material>
  </gazebo>

Khởi động và Điều Khiển Robot

Để điều khiển mobile robot của chúng ta trong Gazebo, bạn cần thêm hai thứ nữa vào tệp Xacro. Đầu tiên, mọi khớp truyền động, tức là tất cả các khớp bánh xe trong trường hợp của chúng ta, cần thẻ <transmission> bên trong macro wheel như bên dưới.

  <!-- Adding transmission to wheels -->
  <transmission name="${name}_wheel_trans">
    <type>transmission_interface/SimpleTransmission</type>
    <actuator name="${name}_wheel_motor">
      <mechanicalReduction>1</mechanicalReduction>
    </actuator>
    <joint name="${name}_wheel_joint">
      <hardwareInterface>hardware_interface/VelocityJointInterface</hardwareInterface>
    </joint>
  </transmission>

Thứ hai, plugin gazebo_ros_control được thêm vào để phân tích cú pháp các thẻ tranmission và tải các giao diện phần cứng và trình quản lý bộ điều khiển thích hợp trong gazebo.

Launch File

Xacro đã hoàn tất và để khởi chạy nó, hãy tạo một tệp launch khác có tên drive_robot.launch. Tệp đầy đủ nằm ở đây và mình đã thêm comment vào mỗi dòng để giải thích ý nghĩa của chúng nhưng nếu bạn vẫn chưa rõ về bất kỳ điều gì, hãy nhắn mình bằng comment dưới bài viết này.

Một điều quan trọng cần lưu ý là drive_robot.launch này cần 2 tệp (có thể được tải về tại đây và đặt trong thư mục config):

  • diffdrive.yaml bao gồm các cấu hình của diff_drive_controller (một trong nhiều bộ điều khiển mà ROS cung cấp và nó được sử dụng đặc biệt để tính toán vận tốc góc trái và phải cho rô-bốt 2 hoặc 4 bánh (bạn có thể tìm thêm chi tiết tại đây)).

  • gazebo_ros_control_params.yaml chứa các cài đặt cho control trong Gazebo.

Điều Khiển Robot Trong Gazebo

Mở 2 terminal, trong cái đầu tiên chạy tệp drive_robot.launch:

roslaunch ros_mobile_robot drive_robot.launch

Đợi vài giây cho Gazebo được tải xong.

Trong terminal thứ hai, chạy package rqt_robot_steering cung cấp GUI (giao diện) để điều khiển robot. Về cơ bản, nó cho phép bạn thay đổi vận tốc tuyến tính và tốc độ góc được publish tới topic /robot_diff_drive_controller/cmd_vel để điều khiển rô-bốt. Nếu tên topic không phải là /robot_diff_drive_controller/cmd_vel, hãy gõ lại cho đúng.

rosrun rqt_robot_steering rqt_robot_steering

rqt_robot_steering

Thay đổi vận tốc tuyến tính và góc trong GUI để điều khiển robot:

steer-robot-gazebo

Nếu bạn đang sử dụng máy ảo thì có thể thấy rằng mô phỏng bị lag. Đó là bởi vì Gazebo rất nặng, nếu bạn chạy nó trên máy tính chạy Ubuntu gốc và có card đồ họa tốt thì nó sẽ chạy mượt hơn.

Có thú vị khi thấy robot di chuyển không? Mình cá là có. Bạn đã đi một chặng đường dài và đã làm rất tốt! Chương tiếp theo sẽ là chương cuối của loạt bài này, trong đó bạn sẽ kết hợp mọi thứ bạn đã học được cho đến nay để điều khiển robot bằng cử chỉ tay của mình. See you there!

Q

Em chào anh, em chưa hiểu tại sao cần tới 2 bộ điều khiển trong 'controller_manager' là :" mobile_robot_joint_state_controller và robot_diff_drive_controller" ạ? Em cảm ơn!

Đ

mình muốn sử dụng ROS2 và các khối được tạo từ STL nhưng không biết làm như thế nào? Mong bạn có thể hướng dẫn thêm

T

ROS 2 có khá nhiều thay đổi . Các khái niệm cơ bản thì vẫn khá giống ROS 1 nên bạn thử mày mò xem. Muốn import STL model vào Gazebo thì bạn có thể define trong world file, hoặc import trực tiếp bằng cách vào Edit chọn Model Editor (hoặc Ctrl + M). Sau đó ở mục Custom Shape chọn Add rồi Browse tới file STL. Sau khi chọn Import, model sẽ hiện lên bên Viewer và bạn có thể click chuột trái để đặt model ở vị trí mong muốn. Sau đó chọn Ctrl + S, đổi tên model và lưu lại. Cuối cùng bạn ấn Ctrl + X để thoát Model Editor. Lúc này bạn có thể thấy model của bạn ở bên cột Model. Bạn có thể lưu lại world file bằng cách vào File > Save World As. Khi bạn include file World vào (thực chất là 1 XML) này 1 launch file nào đó thì nó sẽ tự động lại cái scene mà bạn đã tạo.

Đ

Trinh Nguyen mình muốn import STL vào Rviz ko phải Gazebo thì phải làm ntn?

T

đạt lê văn Bạn có thể thay đổi file URDF ở mục geometry. Ví dụ: https://answers.ros.org/question/9613/how-to-import-stl-files-into-urdf-files/

Đ

em đang phát triển project của anh thêm bằng cách sử dụng cảm biến lidar để quét map anh có thể hướng dẫn phần này được không ạ,vì em chưa hiểu phần trao đổi dữ liệu giữa rviz và gazebo

T

Hi em, em có thể tham khảo thêm ở đây: https://discourse.ros.org/t/free-simulation-model-mobile-robot-with-lidar-and-rgbd-camera/4535

D
Duy Giang3y ago

Khi em chạy dòng code này: roslaunch ros_mobile_robot drive_robot.launch Thì chương trình báo lỗi: The error message "RLException: error loading <rosparam> tag: file does not exist [/home/giang/catkin_ws/src/ros_mobile_robot/config/diffdrive.yaml]" suggests that the file "diffdrive.yaml" cannot be found in the directory "/home/giang/catkin_ws/src/ros_mobile_robot/config/". Mong sớm nhận được phản hồi từ anh

T

Hi em, có vẻ như em chưa có file diffdrive.yaml trong folder config. Như trong bài a có viết, file này là configuration của differential drive controller, một loại controller mà ROS cung cấp để điều khiển xe 2-4 bánh. Em lên github của a tải về là được. Nội dung của file a giải thích bằng comment bên trong, e có thể đọc thêm.

T

Hi em, trong file URDF anh không thấy có link bánh xe (wheel) hay là em tạo ở một file khác? Nếu em dùng github thì có thể share lên đó rồi a sẽ check giúp, ok?

V
Võ Minhh3y ago

Dạ em dùng Fusion 360 tạo file URDF cho mình, em chỉ vẽ 3d phần thân ( như hình model màu xanh) >> Fusion 360 export file Urdf giúp em. EM k dùng github nên có vẻ sẽ tốn xí thời gian để up lên.

Tuy nhiên, trước mắt cho em hỏi là vấn đề nó k chạy là do em k có link bánh xe hả a ? hay là do em thiếu đoạn mã code nào đó ở file launch hả a ( hình 3,4) ? Mình có cách nào để cái thân xe chạy mà k cần đến bánh k ạ ?

T

Võ Minh Tiến Thứ nhất, đúng là em cần có bánh xe. Thứ 2, trong launch file của em có load vài launch file khác nên anh không biết có thiếu gì không. Ví dụ, nếu em dùng differential drive controller thì em cũng phải load nó như a làm ở đây: https://github.com/TrinhNC/ros_mobile_robot/blob/main/launch/drive_robot.launch. Ngoài ra, anh không biết là em đang mô phỏng hay làm trên robot thật. Nếu là mô phỏng trên gazebo thì phải launch cả gazebo nữa. Thứ 3, em muốn robot chạy mà không cần đến bánh thì anh không biết mục đích của em ở đây là làm gì. Sẽ dễ hơn nếu em có thể share code.

V
Võ Minhh3y ago

Trinh Nguyen dạ đợi em share code nhé, nhưng mà em có thể liên lạc trên mạng xã hội nào đó thay vì như trên đây đc k ạ ? Hay là em chỉ đc chat với a trên đây thôi ?

T

Võ Minh Tiến LinkedIn của a: https://www.linkedin.com/in/trinh-c-nguyen

V
Võ Minhh3y ago

image.png

Từ hướng dẫn của a, e tạo mô hình robot 3D của mình. E đã tích hợp mô hình Robot của mình vào dự án của mình và a có thể thấy trong hình ảnh. Tuy nhiên, điều e gặp phải là mô hình không chạy theo đường dẫn. Nó vẫn đứng nguyên tại điểm gốc không chuyển động.

A có thể cho e một số lời khuyên để sửa chữa nó? những gì e thiếu trong chương trình? E Cảm ơn

V
Võ Minhh3y ago

Code file xacro image.png

Code file launch cua model

image.png

code fle launch whole project

image.png

line 14 va line 10 la` em goi robot model.