当前位置: 首页 > news >正文

ROS2笔记-2:第一个在Gazebo中能动的例子

第一个在Gazebo中能动的例子

  • 写在前面
  • X-windows 与cursor
  • Simple ROS2 Robot
    • Project Structure
    • Features
    • Dependencies
    • Installation
    • Usage
    • Robot Description
    • Movement Pattern
    • Customization
  • 解释
  • 运行的效果
    • 启动
    • 控制机器人移动
  • 代码

写在前面

第一个在Gazebo中能动的例子 是指对我来说。在Gazebo中显示,第二个要求是能动。
这个目标对我来说并不容易。可能是我没有装实体机的原因。
如果在MobaStrem中,当然不需要考虑X-windows的问题,但如果在cursor中,就是一个大困难。

X-windows 与cursor

在学习新技术时,我一般需要cursor.
怎么说呢,我不想看书。不是我不想看,一般来说,也没有有书可以看。
再者,人脑容量是有限的,我们需要用一种哲学模式,来描述世界,我们需要在学习一种技术之前,利用哲学窠臼,来思考,如果是我们自己来实现,应当如何做。

所以,我一般都是放弃深度思考,反复与cursor磨合,看它如何进展和不断地犯错,来思考。
但是对X-windows的支持,cursor做得不好。这样一来,我就无法搞清楚是vmware带来的问题还是cursor的问题。
虽然,用手工来执行,也是一个方法,但那并不是个好主意。

所以,想来想去想了一晚上,才想到直接装到ubuntu上。真的是,这么个简单的答案,我一直没想到。
在ubuntu上,我又来到基本的目标,就是机器人能动。

# 部分笔记
因为ubuntu 的桌面,这几年没怎么用。
所以,也不想装输入法,就英文吧。蹩脚,乱,是难免的。

Simple ROS2 Robot

A simple differential drive robot implementation in ROS2 Humble with Gazebo simulation. This project serves as a learning platform for ROS2 and Gazebo integration.

Project Structure

simple_robot_ws/
├── src/
│   └── simple_robot/
│       ├── simple_robot/
│       │   ├── launch/
│       │   │   └── robot_gazebo.launch.py
│       │   ├── robot.urdf.xacro
│       │   └── square_movement.py
│       ├── package.xml
│       └── setup.py

Features

  • Simple differential drive robot with two wheels
  • Gazebo simulation integration
  • Square movement pattern demonstration
  • ROS2 Humble compatible

Dependencies

  • ROS2 Humble
  • Gazebo
  • Python 3.10
  • Required ROS2 packages:
    • gazebo_ros_pkgs
    • gazebo_ros2_control
    • robot_state_publisher
    • xacro

Installation

  1. Clone this repository into your ROS2 workspace:
cd ~/ros2_ws/src
git clone <repository-url> simple_robot
  1. Install dependencies:
sudo apt-get update
sudo apt-get install -y ros-humble-gazebo-ros-pkgs ros-humble-gazebo-ros2-control ros-humble-robot-state-publisher ros-humble-xacro
  1. Build the package:
cd ~/ros2_ws
colcon build --symlink-install

Usage

  1. Source the workspace:
source install/setup.bash
  1. Launch the robot in Gazebo:
ros2 launch simple_robot robot_gazebo.launch.py
  1. In a new terminal, run the square movement node:
source install/setup.bash
ros2 run simple_robot square_movement

Robot Description

The robot consists of:

  • A blue rectangular base (0.3m x 0.3m x 0.1m)
  • Two black wheels (radius: 0.05m, width: 0.04m)
  • Differential drive control system

Movement Pattern

The robot follows a square pattern:

  1. Moves forward for 5 seconds at 0.2 m/s
  2. Turns 90 degrees at 0.5 rad/s
  3. Repeats the pattern

Customization

You can modify:

  • Robot dimensions in robot.urdf.xacro
  • Movement speed and pattern in square_movement.py
  • Launch parameters in robot_gazebo.launch.py

后面我会把这个代码放到github.

解释

the main source code files in detail to help you understand ROS2 concepts:

  1. First, let’s look at the URDF file (robot.urdf.xacro):

Read file: /data/myrobot/simple_robot_ws/src/simple_robot/simple_robot/robot.urdf.xacro


Let me explain the key components of the URDF file:

  1. Properties and Parameters:
<xacro:property name="PI" value="3.1415926535897931"/>
<xacro:property name="robot_width" value="0.3"/>
  • These are reusable variables that define robot dimensions
  • Makes it easy to modify robot size by changing one value
  1. Links (Physical parts of the robot):
<link name="base_link">
    <visual>...</visual>
    <collision>...</collision>
    <inertial>...</inertial>
</link>
  • visual: Defines how the robot looks in simulation
  • collision: Defines collision geometry for physics
  • inertial: Defines mass and inertia properties
  1. Joints (Connections between links):
<joint name="base_right_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="right_wheel"/>
    <origin xyz="0 ${-(robot_width/2 + wheel_width/2)} 0" rpy="${PI/2} 0 0"/>
    <axis xyz="0 0 1"/>
</joint>
  • type="continuous": Allows unlimited rotation (for wheels)
  • parent and child: Defines which links are connected
  • origin: Position and orientation of the joint
  • axis: Axis of rotation
  1. Gazebo Plugin (Simulation interface):
<gazebo>
    <plugin name="differential_drive" filename="libgazebo_ros_diff_drive.so">
        <left_joint>base_left_wheel_joint</left_joint>
        <right_joint>base_right_wheel_joint</right_joint>
        ...
    </plugin>
</gazebo>
  • Connects ROS2 to Gazebo simulation
  • Handles differential drive control
  • Publishes odometry information

Now, let’s look at the Python node that controls the robot:


Read file: /data/myrobot/simple_robot_ws/src/simple_robot/simple_robot/simple_robot/square_movement.py


Let me explain the Python node:

  1. Node Initialization:
def __init__(self):
    super().__init__('square_movement')
    self.publisher = self.create_publisher(Twist, '/cmd_vel', 10)
    self.timer = self.create_timer(0.1, self.timer_callback)
  • Creates a ROS2 node named ‘square_movement’
  • Creates a publisher for Twist messages on ‘/cmd_vel’ topic
  • Sets up a timer that calls timer_callback every 0.1 seconds
  1. Movement Control:
def timer_callback(self):
    current_time = self.get_clock().now()
    elapsed_time = (current_time - self.state_start_time).nanoseconds / 1e9
    
    msg = Twist()
    
    if self.state == 'forward':
        msg.linear.x = 0.2  # Move forward at 0.2 m/s
        msg.angular.z = 0.0
        if elapsed_time >= 5.0:  # After 5 seconds
            self.state = 'turn'
    elif self.state == 'turn':
        msg.linear.x = 0.0
        msg.angular.z = 0.5  # Turn at 0.5 rad/s
        if elapsed_time >= 3.14:  # After ~90 degrees
            self.state = 'forward'
  • Uses a state machine to control robot movement
  • linear.x: Forward/backward velocity
  • angular.z: Rotational velocity
  • Switches between forward and turning states
  1. Main Function:
def main(args=None):
    rclpy.init(args=args)
    node = SquareMovement()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()
  • Initializes ROS2
  • Creates and runs the node
  • Handles cleanup on shutdown

Finally, let’s look at the launch file:


Read file: /data/myrobot/simple_robot_ws/src/simple_robot/simple_robot/launch/robot_gazebo.launch.py


The launch file is responsible for starting all necessary components:

  1. URDF Processing:
xacro_file = os.path.join(pkg_dir, 'robot.urdf.xacro')
robot_description_config = xacro.process_file(xacro_file)
robot_description = {'robot_description': robot_description_config.toxml()}
  • Loads and processes the URDF file
  • Converts Xacro macros into XML
  1. Gazebo Launch:
gazebo_launch = IncludeLaunchDescription(
    PythonLaunchDescriptionSource([os.path.join(
        get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')]),
)
  • Starts the Gazebo simulator
  1. Robot State Publisher:
robot_state_publisher = Node(
    package='robot_state_publisher',
    executable='robot_state_publisher',
    output='screen',
    parameters=[robot_description]
)
  • Publishes robot joint states
  • Required for visualization and control
  1. Robot Spawning:
spawn_entity = Node(
    package='gazebo_ros',
    executable='spawn_entity.py',
    arguments=['-entity', 'simple_robot',
              '-topic', 'robot_description'],
    output='screen'
)
  • Spawns the robot in Gazebo
  • Uses the processed URDF description

Key ROS2 Concepts Demonstrated:

  1. Nodes: Independent processes (square_movement.py)
  2. Topics: Communication channels (‘/cmd_vel’)
  3. Messages: Data structures (Twist)
  4. Launch System: Starting multiple nodes
  5. URDF/Xacro: Robot description
  6. Gazebo Integration: Simulation
  7. Parameters: Configuration values
  8. Publishers/Subscribers: Communication pattern

运行的效果

启动

root@ros:/data/myrobot/simple_robot_ws# source install/setup.bash && ros2 launch simple_robot robot_gazebo.launch.py
[INFO] [launch]: All log files can be found below /root/.ros/log/2025-04-06-12-30-45-332217-ros-4626
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [gzserver-1]: process started with pid [4634]
[INFO] [gzclient-2]: process started with pid [4636]
[INFO] [robot_state_publisher-3]: process started with pid [4638]
[INFO] [spawn_entity.py-4]: process started with pid [4640]
[robot_state_publisher-3] [WARN] [1743913845.758133319] [kdl_parser]: The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia.  As a workaround, you can add an extra dummy link to your URDF.
[robot_state_publisher-3] [INFO] [1743913845.758202925] [robot_state_publisher]: got segment base_link
[robot_state_publisher-3] [INFO] [1743913845.758239006] [robot_state_publisher]: got segment left_wheel
[robot_state_publisher-3] [INFO] [1743913845.758242357] [robot_state_publisher]: got segment right_wheel
[spawn_entity.py-4] [INFO] [1743913845.891193009] [spawn_entity]: Spawn Entity started
[spawn_entity.py-4] [INFO] [1743913845.891440305] [spawn_entity]: Loading entity published on topic robot_description
[spawn_entity.py-4] [INFO] [1743913845.892783074] [spawn_entity]: Waiting for entity xml on robot_description
[spawn_entity.py-4] [INFO] [1743913846.020159987] [spawn_entity]: Waiting for service /spawn_entity, timeout = 30
[spawn_entity.py-4] [INFO] [1743913846.020361422] [spawn_entity]: Waiting for service /spawn_entity
[spawn_entity.py-4] [INFO] [1743913847.038242167] [spawn_entity]: Calling service /spawn_entity
[spawn_entity.py-4] [INFO] [1743913847.248558627] [spawn_entity]: Spawn status: SpawnEntity: Successfully spawned entity [simple_robot]
[gzserver-1] [INFO] [1743913847.262162662] [differential_drive]: Wheel pair 1 separation set to [0.340000m]
[gzserver-1] [INFO] [1743913847.262435027] [differential_drive]: Wheel pair 1 diameter set to [0.100000m]
[gzserver-1] [INFO] [1743913847.263072041] [differential_drive]: Subscribed to [/cmd_vel]
[gzserver-1] [INFO] [1743913847.264434814] [differential_drive]: Advertise odometry on [/odom]
[gzserver-1] [INFO] [1743913847.266079557] [differential_drive]: Publishing odom transforms between [odom] and [base_link]
[gzserver-1] [INFO] [1743913847.266098937] [differential_drive]: Publishing wheel transforms between [base_link], [base_left_wheel_joint] and [base_right_wheel_joint]
[INFO] [spawn_entity.py-4]: process has finished cleanly [pid 4640]
[gzclient-2] context mismatch in svga_surface_destroy
[gzclient-2] context mismatch in svga_surface_destroy
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)
[robot_state_publisher-3] [INFO] [1743917858.696625720] [rclcpp]: signal_handler(signum=2)
[gzclient-2] context mismatch in svga_surface_destroy
[gzclient-2] context mismatch in svga_surface_destroy
[INFO] [robot_state_publisher-3]: process has finished cleanly [pid 4638]
[INFO] [gzclient-2]: process has finished cleanly [pid 4636]
[INFO] [gzserver-1]: process has finished cleanly [pid 4634]
root@ros:/data/myrobot/simple_robot_ws# source install/setup.bash && ros2 launch simple_robot robot_gazebo.launch.py
[INFO] [launch]: All log files can be found below /root/.ros/log/2025-04-06-13-37-49-581935-ros-21692
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [gzserver-1]: process started with pid [21693]
[INFO] [gzclient-2]: process started with pid [21695]
[INFO] [robot_state_publisher-3]: process started with pid [21697]
[INFO] [spawn_entity.py-4]: process started with pid [21699]
[robot_state_publisher-3] [WARN] [1743917869.961730595] [kdl_parser]: The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia.  As a workaround, you can add an extra dummy link to your URDF.
[robot_state_publisher-3] [INFO] [1743917869.961810285] [robot_state_publisher]: got segment base_link
[robot_state_publisher-3] [INFO] [1743917869.961840435] [robot_state_publisher]: got segment left_wheel
[robot_state_publisher-3] [INFO] [1743917869.961843738] [robot_state_publisher]: got segment right_wheel
[spawn_entity.py-4] [INFO] [1743917870.115293166] [spawn_entity]: Spawn Entity started
[spawn_entity.py-4] [INFO] [1743917870.115563623] [spawn_entity]: Loading entity published on topic robot_description
[spawn_entity.py-4] [INFO] [1743917870.127828694] [spawn_entity]: Waiting for entity xml on robot_description
[spawn_entity.py-4] [INFO] [1743917870.140340287] [spawn_entity]: Waiting for service /spawn_entity, timeout = 30
[spawn_entity.py-4] [INFO] [1743917870.140550074] [spawn_entity]: Waiting for service /spawn_entity
[spawn_entity.py-4] [INFO] [1743917871.185531000] [spawn_entity]: Calling service /spawn_entity
[spawn_entity.py-4] [INFO] [1743917871.393789340] [spawn_entity]: Spawn status: SpawnEntity: Successfully spawned entity [simple_robot]
[gzserver-1] [INFO] [1743917871.415619114] [differential_drive]: Wheel pair 1 separation set to [0.340000m]
[gzserver-1] [INFO] [1743917871.416094928] [differential_drive]: Wheel pair 1 diameter set to [0.100000m]
[gzserver-1] [INFO] [1743917871.416994931] [differential_drive]: Subscribed to [/cmd_vel]
[gzserver-1] [INFO] [1743917871.418813122] [differential_drive]: Advertise odometry on [/odom]
[gzserver-1] [INFO] [1743917871.421652281] [differential_drive]: Publishing odom transforms between [odom] and [base_link]
[gzserver-1] [INFO] [1743917871.421705231] [differential_drive]: Publishing wheel transforms between [base_link], [base_left_wheel_joint] and [base_right_wheel_joint]
[INFO] [spawn_entity.py-4]: process has finished cleanly [pid 21699]
[gzclient-2] context mismatch in svga_surface_destroy
[gzclient-2] context mismatch in svga_surface_destroy

控制机器人移动

root@ros:/data/myrobot/simple_robot_ws# cd /data/myrobot/simple_robot_ws && source install/setup.bash && ros2 run simple_robot square_movement

在这里插入图片描述

代码

https://download.csdn.net/download/haoyujie/90571841
不需要积分。
突然懒病就犯了。不想传到github去了。

相关文章:

  • Linux——冯 • 诺依曼体系结构操作系统初识
  • C#核心学习(六)面向对象--封装(5)静态成员及静态构造函数和静态类 以及和常量的区别
  • 《手写MyBatis框架全流程:从DOM4J解析到SQL执行原理剖析》
  • 七、C++速通秘籍—静态多态(编译期)
  • 预测函数控制(PFC)——理论、应用与实践
  • 学透Spring Boot — 014. Spring MVC的自动配置
  • CANoe CAPL——CAN CAPL函数
  • jQuery 文本属性值
  • OceanBase生态2.0:如何实现“三分天下有其一”?
  • 应用层自定义协议与序列化
  • 【AI提示词】大学教授学术阅读(读论文)
  • 基于SpringBoot的售楼管理系统【附源码】
  • 记一次常规的网络安全渗透测试
  • SpringMVC与SpringCloud的区别
  • 区块链赋能知识产权保护:用技术捍卫创作者的权利
  • 下载安装Node.js及其他环境
  • 什么是异步?
  • ChatGPT-4o 在汉字显示上进步巨大
  • 解锁多邻国:全方位语言学习新体验
  • Gateway 网关 快速开始
  • 荥阳网站建设/关键词优化哪家强
  • 怎么做期货网站/湖南百度推广开户
  • wordpress 安装主题 无法调用图片和颜色/长沙整站优化
  • 学校网站建设新闻/宁波seo外包推广
  • 阿里云网站如何做淘宝客/如何推广网站方法
  • 企业做网站价钱/长尾关键词网站