一、安装ros环境
学长快速安装包
二、概念解释
1、话题
话题用于发布者和订阅者之间的通信。发布者消息发布到指定的话题上,而订阅者则订阅这些话题以接收和处理这些消息。
ROS中的话题发布者和订阅者不需要同时运行,它们可以在不同的时间节点上发布和接收消息。话题还提供了消息的持久性,即使订阅者在消息发布时并未运行,它也可以在稍后从话题中读取这些消息。
2、服务
服务在ROS中用于需要即时结果或需要确认的请求。
ROS中的服务是一种同步、请求-响应式的通信机制,用于需要即时结果或确认的请求。它由两部分组成:请求(Request)和响应(Response),允许节点之间发送请求并接收响应。即一个节点发送请求,并等待另一个节点处理该请求并返回响应。
请求:是发送方发送给接收方的数据
响应:是接收方处理请求后返回给发送方的数据。
服务的这种请求-响应模式使得通信更加直接和明确。
(在ROS中,服务和话题各有其适用的场景。话题适用于需要持续、实时数据传输的场景,如传感器数据的发布和订阅。而服务则适用于需要同步、即时响应的场景,如请求某个节点的状态或执行某个动作。)
3、动作
动作是ROS中另一种通信机制,主要用于管理机器人的完整行为流程。它与服务类似,也是基于客户端-服务端模型。客户端发送动作的目标给服务端,服务端则执行该动作,控制机器人达到目标,并在执行过程中周期性地反馈状态。
动作特别适用于需要长时间响应并且需要中途反馈的场景。与服务相比,动作在执行过程中可以定期返回执行状态,这使得动作更适合处理复杂、长时间运行的任务。
动作文件的结构包含目标(goal)、结果(result)和反馈(feedback)三个部分。其中,目标是客户端发送给服务端的动作指令,结果是服务端执行动作后的输出结果,而反馈则是服务端在执行动作过程中定期发送给客户端的状态信息。
总的来说,ROS中的动作是一种应用层的通信机制,它基于话题和服务实现,特别适用于需要长时间响应和中途反馈的机器人行为管理。
三、配置C++的catkin工作空间
1、初始化catkin工作空间
输入下列指令,完成初始创建
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make #初始化工作空间
注意:
1. catkin_make命令必须在工作空间这个路径上执行
2.原先的初始化命令catkin_init_workspace仍然保留
2、package的创建
在catkin_ws/src下用到catkin_create_pkg命令,
语法:catkin_create_pkg package depends
(其中package是包名,depends是依赖的包名,可以依赖多个软件包)
输入命令:
catkin_create_pkg test_pkg roscpp rospy std_msgs
四、练习
(1) 实验 1:
使用 ROS 话题(Topic) 机制实现消息发布与订阅
要求:编写代码实现 ROS 中消息的发布与订阅: 创建一个发布者,每隔 100ms 依次发送斐波拉契数列的数字到话题/fibonacci 中;创建一个订阅者,订阅该话题,输出订阅结果。如,订阅者依次输出: 1 1 2 3 5 8 ··
1、运行ros,输入命令
roscore
2、创建包:svepana
cd catkin_ws/scr
catkin_create_pkg svepana roscpp rospy std_msgs
3、将程序写到svepana的scr
(创建文件)
cd svepana/scr
gedit fibonacci_publisher.cpp
gedit fibonacci_subscriber.cpp
将写好的代码分别存入这两个创建好的文件
(代码有借鉴其他人的)
发布者节点(fibonacci_publisher.cpp)
#include <ros/ros.h> // 包含ROS基础库的头文件
#include <std_msgs/Int32.h> // 包含ROS标准消息类型的头文件,用于发布Int32类型的消息
// 定义一个FibonacciPublisher类,用于发布斐波那契数列
class FibonacciPublisher {
public:
// 构造函数
FibonacciPublisher() {
// 初始化ROS节点句柄
// 创建一个发布者对象,发布名为"fibonacci"的话题,队列长度为1000
pub_ = n_.advertise<std_msgs::Int32>("fibonacci", 1000);
// 初始化斐波那契数列的前两个数字
fib_seq_.push_back(0);
fib_seq_.push_back(1);
// 设置索引,指向斐波那契数列的下一个要发布的数字
index_ = 1;
}
// 发布斐波那契数列的函数
void publishFibonacci() {
// 设置发布频率为10Hz,即每100ms发布一次消息
ros::Rate loop_rate(10);
// 循环发布消息,直到节点被关闭
while (n_.ok()) {
// 创建一个Int32类型的消息对象
std_msgs::Int32 msg;
// 检查是否需要计算新的斐波那契数
if (index_ >= fib_seq_.size()) {
// 如果需要,调用函数计算下一个斐波那契数
calculateNextFibonacci();
}
// 将斐波那契数列中的下一个数字赋值给消息的数据字段
msg.data = fib_seq_[index_++];
// 发布消息
pub_.publish(msg);
// 处理任何挂起的ROS消息或回调
ros::spinOnce();
// 按照设定的发布频率休眠
loop_rate.sleep();
}
}
private:
// 计算下一个斐波那契数的函数
void calculateNextFibonacci() {
// 计算斐波那契数列中的下一个数字,并添加到数列中
int next_fib = fib_seq_[index_ - 1] + fib_seq_[index_ - 2];
fib_seq_.push_back(next_fib);
}
// ROS节点句柄
ros::NodeHandle n_;
// 发布者对象,用于发布斐波那契数列
ros::Publisher pub_;
// 存储斐波那契数列的向量
std::vector<int> fib_seq_;
// 当前要发布的斐波那契数列的索引
size_t index_;
};
// 主函数
int main(int argc, char **argv) {
// 初始化ROS节点,节点名为"fibonacci_publisher"
ros::init(argc, argv, "fibonacci_publisher");
// 创建FibonacciPublisher对象
FibonacciPublisher fib_pub;
// 调用publishFibonacci函数发布斐波那契数列
fib_pub.publishFibonacci();
// 程序正常结束,返回0
return 0;
}
订阅者节点(fibonacci_subscriber.cpp)
#include <ros/ros.h>
#include <std_msgs/Int32.h>
void fibonacciCallback(const std_msgs::Int32::ConstPtr& msg) {
ROS_INFO("%d", msg->data);
}
int main(int argc, char **argv) {
ros::init(argc, argv, "fibonacci_subscriber");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("fibonacci", 1000, fibonacciCallback);
ros::spin();
return 0;
}
4、在catkin工作空间的src目录下的相应包中编译以上两个文件
1、在CMakeLists.txt中添加对应的编译指令
add_executable(fibonacci_publisher src/fibonacci_publisher.cpp)
target_link_libraries(fibonacci_publisher ${catkin_LIBRARIES})
add_executable(fibonacci_subscriber src/fibonacci_subscriber.cpp)
target_link_libraries(fibonacci_subscriber ${catkin_LIBRARIES})
2、回到catkin_ws目录下
执行命令进行编译
matkin_make
3、source工作空间
输入命令:
rosrun your_package_name fibonacci_publisher
4、启动发布者节点
rosrun svepana fibonacci_publisher
5、另一个新终端中启动订阅者节点:
rosrun svepana fibonacci_subscriber
会在订阅者节点的终端中看到斐波那契数列的输出
(但是我没看到。。。。。我也不知道哪里出了问题,求教)
我看到的是这样一堆数字。。。。。。。。