机器人操作系统(ROS)的核心在于其模块化通信架构与高效的开发流程。本指南直击ROS开发的核心技术环节,助你快速构建功能节点并实现系统集成。你将从理解工作空间(catkin_ws
)这一代码与编译的容器开始,掌握使用catkin_create_pkg
创建功能包(Package)的方法,并深入关键配置文件CMakeLists.txt
与package.xml
的作用。核心在于编写节点(Node):通过Python实现发布者(Publisher)与订阅者(Subscriber),理解话题(Topic)通信机制,实践编译(catkin_make
)与运行(rosrun
)。为提升效率,你将学习编写启动文件(Launch File),实现多节点、参数()及话题重映射(
)的一键部署。最后,掌握可视化利器RViz(3D数据呈现) 和 rqt工具套件(rqt_graph
分析通信拓扑、rqt_plot
绘制实时曲线) 对于调试与理解系统状态至关重要。遵循此路径,你将奠定使用ROS高效开发机器人系统的坚实基础。
最后,如果大家喜欢我的创作风格,请大家多多关注up主,你们的支持就是我创作最大的动力!如果各位观众老爷觉得我哪些地方需要改进,请一定在评论区告诉我,马上改!在此感谢大家了。
各位观众老爷,本文通俗易懂,快速熟悉ROS,收藏本文,关注up不迷路,后续将持续分享ROS纯干货(请观众老爷放心,绝对又干又通俗易懂)。请多多关注、收藏、评论,评论区等你~~~
ROS开发的基石始于功能包(Package)。 掌握
catkin_ws
工作空间的构建、catkin_create_pkg
命令创建包、理解CMakeLists.txt
与package.xml
关键配置,并添加首个Python节点,是构建任何ROS应用的必备起点。
catkin_ws
)是什么?(代码仓库)ROS工作空间是存放ROS包和相关文件的目录结构
类似于项目文件夹,包含所有源代码、依赖和构建结果
标准工作空间结构:
catkin_ws/ # 工作空间根目录
├── build/ # 存放编译过程中生成的中间文件(自动生成)
├── devel/ # 存放最终生成的可执行文件和库(自动生成)
└── src/ # 用户源代码目录(你在这里创建包)
└── CMakeLists.txt # 工作空间的CMake配置文件
创建步骤
# 1. 创建工作空间目录
mkdir -p ~/catkin_ws/src
# 2. 进入src目录
cd ~/catkin_ws/src
# 3. 初始化工作空间(创建顶层CMakeLists.txt)
catkin_init_workspace
# 4. 返回工作空间根目录
cd ~/catkin_ws
# 5. 构建工作空间(生成build和devel目录)
catkin_make
# 6. 激活工作空间环境(重要!每次新终端都需要)
source devel/setup.bash
提示:将激活命令加入`.bashrc`永久生效:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
验证工作空间
echo $ROS_PACKAGE_PATH
# 应该输出包含/home/你的用户名/catkin_ws/src
catkin_create_pkg
)命令语法
catkin_create_pkg <包名> [依赖1] [依赖2] ...
创建第一个包
# 进入工作空间的src目录
cd ~/catkin_ws/src
# 创建名为my_first_package的包,依赖roscpp和rospy
catkin_create_pkg my_first_package roscpp rospy
输出示例
Created file my_first_package/package.xml
Created file my_first_package/CMakeLists.txt
Created folder my_first_package/include/my_first_package
Created folder my_first_package/src
Successfully created files in /home/user/catkin_ws/src/my_first_package.
关键目录说明
include/包名
:存放C++头文件src
:存放源代码(.cpp或.py文件)CMakeLists.txt
:构建配置文件package.xml
:包信息清单CMakeLists.txt
+ package.xml
package.xml
- 包信息清单
文件位置: ~/catkin_ws/src/my_first_package/package.xml
基础配置
<package format="2">
<name>my_first_packagename>
<version>0.0.0version>
<description>我的第一个ROS包description>
<maintainer email="[email protected]">Your Namemaintainer>
<license>MITlicense>
<buildtool_depend>catkinbuildtool_depend>
<build_depend>roscppbuild_depend>
<build_depend>rospybuild_depend>
<exec_depend>roscppexec_depend>
<exec_depend>rospyexec_depend>
package>
重要字段说明
:必须与文件夹名一致
:编译时需要的依赖
:运行时需要的依赖CMakeLists.txt
CMakeLists.txt
- 构建配置文件
文件位置: ~/catkin_ws/src/my_first_package/CMakeLists.txt
基础配置
cmake_minimum_required(VERSION 3.0.2)
project(my_first_package)
# 查找依赖包
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
)
# 声明为catkin包
catkin_package()
# 包含目录
include_directories(
${catkin_INCLUDE_DIRS}
)
# 添加Python脚本示例(取消注释)
# catkin_install_python(PROGRAMS scripts/simple_node.py
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
# 添加C++节点示例(取消注释)
# add_executable(simple_node src/simple_node.cpp)
# target_link_libraries(simple_node ${catkin_LIBRARIES})
创建脚本目录
mkdir -p ~/catkin_ws/src/my_first_package/scripts
创建Python节点文件 simple_node.py
#!/usr/bin/env python3
import rospy
if __name__ == '__main__':
rospy.init_node('my_first_node')
rospy.loginfo("我的第一个ROS节点已启动!")
rate = rospy.Rate(1) # 1Hz
while not rospy.is_shutdown():
rospy.loginfo("节点运行中...")
rate.sleep()
赋予执行权限
chmod +x ~/catkin_ws/src/my_first_package/scripts/simple_node.py
在CMakeLists.txt
中添加
catkin_install_python(PROGRAMS scripts/simple_node.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
构建包
# 1. 返回工作空间根目录
cd ~/catkin_ws
# 2. 构建所有包
catkin_make
# 3. 激活环境
source devel/setup.bash
运行节点
rosrun my_first_package simple_node.py
预期输出:
[INFO] [1680000000.000000]: 我的第一个ROS节点已启动!
[INFO] [1680000001.000000]: 节点运行中...
[INFO] [1680000002.000000]: 节点运行中...
...
找不到包/节点:
# 确保已激活工作空间
source devel/setup.bash
# 先再第一个终端运行 roscore ,再打开新的一个终端运行节点
roscore # 第一个终端
source ~/catkin_ws/devel/setup.bash # 第二个终端
rosrun my_first_package simple_node.py # 第二个终端
构建错误:
# 清理构建
cd ~/catkin_ws
rm -rf build devel
catkin_make
Python节点权限问题:
# 确保有执行权限
chmod +x ~/catkin_ws/src/my_first_package/scripts/*.py
ROS节点间通过话题(Topic)通信。 本节使用Python编写发布速度指令(
Publisher
)与订阅位置信息(Subscriber
)的节点,并通过catkin_make
编译、rosrun
运行,掌握ROS通信的核心能力。
节点通信的核心概念
在ROS中,节点(Node) 是执行计算的基本单元,而节点间通过话题(Topic) 进行通信。发布者(Publisher)将消息发送到话题,订阅者(Subscriber)从话题接收消息,这种发布-订阅模式是ROS分布式通信的核心。
代码实现与解析
#!/usr/bin/env python3
import rospy
from geometry_msgs.msg import Twist # 导入速度消息类型
def velocity_publisher():
# 初始化节点,命名为'velocity_publisher'
rospy.init_node('velocity_publisher', anonymous=True)
# 创建Publisher对象
# 参数1:话题名称 '/turtle1/cmd_vel'
# 参数2:消息类型 Twist
# 参数3:队列大小
pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
# 设置发布频率 (10Hz)
rate = rospy.Rate(10)
# 循环发布消息
while not rospy.is_shutdown():
# 创建Twist消息对象
vel_msg = Twist()
# 设置线速度 (x方向前进)
vel_msg.linear.x = 0.5 # 0.5 m/s
# 设置角速度 (z轴旋转)
vel_msg.angular.z = 0.2 # 0.2 rad/s
# 发布消息
pub.publish(vel_msg)
# 日志输出
rospy.loginfo("发布速度指令: 线速度=%.2f m/s, 角速度=%.2f rad/s",
vel_msg.linear.x, vel_msg.angular.z)
# 按频率休眠
rate.sleep()
if __name__ == '__main__':
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
可视化解析
代码实现与解析
#!/usr/bin/env python3
import rospy
from turtlesim.msg import Pose # 导入位置消息类型
def pose_callback(pose):
# 当收到新消息时自动调用此回调函数
rospy.loginfo("乌龟位置: x=%.2f, y=%.2f, 朝向=%.2f",
pose.x, pose.y, pose.theta)
def pose_subscriber():
# 初始化节点,命名为'pose_subscriber'
rospy.init_node('pose_subscriber', anonymous=True)
# 创建Subscriber对象
# 参数1:话题名称 '/turtle1/pose'
# 参数2:消息类型 Pose
# 参数3:回调函数
rospy.Subscriber('/turtle1/pose', Pose, pose_callback)
# 保持节点运行
rospy.spin()
if __name__ == '__main__':
pose_subscriber()
可视化解析
catkin_make
+ rosrun
)创建工作空间和包(如果尚未创建)
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_create_pkg my_robot_control rospy
添加Python脚本
scripts
文件夹scripts
目录chmod +x velocity_publisher.py
chmod +x pose_subscriber.py
编译工作空间
cd ~/catkin_ws
catkin_make
source devel/setup.bash
运行节点
# 终端1: 启动ROS核心
roscore
# 终端2: 启动小乌龟模拟器
rosrun turtlesim turtlesim_node
# 终端3: 运行发布者节点
rosrun my_robot_control velocity_publisher.py
# 终端4: 运行订阅者节点
rosrun my_robot_control pose_subscriber.py
可视化通信关系
使用rqt_graph
工具查看节点和话题的通信关系:
rosrun rqt_graph rqt_graph
运行效果
[INFO] [1677727045.123456]: 乌龟位置: x=5.54, y=5.54, 朝向=0.78
[INFO] [1677727045.223456]: 乌龟位置: x=5.52, y=5.56, 朝向=0.80
...
启动文件是ROS系统部署的核心工具。 通过单命令批量启动节点(小乌龟+控制器),实现参数动态配置(
)和话题重映射(
),完成复杂系统的一键部署。
启动文件的本质作用
启动文件(Launch File)是ROS中的系统部署蓝图,它解决了复杂机器人系统中的关键问题:
批量节点管理:同时启动多个相关节点
参数集中配置:统一设置节点参数
命名空间管理:解决节点/话题命名冲突
环境预设:自动配置ROS环境变量
步骤1:创建Launch文件
在包中创建 launch
目录
cd ~/catkin_ws/src/my_robot_control
mkdir launch
创建 Launch 文件
touch launch/turtle_control.launch
编辑文件内容 – 小乌龟系统启动文件示例
<launch>
<node pkg="turtlesim" type="turtlesim_node" name="turtle_sim" output="screen">
<param name="background_r" value="50" />
<param name="background_g" value="100" />
<param name="background_b" value="150" />
node>
<node pkg="my_robot_control" type="velocity_publisher.py" name="turtle_controller" output="screen">
<param name="linear_speed" value="0.5" />
<param name="angular_speed" value="0.2" />
node>
<node pkg="my_robot_control" type="pose_subscriber.py" name="pose_monitor" />
launch>
步骤2:配置包依赖
确保package.xml
包含必要依赖
~/catkin_ws/src/my_robot_control
路径下 package.xml
<buildtool_depend>catkinbuildtool_depend>
<exec_depend>rospyexec_depend>
<exec_depend>turtlesimexec_depend>
<exec_depend>geometry_msgsexec_depend>
步骤3:编译工作空间
cd ~/catkin_ws
catkin_make
source devel/setup.bash # 重要!使系统识别新launch文件
步骤4:运行 Launch 文件
roslaunch my_robot_control turtle_control.launch
实际运行窗口
运行效果可视化
) 与重映射 (
)参数传递深度应用
<launch>
<arg name="linear_speed" default="0.8" />
<arg name="angular_speed" default="0.5" />
<arg name="bg_red" default="50" />
<node pkg="turtlesim" type="turtlesim_node" name="simulator">
<param name="background_r" value="$(arg bg_red)" />
<param name="background_g" value="100" />
<param name="background_b" value="150" />
node>
<node pkg="my_robot_control" type="velocity_publisher.py" name="controller">
<param name="linear_speed" value="$(arg linear_speed)" />
<param name="angular_speed" value="$(arg angular_speed)" />
node>
launch>
# 覆盖默认参数
roslaunch my_robot_control turtle_control.launch linear_speed:=1.2 angular_speed:=0.8 bg_red:=100
参数层级关系
重映射高级应用
<launch>
<group ns="turtle1">
<node pkg="turtlesim" type="turtlesim_node" name="sim">
<remap from="turtle1/pose" to="pose" />
<remap from="turtle1/cmd_vel" to="cmd_vel" />
node>
<node pkg="my_robot_control" type="controller.py" name="ctrl">
<remap from="turtle1/cmd_vel" to="cmd_vel" />
node>
group>
<group ns="turtle2">
<node pkg="turtlesim" type="turtlesim_node" name="sim">
<remap from="turtle1/pose" to="pose" />
<remap from="turtle1/cmd_vel" to="cmd_vel" />
node>
<node pkg="my_robot_control" type="controller.py" name="ctrl">
<remap from="turtle1/cmd_vel" to="cmd_vel" />
node>
group>
launch>
重映射前后对比
下面我将提供一个完整的ROS包实现,包含所有代码文件和详细路径说明,实现RGB-D相机、IMU数据可视化及曲线绘制。我们将创建一个名为
visualization_demo
的ROS包。
~/catkin_ws/src/
└── visualization_demo/
├── launch/
│ ├── demo.launch
│ ├── sensors.launch
│ └── rviz_config.rviz
├── scripts/
│ ├── sensor_simulator.py
│ └── robot_controller.py
├── urdf/
│ └── my_robot.urdf
├── config/
│ └── robot_params.yaml
└── CMakeLists.txt
└── package.xml
cd ~/catkin_ws/src
catkin_create_pkg visualization_demo rospy sensor_msgs geometry_msgs tf visualization_msgs
cd visualization_demo
mkdir launch scripts urdf config
urdf/my_robot.urdf
)
<robot name="visualization_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.3 0.3 0.1"/>
geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
material>
visual>
link>
<link name="camera_link"/>
<joint name="camera_joint" type="fixed">
<parent link="base_link"/>
<child link="camera_link"/>
<origin xyz="0.2 0 0.15" rpy="0 0.3 0"/>
joint>
<link name="imu_link"/>
<joint name="imu_joint" type="fixed">
<parent link="base_link"/>
<child link="imu_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
joint>
<link name="wheel_left">
<visual>
<geometry>
<cylinder length="0.05" radius="0.08"/>
geometry>
visual>
link>
<joint name="wheel_left_joint" type="continuous">
<parent link="base_link"/>
<child link="wheel_left"/>
<origin xyz="0 0.15 -0.05" rpy="1.57 0 0"/>
joint>
<link name="wheel_right">
<visual>
<geometry>
<cylinder length="0.05" radius="0.08"/>
geometry>
visual>
link>
<joint name="wheel_right_joint" type="continuous">
<parent link="base_link"/>
<child link="wheel_right"/>
<origin xyz="0 -0.15 -0.05" rpy="1.57 0 0"/>
joint>
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<commandTopic>cmd_velcommandTopic>
<odometryTopic>odomodometryTopic>
<odometryFrame>odomodometryFrame>
<robotBaseFrame>base_linkrobotBaseFrame>
<publishWheelTF>truepublishWheelTF>
<wheelSeparation>0.3wheelSeparation>
<wheelDiameter>0.16wheelDiameter>
plugin>
gazebo>
robot>
scripts/sensor_simulator.py
)#!/usr/bin/env python3
import rospy
import math
import numpy as np
from sensor_msgs.msg import PointCloud2, PointField, Imu, Image
from geometry_msgs.msg import Twist, PoseStamped
from nav_msgs.msg import Odometry
from std_msgs.msg import Header
import tf2_ros
from tf.transformations import quaternion_from_euler
class SensorSimulator:
def __init__(self):
rospy.init_node('sensor_simulator')
# 创建发布器
self.pointcloud_pub = rospy.Publisher('/camera/depth/points', PointCloud2, queue_size=10)
self.imu_pub = rospy.Publisher('/imu/data', Imu, queue_size=10)
self.image_pub = rospy.Publisher('/camera/rgb/image_raw', Image, queue_size=10)
self.odom_pub = rospy.Publisher('/odom', Odometry, queue_size=10)
# 订阅速度指令
rospy.Subscriber('/cmd_vel', Twist, self.cmd_vel_callback)
# TF广播器
self.tf_broadcaster = tf2_ros.TransformBroadcaster()
# 机器人状态
self.x = 0.0
self.y = 0.0
self.th = 0.0
self.vx = 0.0
self.vth = 0.0
self.last_time = rospy.Time.now()
# 模拟参数
self.rate = rospy.Rate(20) # 20Hz
def cmd_vel_callback(self, msg):
self.vx = msg.linear.x
self.vth = msg.angular.z
def generate_pointcloud(self):
"""生成模拟点云数据(立方体环境)"""
header = Header()
header.stamp = rospy.Time.now()
header.frame_id = "camera_link"
# 创建点云数据(立方体)
points = []
for x in np.arange(-1.0, 1.0, 0.05):
for y in np.arange(-1.0, 1.0, 0.05):
for z in [0.5, 1.5]: # 两个平面
points.append([x, y, z])
# 转换为PointCloud2格式
fields = [
PointField('x', 0, PointField.FLOAT32, 1),
PointField('y', 4, PointField.FLOAT32, 1),
PointField('z', 8, PointField.FLOAT32, 1)
]
cloud = PointCloud2()
cloud.header = header
cloud.height = 1
cloud.width = len(points)
cloud.fields = fields
cloud.is_bigendian = False
cloud.point_step = 12 # 12 bytes per point (3 floats)
cloud.row_step = cloud.point_step * cloud.width
cloud.is_dense = True
cloud.data = np.array(points, dtype=np.float32).tobytes()
return cloud
def generate_imu_data(self):
"""生成模拟IMU数据(含噪声)"""
imu = Imu()
imu.header.stamp = rospy.Time.now()
imu.header.frame_id = "imu_link"
# 添加俯仰角模拟机器人倾斜
pitch = 0.1 * math.sin(rospy.get_time() * 0.5)
# 方向四元数
q = quaternion_from_euler(0, pitch, self.th)
imu.orientation.x = q[0] + np.random.normal(0, 0.01)
imu.orientation.y = q[1] + np.random.normal(0, 0.01)
imu.orientation.z = q[2] + np.random.normal(0, 0.01)
imu.orientation.w = q[3] + np.random.normal(0, 0.01)
# 角速度
imu.angular_velocity.x = np.random.normal(0, 0.01)
imu.angular_velocity.y = np.random.normal(0, 0.01)
imu.angular_velocity.z = self.vth + np.random.normal(0, 0.02)
# 线加速度
imu.linear_acceleration.x = self.vx * 0.1 + np.random.normal(0, 0.05)
imu.linear_acceleration.y = np.random.normal(0, 0.05)
imu.linear_acceleration.z = 9.8 + np.random.normal(0, 0.1)
return imu
def generate_image(self):
"""生成模拟RGB图像(梯度图)"""
img = Image()
img.header.stamp = rospy.Time.now()
img.header.frame_id = "camera_link"
img.height = 480
img.width = 640
img.encoding = "rgb8"
img.is_bigendian = 0
img.step = 640 * 3 # width * channels
# 创建梯度图像
data = bytearray()
for y in range(480):
for x in range(640):
r = int(255 * x / 640)
g = int(255 * y / 480)
b = 128 + int(64 * math.sin(rospy.get_time()))
data.extend([r, g, b])
img.data = bytes(data)
return img
def update_odometry(self):
"""更新机器人里程计"""
current_time = rospy.Time.now()
dt = (current_time - self.last_time).to_sec()
self.last_time = current_time
# 更新位置
delta_x = self.vx * math.cos(self.th) * dt
delta_y = self.vx * math.sin(self.th) * dt
delta_th = self.vth * dt
self.x += delta_x
self.y += delta_y
self.th += delta_th
# 发布TF变换
transform = tf2_ros.TransformStamped()
transform.header.stamp = current_time
transform.header.frame_id = "odom"
transform.child_frame_id = "base_link"
transform.transform.translation.x = self.x
transform.transform.translation.y = self.y
transform.transform.translation.z = 0.0
q = quaternion_from_euler(0, 0, self.th)
transform.transform.rotation.x = q[0]
transform.transform.rotation.y = q[1]
transform.transform.rotation.z = q[2]
transform.transform.rotation.w = q[3]
self.tf_broadcaster.sendTransform(transform)
# 发布里程计
odom = Odometry()
odom.header.stamp = current_time
odom.header.frame_id = "odom"
odom.child_frame_id = "base_link"
odom.pose.pose.position.x = self.x
odom.pose.pose.position.y = self.y
odom.pose.pose.orientation = transform.transform.rotation
odom.twist.twist.linear.x = self.vx
odom.twist.twist.angular.z = self.vth
self.odom_pub.publish(odom)
def run(self):
while not rospy.is_shutdown():
# 发布传感器数据
self.pointcloud_pub.publish(self.generate_pointcloud())
self.imu_pub.publish(self.generate_imu_data())
self.image_pub.publish(self.generate_image())
# 更新并发布里程计
self.update_odometry()
self.rate.sleep()
if __name__ == '__main__':
try:
simulator = SensorSimulator()
simulator.run()
except rospy.ROSInterruptException:
pass
scripts/robot_controller.py
)#!/usr/bin/env python3
import rospy
from geometry_msgs.msg import Twist
import math
class RobotController:
def __init__(self):
rospy.init_node('robot_controller')
self.cmd_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
self.rate = rospy.Rate(10) # 10Hz
self.duration = 30 # 演示时长(秒)
def run_demo(self):
start_time = rospy.get_time()
while not rospy.is_shutdown() and (rospy.get_time() - start_time) < self.duration:
elapsed = rospy.get_time() - start_time
# 分段控制
if elapsed < 10:
# 第一阶段:直线运动
self.move_robot(0.5, 0.0)
elif elapsed < 20:
# 第二阶段:旋转
self.move_robot(0.0, 0.5)
else:
# 第三阶段:正弦运动
speed = 0.5 * math.sin(elapsed - 20)
self.move_robot(speed, speed)
self.rate.sleep()
# 停止机器人
self.move_robot(0, 0)
rospy.loginfo("演示结束")
def move_robot(self, linear, angular):
twist = Twist()
twist.linear.x = linear
twist.angular.z = angular
self.cmd_pub.publish(twist)
if __name__ == '__main__':
try:
controller = RobotController()
controller.run_demo()
except rospy.ROSInterruptException:
pass
launch/sensors.launch
)<launch>
<node name="sensor_simulator" pkg="visualization_demo" type="sensor_simulator.py" output="screen"/>
<node name="robot_controller" pkg="visualization_demo" type="robot_controller.py" output="screen"/>
<node pkg="tf" type="static_transform_publisher" name="map_to_odom"
args="0 0 0 0 0 0 map odom 100"/>
<param name="robot_description" textfile="$(find visualization_demo)/urdf/my_robot.urdf"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/>
launch>
launch/demo.launch
)<launch>
<include file="$(find visualization_demo)/launch/sensors.launch"/>
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find visualization_demo)/launch/rviz_config.rviz"/>
<node name="rqt_graph" pkg="rqt_graph" type="rqt_graph" output="screen"/>
<node name="rqt_plot" pkg="rqt_plot" type="rqt_plot"
args="/cmd_vel/linear/x /cmd_vel/angular/z /imu/data/orientation/y /odom/pose/pose/position/x"/>
launch>
launch/rviz_config.rviz
)Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
Splitter Ratio: 0.5
Tree Height: 523
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Name: Time
SyncMode: 0
SyncSource: ""
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.03
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: >
Value: true
- Class: rviz/RobotModel
Enabled: true
Name: Robot Model
TF Prefix: ""
Update Interval: 0
Visual Enabled: true
- Class: rviz/TF
Enabled: true
Frame Timeout: 15
Frames:
All Enabled: true
Marker Scale: 1
Name: TF
Show Arrows: true
Show Axes: true
Show Names: true
Tree:
base_link: {parent: '', view: true}
camera_link: {parent: base_link, view: true}
imu_link: {parent: base_link, view: true}
odom: {parent: map, view: true}
wheel_left: {parent: base_link, view: true}
wheel_right: {parent: base_link, view: true}
Update Interval: 0
Value: true
- Class: rviz/PointCloud2
Enabled: true
Name: RGB-D PointCloud
Queue Size: 10
Selectable: true
Size (Pixels): 3
Style: Flat Squares
Topic: /camera/depth/points
Unreliable: false
Value: true
- Class: rviz/Image
Enabled: true
Image Topic: /camera/rgb/image_raw
Max Value: 1
Median window: 5
Min Value: 0
Name: RGB Camera
Normalize Range: false
Queue Size: 2
Transport Hint: raw
Unreliable: false
Value: true
- Class: rviz/Imu
Enabled: true
Name: IMU Orientation
Scale: 0.3
Show Arrow: true
Show Covariance: false
Show History: false
Topic: /imu/data
Value: true
- Class: rviz/Path
Alpha: 1
Buffer Length: 100
Color: 255; 0; 0
Enabled: true
Name: Robot Path
Offset:
X: 0
Y: 0
Z: 0
Pose Style: Lines
Queue Size: 10
Topic: /odom
Value: true
Width: 0.05
Enabled: true
Global Options:
Background Color: 48; 48; 48
Default Light: true
Fixed Frame: odom
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: false
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
Line color: 128; 128; 0
- Class: rviz/SetInitialPose
Topic: /initialpose
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
Single click: true
Topic: /clicked_point
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 4
Enable Stereo Rendering:
Stereo Eye Separation: 0.06
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Field of View: 0.785398
Focal Point:
X: 0
Y: 0
Z: 0.3
Focal Shape Fixed Size: true
Focal Shape Size: 0.05
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.01
Pitch: 0.5
Target Frame: base_link
Value: Orbit (rviz)
Yaw: 0
Saved: ~
设置文件权限
cd ~/catkin_ws/src/visualization_demo/scripts
chmod +x sensor_simulator.py
chmod +x robot_controller.py
编译包
cd ~/catkin_ws
catkin_make
source devel/setup.bash
运行完整演示
roslaunch visualization_demo demo.launch
RViz (4.1):
rqt_graph (4.2):
/robot_controller → /cmd_vel
/sensor_simulator → /camera/depth/points, /imu/data, /odom, TF
/rviz 订阅所有可视化话题
rqt_plot (4.3):
能够看到这里的观众老爷,无疑是对up的最大肯定和支持,在此恳求各位观众老爷能够多多点赞、收藏和关注。在这个合集中,未来将持续给大家分享关于Docker的多种常见开发实用操作。未来也将继续分享Docker、conda、ROS等等各种实用干货。感谢大家支持!
往期专栏: Ubuntu系列 Docker系列
本期专栏:
ROS系列(一):机器人操作系统终极指南 —— 5大核心组件 × ROS1/ROS2代际革命
ROS系列(二):别光看!5分钟动手搞定ROS第一个机器人 —小乌龟实战