ROS1学习(入门)
一、搭建工作环境
1.检查环境:
- 确保ROS_ROOT和ROS_PACKAGE_PATH两个环境变量正确设置
$ printenv | grep ROS (无回应要重新source)
2.设置环境:
- 下面的命令在每次启动新的shell窗口都会自动source
echo “source /opt/ros/noetic/setup.bash” >> ~/.bashrc
source ~/.bashrc
3.创建ROS工作空间:
- 创建workstation
$ mkdir -p ~/catkin_ws/src
$ cd ~/catkin_ws/
$ catkin_make
4.确定搭建完成:
- 保证工作区被安装脚本覆盖,需要确定ROS_PACKAGE_PATH环境变量包含当前工作空间目录:
$ echo $ROS_PACKAGE_PATH
返回/home//catkin_ws/src:/opt/ros/ /share,说明环境搭建完成
二、文件系统工具
1.rospack find [package_name]
- 查找软件包路径
2.roscd
ROS中的其它工具一样,roscd只能切换到那些路径已经包含在ROS_PACKAGE_PATH环境变量中的软件包。要查看 ROS_PACKAGE_PATH中包含的路径,可以输入:
$ echo $ROS_PACKAGE_PATH
已运行过ROS程序,可以使用roscd log进入存储ROS日志文件的目录
$ roscd log
3.rosls
- 同shell命令ls
三、catkin软件包(包含package.xml和CMakeLists.txt)
构建ROS工作空间后,系统会在devel/目录下生成类似/opt/ros/noetic的环境配置文件setup.bash,为了使ROS能够找到编译的包,需要source setup.bash (提供ROS系统级的环境变量)
1.source方法
- 临时生效
$ source ~/catkin_ws/devel/setup.bash
- 永久生效
$ echo “source ~/catkin_ws/devel/setup.bash” >> ~/.bashrc
$ source ~/.bashrc - 多工作空间管理(多个工作空间。后source的会覆盖之前的,如果想要叠加多个工作空间)
$ source ~/catkin_ws1/devel/setup.bash –extend
$ source ~/catkin_ws2/devel/setup.bash –extend
2.软件包依赖关系
$ rospack depends1 beginner_tutorials (查看一级依赖包)
$ rospack depends1 rospy(查看所有嵌套的依赖包)
3.package.xml结构
- 文本打开后除了前面最基本的维护解释外,最底端有运行时依赖的详细说明
各标签作用说明:
四、编译ROS软件包
安装完所有依赖,就可以编译软件包(apt等其他管理器会自动安装所有依赖项)
- 注:未设置环境需先source
$ source /opt/ros/
/setup.bash
1.使用catkin_make(标准CMake工作流程中依次调用 cmake和make)
- 在catkin工作空间下
$ catkin_make [make_targets] [-DCMAKE_VARIABLES=…]
2.标准CMake工作流程
- 在CMake工作空间下
$ mkdir build $ cd build $ cmake .. $ make $ make install # (可选) - 若要编译src目录下所有catkin项目:
在catkin工作空间下$ catkin_make --source my_src $ catkin_make install --source my_src # (可选)
3.编译之前创建的pkg(catkin工作空间下)
$ catkin_make
五、ROS节点
基本概念:计算图(Computation Graph)是一个由ROS进程组成的点对点网络,它们能够共同处理数据。ROS的基本计算图概念有节点(Nodes)、主节点(Master)、参数服务器(Parameter Server)、消息(Messages)、服务(Services)、话题(Topics)和袋(Bags),它们都以不同的方式向图(Graph)提供数据。
- 使用ROS客户端库与其他节点通信,rospy、roscpp
六、roscore
运行所有ros程序前要运行的命令
- 初始化
$ roscore
- 提示缺少权限,则用下列命令更改目录所有权:
$ sudo chown -R
<your_username>~/.ros - 网络设置问题参考https://wiki.ros.org/ROS/NetworkSetup#Single_machine_configuration
七、rosnode & rosrun
- 使用rosnode显示当前正在运行的ros节点信息
$ rosnode list (列出活动节点)
$ rosnode info (返回某个指定节点的信息) - 用包名直接运行软件包内节点(无需知道路径)
$ rosrun [package_name] [node_name]
- ros强大功能可通过命令行重新分配名称
$ rosrun turtlesim turtlesim_node _name:=myturtle
八、ROS话题
- turtlesim_node节点和turtle_teleop_key之间以ROS话题来相互通信。使用rqt_graph来显示当前节点和话题
$ rosrun rqt_graph rqt_graph

- 使用帮助选项(-h)查看可用的rostopic的子命令
$ rostopic -h

- 能够查看节点的”指令、速度“数据
$ rostopic echo [topic]
- rostopic list 可以列出当前被订阅和发布的所有话题
其中verbose选项(-v)会列出所有发布和订阅的主题以及类型的详细信息。
九、ROS消息
- 查看所发布话题的消息类型
$ rostopic type [topic]
- 查看消息的详细信息
$ rosmsg show [type]
进一步学习
- rostopic pub [topic] [msg_type] [args] 能够将数据发布到正在广播的话题上
$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist – ‘[2.0, 0.0, 0.0]’ ‘[0.0, 0.0, 1.8]’
以上命令会发送一条消息给turtlesim,告诉它以2.0大小的线速度和1.8大小的角速度移动。 - rostopic hz[topic] 报告数据发布的速率
$ rostopic hz /turtle1/pose (小乌龟程序速率)
- rqt_plot 绘制正在发布到话题的数据
$ rosrun rqt_plot rqt_plot
十、ROS服务和参数
服务允许节点发送一个请求(request)并获得一个响应(response)
1.rosservice

显示节点服务:rosservice list
$ rosservice list
查看服务的用法 rosservice type
$ rosservice type
比如查看clearn服务的类型
$ rosservice type /clear
输出std_srvs/Empty 说明调用该服务不需要参数
2.rosservice call
- 用法: rosservice call [service][args]
args(参数的意思) - 由于/clear的类型为empty,无需参数调用,会清除turtlesim_node背景的轨迹:
$ rosservice call /clear
- 尝试有参数的服务,如spawn(产卵),先查看参数
$ rosservice type /spawn | rossrv show
- 不设置具体名字,让turtsim自动创建
$ rosservice call /spawn 2 2 0.2 “”
3.使用rosparam
rosparam能让我们在ROS参数服务器(Parameter Server)上存储和操作数据。参数服务器能够存储整型(integer)、浮点(float)、布尔(boolean)、字典(dictionaries)和列表(list)等数据类型。rosparam使用YAML标记语言的语法。一般而言,YAML的表述很自然:1是整型,1.0是浮点型,one是字符串,true是布尔型,[1, 2, 3]是整型组成的列表,{a: b, c: d}是字典。
- rosparam有很多命令可以用来操作参数,如下所示:

- rosparam list(输出的最下端会出现参数)
$ rosparam list
4.rosparam set 和 rosparam get
- 用法:
rosparam set [param_name]
rosparam get [param_name] - 修改参数值
$ rosparam set /turtlesim/background_r 150
- 修改参数值后调用clear服务使参数修改生效:
$ rosservice call /clear
- 查看服务器其他参数值,比如获取背景的绿色通道的值:
$ rosparam get /turtlesim/background_g
- 也可以使用rosparam get /来显示参数服务器上的所有内容:
$ rosparam get /
5.rosparam dump和rosparam load
- 用法:
rosparam dump [file_name] [namespace]
rosparam load [file_name] [namespace] - 将所有参数写入params.yaml文件:
$ rosparam dump params.yaml
- 将yaml文件重新载入新的命名空间,例如copy_turtle:
$ rosparam load params.yaml copy_turtle
$ rosparam get /copy_turtle/turtlesim/background_b
6.使用rqt_console和rqt_logger_level
rqt_console连接ROS日志框架,可以显示节点输出
$ rosrun rqt_console rqt_console
rqt_logger_level允许在节点运行时改变输出信息的详细级别,包括Debug、Info、Warn和Error`
$ rosrun rqt_logger_level rqt_logger_level

十一、roslaunch
roslaunch可以用来启动定义在launch(启动)文件中的节点,用法:
$ roslaunch [package] [filename.launch]
先切到创建和构建的beginner_tutorials软件包目录下:
$ roscd beginner_tutorials
!!!如果roscd提示类似于roscd: No such package/stack ‘beginner_tutorials’的话,你需要按照创建catkin工作空间后面的步骤使环境变量生效:
$ cd ~/catkin_ws
$ source devel/setup.bash
$ roscd beginner_tutorials创建一个launch目录:
$ mkdir launch
$ cd launch注:roslaunch会自动查找经过的包并检测可用启动文件。
launch文件
创建一个turtlemimic.launch的launch文件:
$ touch turtlemimic.launch
launch文件内会定义各节点
使用roslaunch
$ roslaunch beginner_tutorials turtlemimic.launch
话题发布:
$ rostopic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/Twist -r 1 – ‘[2.0, 0.0, 0.0]’ ‘[0.0, 0.0, -1.8]’
然后双龟转圈,虽然命令只发布给turtlesim1
十二、用rosed编辑文件
是rosbash套件一部分,可以直接通过软件包名编辑包中文件,无需键入完整路径,其用法:
$ rosed [package_name] [filename]
更改默认编辑器,可以在~/.bashrc文件中加入这一行
export EDITOR=’nano -w’
注:.bashrc文件的改变只对新打开的终端有效。之前已经打开的终端不受更改环境变量的影响。
十三、创建ROS消息和服务
msg和srv介绍
- msg(消息):描述ROS消息的文本文件。为不同编程语言编写的消息生成源代码
srv(服务):描述服务,由请求和响应两部分组成。
ROS特殊数据类型:Header,含有时间戳和ROS广泛使用的坐标帧信息
srv文件和msg文件一样,只是它们包含两个部分:请求和响应。这两部分用一条—线隔开。
使用msg
- 创建msg
$ roscd beginner_tutorials
$ mkdir msg
$ echo “int64 num” > msg/Num.msg
关键步骤(确保msg文件能转换为其他语言的源代码):
- 打开package.xml, 确保它包含以下两行且没有被注释,如果没有,添加进去:
<build_depend>message_generation</build_depend><exec_depend>message_runtime</exec_depend>
注:在构建时,其实只需要message_generation,而在运行时,我们只需要message_runtime。在CMakeLists.txt中,为已经存在里面的find_package调用添加message_generation依赖项,这样就能生成消息了。直接将message_generation添加到COMPONENTS列表中即可。有时即使没有使用全部依赖项调用find_package,项目也可以构建。这是因为catkin把你所有的项目整合在了一起,因此如果之前的项目调用了find_package,你的依赖关系也被配置成了一样的值。但是,忘记调用意味着你的项目在单独构建时很容易崩溃。
找到如下代码块:

删除#符号来取消注释,然后将Message*.msg替换为你的.msg文件名手动添加完.msg文件后,需要确保CMake知道何时重新配置项目,必须确保generate_messages()函数被调用,需要取消下面几行的注释:

使用rosmsg
rosmsg show命令可以看ROS能否识别它$ rosmsg show [message type]
$ rosmsg show beginner_tutorials/Num
消息类型包含两部分(定义消息的软件包和消息的名称)
使用srv
- 创建srv:从另一个包复制现有的srv定义,而不是手动创建新的srv。roscp是一个实用的命令行工具,用于将文件从一个包复制到另一个包。
$ roscp [package_name] [file_to_copy_path] [copy_path]
可以从rospy_tutorials包中复制一个服务:
$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
打开package.xml,做之前msg的同样步骤,修改CMakelist.txt服务字段不同,删除#符号来取消注释,然后将Service*.srv替换为.srv文件名
之后就可以从srv文件定义生成源代码文件
- 使用rossrv:(看看ROS能否识别它)
$ rossrv show
例子:$ rossrv show beginner_tutorials/AddTwoInts
同rosmsg,可以在不指定包名下找到服务。
取消generate_messages注释之后重新make一下软件包
- ws里执行catkin_make
msg目录中的任何.msg文件都将生成所有支持语言的代码。C++消息的头文件将生成在 /catkin_ws/devel/include/beginner_tutorials/。Python脚本将创建在/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg。而Lisp文件则出现在/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/。类似地,srv目录中的任何.srv文件都将生成支持语言的代码。对于C++,头文件将生成在消息的头文件的同一目录中。对于Python和Lisp,会在msg目录旁边的srv目录中。
注:构建c++节点,需要声明节点和消息之间的依赖关系
获得ros工具帮助
- show(查看一系列子命令)
- show -h(显示所需要的参数)
十四、编写简单的发布者和订阅者(python)
- 首先要回到pkg包中:
$ roscd beginner_tutorials
1.发布者节点
首先创建scripts目录存放python脚本
下载示例脚本talker.py到scripts目录并给执行权限:
$ wget https://raw.github.com/ros/ros_tutorials/noetic-devel/rospy_tutorials/001_talker_listener/talker.py
若遇到网络问题,请打开上面文件的链接并复制文本内容到talker.py文件中
$ chmod +x talker.py暂时不运行,先用rosed查看编辑这个软件:
$ rosed beginner_tutorials talker.py
将下列内容添加到CMakeLists.txt文件,确保正确安装python脚本,使用合适python编译器
catkin_install_python(PROGRAMS scripts/talker.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} )
发布者节点代码解释参考https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28python%29
需要引入rospy、std_msgs.msg库的导入
定义接口:
pub = rospy.Publisher(‘chatter’, String, queue_size=10)
告诉rospy节点名称(基本名称),才能与主节点进行通信,anonymous=ture让名称末尾添加随机数,使节点具有唯一的名称(初始化ROS节点参考https://wiki.ros.org/rospy/Overview/Initialization%20and%20Shutdown#Initializing_your_ROS_Node)
rospy.init_node(‘talker’, anonymous=True)
设置频率
rate=rsopy.rate(10)
一个标准的rospy结构:
while not rospy.is_shutdown(): hello_str = "hello world %s" % rospy.get_time() rospy.loginfo(hello_str) pub.publish(hello_str) rate.sleep()rate.sleep(),它在循环中可以用刚刚好的睡眠时间维持期望的速率。
rospy.loginfo(str),它有3个任务:打印消息到屏幕上;把消息写入节点的日志文件中;写入rosout。可以使用rqt_console来拉取消息
std_msgs.msg.String是一个非常简单的消息类型,更复杂的类型则是构造函数参数的顺序与.msg文件中的顺序相同。也可以不传入任何参数,直接初始化字段,例如:
>msg = String() msg.data = str或者只初始化某些字段,并将其余字段保留为默认值:
String(data=str)
2.订阅者节点
下载示例脚本listener.py放到scripts目录中并给执行权限:
$ roscd beginner_tutorials/scripts/
$ wget https://raw.github.com/ros/ros_tutorials/noetic-devel/rospy_tutorials/001_talker_listener/listener.py # 若遇到网络问题,请打开上面文件的链接并复制文本内容到listener.py文件中
$ chmod +x listener.py同样编辑CMakeLists.txt,找到catkin_install_python()调用,如下:
catkin_install_python(PROGRAMS scripts/talker.py scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
订阅者节点代码解释:参考https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28python%29
与发布者相似但引入一种新的基于回调的机制:
rospy.init_node(‘listener’, anonymous=True)
rospy.Subscriber(“chatter”, String, callback)
spin() 可以让代码在结束前不会自动停止
rospy.spin()构建节点
回到catkin工作空间,运行catkin_make
检验简单的发布者和订阅者(python)
首先打开roscore
然后 source setup.bash文件
- 运行发布者
rosrun beginner_tutorials talker.py
- 运行订阅者:
rosrun beginner_tutorials listener.py
十五、编写简单的服务和客户端(python)
1.编写服务节点:add_two_ints_server
该节点将接收两个整数,返回它们之和
$ roscd beginner_tutorials
在此之前要创建本教程需要的服务AddTwoInts.srv(先前教程已经提供)
粘贴代码
#!/usr/bin/env python from __future__ import print_function from beginner_tutorials.srv import AddTwoInts,AddTwoIntsResponse import rospy def handle_add_two_ints(req): print("Returning [%s + %s = %s]"%(req.a, req.b, (req.a + req.b))) return AddTwoIntsResponse(req.a + req.b) def add_two_ints_server(): rospy.init_node('add_two_ints_server') s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints) print("Ready to add two ints.") rospy.spin() if __name__ == "__main__": add_two_ints_server()给节点执行权限:
$ chmod +x scripts/add_two_ints_server.py
将下列内容添加到CMakeLists.txt文件,确保正确安装python脚本,使用合适python编译器:
catkin_install_python(PROGRAMS scripts/add_two_ints_server.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
解释:
- 使用rospy编写服务的难度非常小,我们使用init_node()声明我们的节点,然后声明服务:
s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints) - 这声明了一个名为add_two_ints的新服务,其服务类型为AddTwoInts。所有的请求(request)都传递给了handle_add_two_ints函数。handle_add_two_ints被AddTwoIntsRequest的实例调用,返回AddTwoIntsResponse实例。同订阅者中的例子一样,rospy.spin()可以防止代码在服务关闭之前退出。
2.编写客户端节点:add_two_ints_client
创建scripts/add_two_ints_client.py,粘贴客户端代码进去:
代码:
#!/usr/bin/env python from __future__ import print_function import sys import rospy from beginner_tutorials.srv import * def add_two_ints_client(x, y): rospy.wait_for_service('add_two_ints') try: add_two_ints = rospy.ServiceProxy('add_two_ints', AddTwoInts) resp1 = add_two_ints(x, y) return resp1.sum except rospy.ServiceException as e: print("Service call failed: %s"%e) def usage(): return "%s [x y]"%sys.argv[0] if __name__ == "__main__": if len(sys.argv) == 3: x = int(sys.argv[1]) y = int(sys.argv[2]) else: print(usage()) sys.exit(1) print("Requesting %s+%s"%(x, y)) print("%s + %s = %s"%(x, y, add_two_ints_client(x, y)))给节点执行权限:
$ chmod +x scripts/add_two_ints_client.py
同样在CMakeLists.txt中编辑catkin_install_python()调用:
catkin_install_python(PROGRAMS scripts/add_two_ints_server.py scripts/add_two_ints_client.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)代码解释:
对客户端来说不需要调用init_node(),首先调用:
rospy.wait_for_service(‘add_two_ints’)
这可以让在add_two_ints服务可用之前一直阻塞。为服务的调用创建一个句柄(handle):
add_two_ints = rospy.ServiceProxy(‘add_two_ints’, AddTwoInts)
之后就可以像函数一样调用:
resp1 = add_two_ints(x, y)
return resp1.sum
至此已经将服务的类型声明为AddTwoInts,它会生成AddTwoIntsRequest对象 (you’re free to pass in your own instead)。如果调用失败,rospy.ServiceException将会抛出。
最后,运行catkin_make
检验简单的服务和客户端
- rosrun
$ rosrun beginner_tutorials add_two_ints_server.py # (Python)
- 客户端在运行时需要附带必要的参数:
$ rosrun beginner_tutorials add_two_ints_client.py 1 3 # (Python)
十六、录制和回放数据
将正在运行的ROS系统中的数据记录到一个bag文件中,通过回放来重现相似的运行过程。
1.录制数据
- 终端1:
$ roscore
- 终端2:
$ rosrun turtlesim turtlesim_node
- 终端3:
$ rosrun turtlesim turtle_teleop_key
2.录制所有发布的话题:
新终端:
$ rostopic list -v
已发布主题的列表是唯一可能被记录在数据日志文件中的消息类型,因为只有发布的消息才能被录制。
记录发布的数据。打开一个新终端:
$ mkdir ~/bagfiles
$ cd ~/bagfiles
$ rosbag record -a在运行rosbag record的窗口中按Ctrl+C以退出。现在查看~/bagfiles目录中的内容,会看到一个以年份、日期和时间开头且扩展名是.bag的文件。这就是传说中的袋文件,
3.检查并回放bag文件
检查:
$ rosbag info
回放:
$ rosbag play
可以通过-s参数选项让rosbag play不从bag文件的开头开始,而是从某个指定的时间开始。还有-r选项,它允许你通过设定一个参数来改变消息发布速率。
$ rosbag play -r 2
4.录制数据子集:
rosbag record命令支持只录制特定的话题到bag文件中
- 在bag文件所在目录下执行以下命令:
$ rosbag record -O subset /turtle1/cmd_vel /turtle1/pose
命令中的-O参数告诉rosbag record将数据记录到名为subset.bag的文件中,而后面的topic参数告诉rosbag record只能订阅这两个指定的话题。然后通过键盘控制乌龟随意移动几秒钟,最后按Ctrl+C退出rosbag record命令。
rosbag录制和回放的有局限性
十七、从bag文件中读取信息:
1.立即回放消息并在多个终端中查看输出
首先需要一个袋(bag)文件,可以按照之前的,也可以下载一个
$ wget https://open-source-webviz-ui.s3.amazonaws.com/demo.bag
立即回复消息并在多个终端中查看输出
$ time rosbag info demo.bag
或者你已经知道话题名称的话:
$ time rosbag info mybag.bag | grep -E “(topic1|topic2|topic3)”
订阅/obs1/gps/fix话题并复读该话题上发布的所有内容,同时用tee命令转储到一个yaml格式的文件中以便之后查看:
$ rostopic echo /obs1/gps/fix | tee topic1.yaml
每个话题都必须有自己的终端(单独打开),再打开另一个新终端来回放bag文件。这一次我们将尽可能快地回放bag文件(使用–immediate选项),只会发布我们感兴趣的话题。格式如下:
$ time rosbag play –immediate demo.bag –topics /topic1 /topic2 /topic3 /topicN
如果由于一些原因某个rostopic进程丢失了消息,可以使用Ctrl+C终止该进程,然后重新启动它,并再次调用rosbag play命令。
2.使用ros_readbagfile脚本轻松地提取感兴趣的话题
可以kill任何正在运行的进程。比如说连roscore都不需要运行。
下载并安装
ros_readbag.py:运行权限
chmod +x ros_readbagfile.py
建立单独的目录
$ mkdir -p ~/bin
将代码放入特定的目录,方便运行
mv ros_readbagfile.py ~/bin/ros_readbagfile
重新source
. ~/.bashrc
使用ros_readbagfile,大体格式如下:
ros_readbagfile <mybagfile.bag> [topic1] [topic2] [topic3] […]
尽管最终yaml文件中存储的每条消息都是有效的YAML语法,但是消息之间的标题和行分隔符(例如=====)不是有效的。也可以很容易地修改ros_readbagfile这个Python脚本来删除这些非YAML特性。
3.为什么用ros_readbagfile而不是rostopic echo -b呢?
其一:rostopic极慢:time rostopic echo -b large_bag_file.bag /topic1
其二:因为rostopic一次只能读取单个话题,而ros_readbagfile可以同时读取任意多的话题!
十八、roswtf入门
开始本教程之前,请确保roscore没有运行。
$ ps -ef | grep -i rosmaster
如果看到包含rosmaster的一行目录,说明roscore正在运行
1.安装检查:
$ roscd rosmaster
$ roswtf如果你的ROS安装没问题,应该会看到一些输出信息,其中含义如下:
Package: rosmaster:roswtf使用当前目录中的任何内容来确定其执行的检查。这个输出告诉我们是在包rosmaster的目录中启动了roswtf。
Static checks summary:它会报告任何关于文件系统或非运行时(比如无需roscore的场景)的问题。本例显示我们没有错误。
ROS Master does not appear to be running.:roscore未在运行。roswtf不会做任何ROS在线检查。
2.在线检查:
$ roscd
$ roswtf
roswtf发出警告,说明rosout节点订阅了一个没有节点向其发布的话题。但在本例中,除了roscore没有任何其它节点在运行,所以我们可以忽略该警告。
3.一些错误:
- roswtf会对一些系统中看起来异常但可能是正常的运行情况发出警告。也会对确实有问题的情况报告错误。接下来我们给ROS_PACKAGE_PATH环境变量设置一个bad值,并退出roscore以简化检查输出信息。
$ roscd
$ ROS_PACKAGE_PATH=bad:$ROS_PACKAGE_PATH roswtf
如果被构建或通信的问题为难,可以尝试运行roswtf来指明正确的方向。
最后:探索ROS维基和更多的学习 https://wiki.ros.org/cn/ROS/Tutorials/NavigatingTheWiki
最后编辑:zhangjn 更新时间:2025-04-13 15:00
