【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
前面我们安装了ROS环境,接着就可以开始进行ROS程序的开发了。在开发之前,我们有几个概念需要厘清一下。第一个是workspace,它相当于一个项目。毕竟,一个电脑上面可以有很多的workspace,也就相当于有很多的项目。第二个是package,它相当于功能块,功能块里面可以有很多的程序,package本身就是很多程序的一个集合。第三个就是node,直接把它看成独立的程序就可以了。
1、创建workspace
创建工作区是所有工作的第一步。可以通过创建workspace下面src目录的方法,直接进行创建,
mkdir -p ./catkin_ws/src
2、编译workspace
创建完成之后,就可以直接编译了。这个时候虽然什么也没有,但是catkin_make命令会帮我们自动创建build和dev这两个目录,
cd ./catkin_ws
catkin_make
3、创建package
有了工作区,就可以开始创建工作包了。工作包的创建方法也不复杂,主要使用catkin_create_pkg命令即可,前提是先进入src目录,
cd ./catkin_ws/src
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
4、开始准备代码talker.cpp & listener.cpp
package里面也是有src目录的,虽然有点绕,这个我们可以稍微花点时间理解一下。现在假设有两个程序,一个是talker.cpp,一个是listener.cpp,他们都是放在package的src目录里面。所以第一步,先进入package里面的src目录,即,
./catkin_ws/src/beginner_tutorials/src
准备talker.cpp文件,
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>int main(int argc, char **argv)
{ros::init(argc, argv, "talker");ros::NodeHandle n;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 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;
}
接着准备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::init(argc, argv, "listener");ros::NodeHandle n;ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);ros::spin();return 0;
}
5、修改CMakeLists.txt
这里需要注意的是,相关的CMakeLists.txt文件不是src目录下面文件,而是package下面的文件。这一点很容易改错的。
cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)## Declare ROS messages and services
#add_message_files(FILES Num.msg)
#add_service_files(FILES AddTwoInts.srv)## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)## Declare a catkin package
catkin_package()## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)
6、开始编译
编译就非常简单了。需要回到workspace的目录,然后输入catkin_make就可以了,
cd ./catkin_ws
catkin_make
不出意外的话,我们在./catkin_ws/devel/lib/beginner_tutorials看到对应的可执行文件。
7、启动程序
启动程序需要三个步骤。第一个步骤,设置一下rosrun的环境,即,
source devel/setup.sh
这样后期rosrun的时候,就可以直接启动node程序了。第二个步骤,输入roscore,这个相当于整个底层信息交换的大脑。第三个步骤,就是启动talker和listener了,
rosrun beginner_tutorials talker
rosrun beginner_tutorials listener
所有操作都完成之后,我们就可以看到talker程序这边在不断发送消息,而listener这边在不断地接收消息。这是一个完整的publish和subscribe程序对。
整个过程看上去自己要做的内容很少。这是因为ros已经帮助我们完成了大部分的工作,用ldd命令看下生成的程序就知道了,
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/catkin_ws/devel/lib/beginner_tutorials$ ldd listener linux-vdso.so.1 (0x00007ffeb4bfe000)libroscpp.so => /opt/ros/noetic/lib/libroscpp.so (0x00007f2381bc9000)libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2381b69000)librosconsole.so => /opt/ros/noetic/lib/librosconsole.so (0x00007f2381b06000)libroscpp_serialization.so => /opt/ros/noetic/lib/libroscpp_serialization.so (0x00007f2381b01000)libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f238191f000)libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f2381904000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2381710000)libxmlrpcpp.so => /opt/ros/noetic/lib/libxmlrpcpp.so (0x00007f23816ec000)librostime.so => /opt/ros/noetic/lib/librostime.so (0x00007f23816bf000)libcpp_common.so => /opt/ros/noetic/lib/libcpp_common.so (0x00007f23816b1000)libboost_thread.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_thread.so.1.71.0 (0x00007f2381685000)libboost_chrono.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_chrono.so.1.71.0 (0x00007f2381677000)libboost_filesystem.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_filesystem.so.1.71.0 (0x00007f2381657000)libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2381508000)/lib64/ld-linux-x86-64.so.2 (0x00007f2381db2000)librosconsole_log4cxx.so => /opt/ros/noetic/lib/librosconsole_log4cxx.so (0x00007f23814e8000)librosconsole_backend_interface.so => /opt/ros/noetic/lib/librosconsole_backend_interface.so (0x00007f23814e3000)liblog4cxx.so.10 => /lib/x86_64-linux-gnu/liblog4cxx.so.10 (0x00007f2381305000)libboost_regex.so.1.71.0 => /lib/x86_64-linux-gnu/libboost_regex.so.1.71.0 (0x00007f2381205000)libconsole_bridge.so.0.4 => /lib/x86_64-linux-gnu/libconsole_bridge.so.0.4 (0x00007f23811fd000)libapr-1.so.0 => /lib/x86_64-linux-gnu/libapr-1.so.0 (0x00007f23811c4000)libaprutil-1.so.0 => /lib/x86_64-linux-gnu/libaprutil-1.so.0 (0x00007f2381196000)libicui18n.so.66 => /lib/x86_64-linux-gnu/libicui18n.so.66 (0x00007f2380e97000)libicuuc.so.66 => /lib/x86_64-linux-gnu/libicuuc.so.66 (0x00007f2380cb1000)libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f2380ca6000)libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2380ca0000)libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f2380c65000)libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f2380c37000)libicudata.so.66 => /lib/x86_64-linux-gnu/libicudata.so.66 (0x00007f237f176000)