工作空间的创建
ros里的工作空间就相当于C++的项目工程,都是用来放置代码的地方。
而ros默认使用的是catkin编译系统,等同与c++的cmake编译系统,编译的方式有所区别,文件的放置有所区别。
典型的空间必有这三个文件夹:src代码空间-存储功能包的源码、build编译空间-存储编译工程中的中间文件、devel开发空间-放置编译生成的可执行文件。
随便建一个你想取名的文件夹,在里面创建src文件夹,使用catkin_init_workspace命令初始化工作空间,会自动生成CMakeLists.txt,个人理解CMakeLists.txt就相当于编译规则,你编译的时候就会按照其中的内容去编译,用命令去初始化工作空间生成CMakeLists.txt就相当于给一个空白空间生成了编译的手段,让他能够catkin编译。
虽然现在我们src源码空间什么都没有写,但是回到上层文件夹用catkin_make命令编译还是能够编译,会自动生成build和devel两个文件夹和其中的文件,这都是CMakeLists.txt中初始就有的。其中devel文件夹中产生了几个setup.bash的环境变量设置脚本,使用source命令运行脚本,工作空间中的环境变量才能生效。个人理解配置环境变量就是让系统找到你写的程序的路径,不然系统只会运行系统文件,根本不知道你的程序的存在。
这就是最基本的工作空间(空的)的创建。
src中功能包的创建
首先进入src中,使用catkin_create_pkg 功能包名 所需依赖功能包名
来创建功能包,生成的功能包中已经包含package.xml-功能包清单,描述功能包属性的信息和CMakeLists.txt-记录功能包的编译规则。
实践-话题编程
话题是ros节点间通信的一种重要方式,发布消息者为发布者,接受消息者为订阅者,两者并不了解彼此的存在,所以时效性不强,无回复,相当于写信,是单向异步通信。这种通信方式常常是用在传感器数据的传输,数据不停的传输,不需要反馈。
在刚刚创建好的工作空间的src文件夹中使用catkin_create_pkg learning_communication std_msgs rospy roscpp命令创建名为learning_communication的功能包。
它创建的功能包会帮你配置好初始的环境,有include文件夹、src文件夹、package.xml和CMakeLists.txt。
在src中写talker.cpp(发布者)和listener.cpp(订阅者)。
(1)talker.cpp:
/**
* 该例程将发布chatter话题,消息类型String
*/
#include <sstream>
#include "ros/ros.h"
#include "std_msgs/String.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "talker");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
// 设置循环的频率
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());
chatter_pub.publish(msg);
// 循环等待回调函数
ros::spinOnce();
// 按照循环频率延时
loop_rate.sleep();
++count;
}
return 0;
}
~
(2)listener.cpp:
/**
* 该例程将订阅chatter话题,消息类型String
*/
#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;
// 创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
然后在功能包CMakeLists.txt中设置需要编译的代码和生成的可执行文件
add_executable(talker src/talker.cpp)
add_executable(listener src/listener.cpp)
设置库连接
target_link_libraries(talker ${catkin_LIBRARIES})
target_link_libraries(listener ${catkin_LIBRARIES})
设置依赖
#add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
#add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
这时,功能包的编写就已经完成。
退到大文件夹下,编译catkin_make。
配置环境变量 source ./devel/setup.bash
先roscore,再rosrun learning_communication talker,最后rosrun learning_communication listener。
效果如图:
完美收工!!!!!