参考链接1
话题中的Publisher与Subscriber
例1: 发送和接收 hello, world
1、创建工作空间
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace
创建完成后,可以在工作空间的根目录下使用catkin_make命令编译整个工作空间:
cd ~/catkin_ws/
catkin_make
编译过程中,在工作空间的根目录里会自动产生build和devel两个文件夹及其中的文件。编译完成后,在devel文件夹中已经产生几个setup.*sh形式的环境变量设置脚本。使用source命令运行这些脚本文件,则工作空间中的环境变量可以生效。
source devel/setup.bash
为了确保环境变量已经生效,可以使用如下命令进行检查:
echo $ROS_PACKAGE_PATH
如果打印的路径中已经包含当前工作空间的路径,则说明环境变量设置成功
2、创建功能包 learning_communication
进入代码空间,使用catkin_create_pkg命令创建功能包
# 命令格式
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp
回到工作空间的根目录下进行编译(命令行cd),并且设置环境变量
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash
3、创建Publisher
Publisher的主要作用是针对 指定话题 发布 特定数据类型 的消息。
创建步骤
·初始化ROS节点。
·向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型。
·按照一定频率循环发布消息。
使用代码实现一个节点,节点中创建一个Publisher并发布字符串“Hello World”
learning_communication\src\talker.cpp
在目录/home/xixi/catkin_ws/src/learning_communication/src 打开命令行
创建一个空白的.cpp文件
touch talker.cpp
输入[复制 ]该代码
#include <sstream>
#include "ros/ros.h" // 包含大部分 ROS 中通用的头文件
#include "std_msgs/String.h" // 节点发布的消息 "Hello World" 为 String 类型
int main(int argc, char **argv)
{
// ROS节点初始化 // 第三个参数定义了Publisher节点的名称,而且该名称在运行的ROS中必须是独一无二的,不允许同时存在相同名称的两个节点。
ros::init(argc, argv, "talker"); // 前两个参数是命令行或launch文件输入的参数,可以用来完成命名重映射等功能
// 创建节点句柄 方便对节点资源的使用和管理
ros::NodeHandle n;
// 创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// 设置循环的频率 Hz
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
// 初始化std_msgs::String类型的消息
std_msgs::String msg;
std::stringstream ss;
ss << "hello, world " << count;
msg.data = ss.str();
// 发布消息
ROS_INFO("%s", msg.data.c_str()); // 类似于C/C++中的printf/cout函数,用来打印日志信息。
chatter_pub.publish(msg); // 发布封装完毕的消息msg
// 循环等待回调函数
ros::spinOnce();
// 按照循环频率延时
loop_rate.sleep(); // 之前设置了10Hz的休眠时间,节点休眠100ms后又会开始下一个周期的循环工作。
++count;
}
return 0;
}
4、创建Subscriber
创建一个Subscriber以订阅Publisher节点发布的“Hello World”字符串
learning_communication\src\listener.cpp
在目录/home/xixi/catkin_ws/src/learning_communication/src 打开命令行
创建一个空白的.cpp文件
touch listener.cpp
输入[复制 ]该代码
#include "ros/ros.h"
#include "std_msgs/String.h"
// 接收到订阅的消息后,会进入消息回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
// 将接收到的消息打印出来
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
// 初始化ROS节点
ros::init(argc, argv, "listener");
// 创建节点句柄
ros::NodeHandle n; // 下一句就用了 n
// 创建一个Subscriber,订阅名为chatter的话题,注册回调函数chatterCallback
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
5、编译功能包
节点的代码已经完成,C++是一种编译语言,在运行之前需要将代码编译成可执行文件,如果使用Python等解析语言编写代码,则不需要进行编译,可以省去此步骤。
ROS中的编译器使用的是CMake,编译规则通过功能包中的CMakeLists.txt
文件设置,使用catkin
命令创建的功能包中会自动生成该文件
打开功能包中的CMakeLists.txt文件,找到以下配置项,去掉注释并稍作修改
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(learning_communication)
include_directories(include ${catkin_INCLUDE_DIRS})
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
CMakeLists.txt修改完成后,在工作空间的根路径下开始编译:
cd ~/catkin_ws
catkin_make
————
报错:
/home/xixi/catkin_ws/src/learning_communication/src/listener.cpp:1:10: fatal error: ros/ros.h: No such file or directory
1 | #include "ros/ros.h"
| ^~~~~~~~~~~
compilation terminated.
解决办法链接
6、运行Publisher与Subscriber
在运行节点之前,需要在终端中设置环境变量,否则无法找到功能包最终编译生成的可执行文件:
cd ~/catkin_ws
source ./devel/setup.bash
也可以将环境变量的配置脚本添加到终端的配置文件中:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
环境变量设置成功后,可以按照以下步骤启动例程。
1.启动roscore
roscore
2.启动Publisher
Publisher和Subscriber节点的启动顺序在ROS中没有要求,这里先使用rosrun命令启动Publisher:
rosrun learning_communication talker
——
报错:
解决办法链接
因为改了 CMakeLists.txt
,返回第5步编译。
————
3.启动Subscriber
Publisher节点已经成功运行,接下来需要运行Subscriber节点,订阅Publisher发布的消息:
rosrun learning_communication listener
—————
例2:自定义话题消息
在ROS的元功能包common_msgs中提供了许多不同消息类型的功能包,如std_msgs(标准数据类型)、geometry_msgs(几何学数据类型)、sensor_msgs(传感器数据类型)等。
learning_communication/msg/Person.msg
新建名为 msg 的文件夹
在该文件夹 中 Open in Terminal
通过下列命令 新建文件 Person.msg
touch Person.msg
Person.msg
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
编译msg文件
(1)在package.xml中添加功能包依赖
首先打开功能包的package.xml文件,确保该文件中设置了以下编译和运行的相关依赖:
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
去掉注释
补充:
<build_depend></build_depend>
标签定义了功能包中代码编译所依赖的其他功能包,而<run_depend></run_depend>
标签定义了功能包中可执行程序运行时所依赖的其他功能包。
(2)在CMakeLists.txt中添加编译选项
打开功能包的CMakeLists.txt文件,在find_package中添加消息生成依赖的功能包message_generation,这样在编译时才能找到所需要的文件:
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
rospy
std_msgs
message_generation
)
catkin依赖也需要进行以下设置:
catkin_package(
……
CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime
……)
最后设置需要编译的msg文件:
add_message_files(
FILES
Person.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
以上配置工作都完成后,就可以回到工作空间的根路径下,使用catkin_make命令进行编译了。
cd ~/catkin_ws
catkin_make
————
报错:
Error(s):
- The manifest of package "learning_communication" (with format version 2) must not contain the following tags: run_depend
- Please replace <run_depend> tags with <exec_depend> tags.
按照提示修改
发现已有,去掉注释即可
报错2:
CMake Error at /opt/ros/noetic/share/catkin/cmake/catkin_package.cmake:196 (message):
catkin_package() the catkin package 'geometry_msgs' has been
find_package()-ed but is not listed as a build dependency in the
package.xml
三件套 安排
报错3:
CMake Error at /opt/ros/noetic/share/genmsg/cmake/genmsg-extras.cmake:197 (message):
generate_messages() must be called before catkin_package() in project
'learning_communication'
Call Stack (most recent call first):
learning_communication/CMakeLists.txt:30 (generate_messages)
-- Configuring incomplete, errors occurred!
调整位置
再次编译
cd ~/catkin_ws
catkin_make
———————————
编译成功后,可以使用如下命令查看自定义的Person消息类型
rosmsg show Person
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(learning_communication)
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
rospy
std_msgs
message_generation
)
include_directories(include ${catkin_INCLUDE_DIRS})
## 位置也挺重要
add_message_files(
FILES
Person.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime)
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
package.xml
<?xml version="1.0"?>
<package format="2">
<name>learning_communication</name>
<version>0.0.0</version>
<description>The learning_communication package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="xixi@todo.todo">xixi</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but multiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/learning_communication</url> -->
<!-- Author tags are optional, multiple are allowed, one per tag -->
<!-- Authors do not have to be maintainers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
<!-- <depend>roscpp</depend> -->
<!-- Note that this is equivalent to the following: -->
<!-- <build_depend>roscpp</build_depend> -->
<!-- <exec_depend>roscpp</exec_depend> -->
<!-- Use build_depend for packages you need at compile time: -->
<build_depend>message_generation</build_depend>
<!-- Use build_export_depend for packages you need in order to build against this package: -->
<build_export_depend>message_generation</build_export_depend>
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use exec_depend for packages you need at runtime: -->
<exec_depend>message_runtime</exec_depend>
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<!-- Use doc_depend for packages you need only for building documentation: -->
<!-- <doc_depend>doxygen</doc_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>geometry_msgs</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<build_export_depend>geometry_msgs</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
服务中的Server和Client
例:加法
本例目标:
Client发布两个需要相加的int类型变量,Server节点接收请求后完成运算并返回加法运算结果。
服务一般分为服务端(Server)和客户端(Client)两个部分,Client负责发布请求数据,等待Server处理;Server负责处理相应的功能,并且返回应答数据。
一般放置在功能包根目录下的srv文件夹中。
若是上述例1中的第1-2步没走,要走一遍。
这里直接从第3步开始
还需要:自定义服务数据
一般放置在功能包根目录下的srv文件夹中。该文件包含请求与应答两个数据域,数据域中的内容与话题消息的数据类型相同,只是在请求与应答的描述之间,需要使用“---
”进行分割。
针对加法运算例程中的服务需求,创建一个定义服务数据类型的srv文件learning_communication/srv/AddTwoInts.srv
创建文件夹 srv
创建文件 AddTwoInts.srv
touch AddTwoInts.srv
AddTwoInts.srv
int64 a
int64 b
---
int64 sum
在功能包的package.xml和CMakeLists.txt文件中配置依赖与编译规则,在编译过程中将该描述文件转换成编程语言所能识别的代码。
打开package.xml文件,添加以下依赖配置
取消相应的注释即可
打开CMakeLists.txt文件,添加如下配置
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
rospy
std_msgs
message_generation
)
add_service_files(
FILES
AddTwoInts.srv
)
编译
cd ~/catkin_ws
catkin_make
报错:
解决办法链接
最终 CMakeLists.txt
在第5步中。
编译成功后,可以使用如下命令查看自定义的AddTwoInts服务类型
rossrv show AddTwoInts
3、创建Server
创建步骤
·初始化ROS节点。
·创建Server实例。
·循环等待服务请求,进入回调函数。
·在回调函数中完成服务功能的处理并反馈应答数据。
首先创建Server节点,提供加法运算的功能,返回求和之后的结果。
learning_communication/src/server.cpp
在目录/home/xixi/catkin_ws/src/learning_communication/src 打开命令行
创建一个空白的.cpp文件
touch server.cpp
输入[复制 ]该代码
#include "ros/ros.h"
#include "learning_communication/AddTwoInts.h" // 必须包含服务数据类型的头文件
// service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,
learning_communication::AddTwoInts::Response &res)
{
// 将输入参数中的请求数据相加,结果放到应答变量中
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.sum);
return true;
}
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "add_two_ints_server");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个名为add_two_ints的server,注册回调函数add()
ros::ServiceServer service = n.advertiseService("add_two_ints", add);
// 循环等待回调函数
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
4、创建Client
创建流程
·初始化ROS节点。
·创建一个Client实例。
·发布服务请求数据。
·等待Server处理之后的应答结果。
创建Client节点,通过终端输入的两个加数发布服务请求,等待应答结果
learning_communication/src/client.cpp
创建一个空白的.cpp文件
touch client.cpp
输入[复制 ]该代码
#include <cstdlib>
#include "ros/ros.h"
#include "learning_communication/AddTwoInts.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "add_two_ints_client");
// 从终端命令行获取两个加数
if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y");
return 1;
}
// 创建节点句柄
ros::NodeHandle n;
// 创建一个client,请求add_two_int service
// service消息类型是learning_communication::AddTwoInts
ros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts> ("add_two_ints");
// 创建learning_communication::AddTwoInts类型的service消息
learning_communication::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
// 发布service请求,等待加法运算的应答结果
if (client.call(srv))
{
ROS_INFO("Sum: %ld", (long int)srv.response.sum);
}
else
{
ROS_ERROR("Failed to call service add_two_ints");
return 1;
}
return 0;
}
5、编译功能包 CMakeLists.txt
接下来编辑CMakeLists.txt文件
cmake_minimum_required(VERSION 2.8)
project(learning_communication)
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
rospy
std_msgs
message_generation
)
include_directories(include ${catkin_INCLUDE_DIRS})
#[[
## 位置也挺重要 自定义 话题消息
add_message_files(
FILES
Person.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
]]
# 自定义 服务 数据
add_service_files(
FILES
AddTwoInts.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime)
#[[
# 话题
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
]]
## 服务中的Server和Client
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)
add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)
cd ~/catkin_ws
catkin_make
6、运行Server和Client
1.启动roscore
roscore
2.运行Server节点
rosrun learning_communication server
3.运行Client节点
打开一个新的终端,运行Client节点,同时需要输入加法运算的两个加数值:
rosrun learning_communication client 3 5
实现TF的广播和监听功能。
参考链接 Plus
例:小乌龟跟随移动
仍是第一步创建工作空间
第二步 创建功能包
这里从第2步开始
2、创建功能包 learning_tf
进入代码空间,使用catkin_create_pkg命令创建功能包
# 命令格式
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
cd ~/catkin_ws/src
catkin_create_pkg learning_tf roscpp rospy tf turtlesim
回到工作空间的根目录下进行编译(命令行cd),并且设置环境变量
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash
3、创建TF广播器
创建一个发布乌龟坐标系与世界坐标系之间TF变换的节点
learning_tf/src/turtle_tf_broadcaster.cpp
touch turtle_tf_broadcaster.cpp
#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>
std::string turtle_name;
void poseCallback(const turtlesim::PoseConstPtr& msg)
{
// TF广播器
static tf::TransformBroadcaster br;
// 根据乌龟当前的位姿,设置相对于世界坐标系的坐标变换
tf::Transform transform;
transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
tf::Quaternion q;
q.setRPY(0, 0, msg->theta);
transform.setRotation(q);
// 发布坐标变换
br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}
int main(int argc, char** argv)
{
// 初始化节点
ros::init(argc, argv, "my_tf_broadcaster");
if (argc != 2)
{
ROS_ERROR("need turtle name as argument");
return -1;
};
turtle_name = argv[1];
// 订阅乌龟的pose信息
ros::NodeHandle node;
ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
ros::spin();
return 0;
};
4、创建TF监听器
TF消息广播之后,其他节点就可以监听该TF消息,从而获取需要的坐标变换了。目前我们已经将乌龟相对于world坐标系的TF变换进行了广播,接下来需要监听TF消息,并从中获取turtle2相对于turtle1坐标系的变换,从而控制turtle2移动。
learning_tf/src/turtle_tf_listener.cpp
touch turtle_tf_listener.cpp
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
// 初始化节点
ros::init(argc, argv, "my_tf_listener");
ros::NodeHandle node;
// 通过服务调用,产生第二只乌龟turtle2
ros::service::waitForService("spawn");
ros::ServiceClient add_turtle =
node.serviceClient<turtlesim::Spawn>("spawn");
turtlesim::Spawn srv;
add_turtle.call(srv);
// 定义turtle2的速度控制发布器
ros::Publisher turtle_vel =
node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
// TF监听器
tf::TransformListener listener;
ros::Rate rate(10.0);
while (node.ok())
{
tf::StampedTransform transform;
try
{
// 查找turtle2与turtle1的坐标变换
listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros:: Duration(3.0));
listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
}
catch (tf::TransformException &ex)
{
ROS_ERROR("%s",ex.what());
ros::Duration(1.0).sleep();
continue;
}
// 根据turtle1和turtle2之间的坐标变换,计算turtle2需要运动的线速度和角速度
// 并发布速度控制指令,使turtle2向turtle1移动
geometry_msgs::Twist vel_msg;
vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
transform.getOrigin().x());
vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
pow(transform.getOrigin().y(), 2));
turtle_vel.publish(vel_msg);
rate.sleep();
}
return 0;
};
52、编辑并编译launch文件
到目前为止,在教程中,一直在为运行的每个新节点打开新终端。当创建越来越多的节点同时运行更复杂的系统时,打开终端并重新输入配置详细信息将变得乏味和低效。 launch文件将需要启动的节点写在一个launch文件中,通过在终端中运行launch文件,就可以同时启动多个节点,解决了以往需要打开多个终端不断输入指令的麻烦。
关于launch 参考链接
learning_tf/launch/start_demo_with_listener.launch
新建文件夹 launch
新建文件 start_demo_with_listener.launch
touch start_demo_with_listener.launch
<launch>
<!-- 海龟仿真器 -->
<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
<!-- 键盘控制 -->
<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
<!-- 两只海龟的TF广播 -->
<node pkg="learning_tf" type="turtle_tf_broadcaster"
args="/turtle1" name="turtle1_tf_broadcaster" />
<node pkg="learning_tf" type="turtle_tf_broadcaster"
args="/turtle2" name="turtle2_tf_broadcaster" />
<!-- 监听TF广播,并且控制turtle2移动 -->
<node pkg="learning_tf" type="turtle_tf_listener"
name="listener" />
</launch>
roscore
roslaunch learning_tf start_demo_with_listener.launch
启动键盘控制 小乌龟 移动
rosrun turtlesim turtle_teleop_key
launch 补充
一次性启动所有节点
# 结点 定义
<node pkg="package-name" type="executable-name" name="node-name" />
<param name="output_frame" value="odom"/>
<rosparam file="$(find 2dnav_pr2)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
<arg name="arg-name" default= "arg-value"/>
<param name="foo" value="$(arg arg-name)" />
<node name="node" pkg="package" type="type " args="$(arg arg-name)" />
重映射
别人功能包的接口与系统不兼容时
<remap from="/turtlebot/cmd_vel" to="/cmd_vel"/>
嵌套复用
<include file="$(dirname)/other.launch" />
http://wiki.ros.org/roslaunch/XML
————————
CMake方法要打开N个终端,弃了 ——> 改launch
实在好奇,可参考这里
51、编译功能包 CMakeLists.txt
接下来编辑CMakeLists.txt文件
add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
cd ~/catkin_ws
catkin_make
6、运行TF广播和监听【这里不完整】
1.启动roscore
roscore
启动海龟结点
//新建终端
rosrun turtlesim turtlesim_node
2.运行TF广播
rosrun learning_tf turtle_tf_broadcaster
3.运行TF监听
rosrun learning_tf turtle_tf_listener
rosbag 录制与回放
例: rosbag 录制与回放 小乌龟轨迹
启动键盘控制乌龟例程所需的所有节点
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
查看在当前ROS系统中到底存在哪些话题
rostopic list -v
使用rosbag抓取这些话题的消息,并且打包成一个文件放置到指定文件夹中:
可以在习惯的地方创建一个bagfiles文件,
Open in Terminal
。运行第3句即可
mkdir ~/bagfiles
cd ~/bagfiles
rosbag record -a # 记录所有消息 all
不要画很复杂的,不然回放也会要比较久。
在终端中控制小乌龟移动一段时间,然后在数据记录运行的终端中按下“Ctrl+C
”,即可终止数据记录
。
关闭所有终端。
————————————
重启turtlesim_node
roscore
rosrun turtlesim turtlesim_node
查看数据
若是生成的bag后缀多了 .active。还需要进一步处理
# rosbag reindex xxx.bag.active;
# 等待修复,按照录制包的大小时间可能长也可能短
# rosbag fix xxx.bag.active result.bag;
# 等待生成结果包,也就是result.bag,不要强制结束,可能会比较长,我怀疑是重跑了一遍rosbag play
rosbag reindex 2023-10-11-11-09-06.bag.active
rosbag fix 2023-10-11-11-09-06.bag.active xiaowugui.bag # 趁机改名
查看 bag 的信息
rosbag info xiaowugui.bag
回放所记录的话题数据
rosbag play xiaowugui.bag
注意有一小段切换时间,因为录制的时候也不是一运行录制命令就马上开始控制小乌龟。如果轨迹很长,稍等。