创建一个工作空间和功能包,完成话题与服务编程
一、创建一个工作空间和功能包,然后在功能包中完成如下工作,并使用launch文件启动涉及的节点
1、创建工作空间然后编译工作区
创建工作空间:
mkdir -p ~/catkin_ws/src
进入src目录编译工作区:
catkin_init_workspace
在catkin_ws目录下注册工作区:
source devel/setup.bash
echo $ROS_PACKAGE_PATH
2、创建工程包、编译
在catkin_ws/src下创建名称为beginner_tutorials的功能包:
catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
回到catkin_ws目录下执行如下命令编译:
catkin_make
如下图所示,编译成功
3、写一个发布节点,在创建的工程包的src目录下创建talker.cpp和listener.cpp
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);
/**
* A count of how many messages we have sent. This is used to create
* a unique string for each message.
*/
int count = 0;
while (ros::ok())
{
/**
* This is a message object. You stuff it with data, and then publish it.
*/
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"
/**
* This tutorial demonstrates simple receipt of messages over the ROS system.
*/
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() will enter a loop, pumping callbacks. With this version, all
* callbacks will be called from within this thread (the main one). ros::spin()
* will exit when Ctrl-C is pressed, or the node is shutdown by the master.
*/
ros::spin();
return 0;
}
然后在创建的功能包下的Cmakelist.txt文件里添加依赖项:
在Cmakelist.txt文件末尾加上如下代码:
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)
切换到工作空间,执行编译命令:
cd ~/catkin_ws
catkin_make
出现如下画面即是编译成功:
4、运行程序
启动ROS核心程序:
roscore
新建一个终端,进入工作空间,注册程序:
cd ~/catkin_ws
source ./devel/setup.bash
运行talker.cpp
rosrun beginner_tutorials talker
会看见如下信息:
[ INFO] [1586177568.629530314]: hello world 0
[ INFO] [1586177568.729966014]: hello world 1
[ INFO] [1586177568.829701867]: hello world 2
[ INFO] [1586177568.930666243]: hello world 3
[ INFO] [1586177569.030527168]: hello world 4
[ INFO] [1586177569.129997647]: hello world 5
[ INFO] [1586177569.230753908]: hello world 6
[ INFO] [1586177569.330438986]: hello world 7
[ INFO] [1586177569.430001067]: hello world 8
[ INFO] [1586177569.529715160]: hello world 9
再新建一个终端,运行listener.cpp
rosrun beginner_tutorials listener
会看见如下信息:
[INFO] [WallTime: 1314931969.258941] /listener_17657_1314931968795I heard hello world 1314931969.26
[INFO] [WallTime: 1314931970.262246] /listener_17657_1314931968795I heard hello world 1314931970.26
[INFO] [WallTime: 1314931971.266348] /listener_17657_1314931968795I heard hello world 1314931971.26
[INFO] [WallTime: 1314931972.270429] /listener_17657_1314931968795I heard hello world 1314931972.27
[INFO] [WallTime: 1314931973.274382] /listener_17657_1314931968795I heard hello world 1314931973.27
[INFO] [WallTime: 1314931974.277694] /listener_17657_1314931968795I heard hello world 1314931974.28
[INFO] [WallTime: 1314931975.283708] /listener_17657_1314931968795I heard hello world 1314931975.28
到这里程序就没有问题了
二、话题与服务编程:通过代码新生一只海龟,放置在(5,5)点,命名为turtle2;通过代码订阅turtle2的实时位置并在终端打印;控制turtle2实现旋转运动
1、创建功能包
cd ~/catkin_ws/src
catkin_create_pkg lesson2_homework std_msgs rospy roscpp
2、在工程包目录下的src目录中创建turtle_control.cpp文件
turtle_control.cpp
#include <ros/ros.h>
#include <turtlesim/Spawn.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Pose.h>
ros::Publisher turtle_vel;
void poseCallback(const turtlesim::PoseConstPtr& msg)
{
ROS_INFO("Turtle2 position:(%f %f)",msg->x,msg->y);
}
int main(int argc,char** argv)
{
//初始化节点
ros::init(argc,argv,"turtle_control");
ros::NodeHandle node;
//通过服务调用,产生第二只乌龟turtle2
ros::service::waitForService("spawn");
ros::ServiceClient add_turtle=node.serviceClient<turtlesim::Spawn>("spawn");
turtlesim::Spawn srv;
srv.request.x=5;
srv.request.y=5;
srv.request.name="turtle2";
add_turtle.call(srv);
ROS_INFO("The turtle2 has been spawn!");
//订阅乌龟的pose信息
ros::Subscriber sub=node.subscribe("turtle2/pose",10,&poseCallback);
//定义turtle的速度控制发布器
turtle_vel=node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel",10);
ros::Rate rate(10.0);
while(node.ok())
{
//发布速度控制命令
geometry_msgs::Twist vel_msg;
vel_msg.angular.z=1;
vel_msg.linear.x=1;
turtle_vel.publish(vel_msg);
ros::spinOnce();
rate.sleep();
}
return 0;
}
3、在lesson2_homework目录下的CmakeLists.txt文件中添加依赖项
add_executable(turtle_control src/turtle_control.cpp)
target_link_libraries(turtle_control ${catkin_LIBRARIES})
4、在功能包目录下新建一个launch文件夹,在里面新建文件turtle_control.launch
launch文件内容如下:
<launch>
<node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node"/>
<node pkg="lesson2_homework" type="turtle_control" name="turtle_control"output="screen"/>
</launch>
5、编译
cd ~/catkin_ws
catkin_make
6、运行程序
新建终端启动ROS核心程序
roscore
再新建一个终端运行程序
source ./devel/setup.bash
rosrun lesson2_homework turtle_control
再次新建终端运行turtlesim.node节点
source ./devel/setup.bash
rosrun turtlesim turtlesim.node
最终运行结果如下,终端中会打印小海龟的实时坐标:
到这里任务就顺利完成啦!