工作空间
创建工作空间
#创建并初始化工作空间
yxq@yxq-ThinkPad-S2:~/$ mkdir -p catkin_ws/src
yxq@yxq-ThinkPad-S2:~/$ cd catkin_ws/src/
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ catkin_init_workspace
#编译工作空间(不产生install文件夹)
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ cd ..
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
#编译工作空间(产生install文件夹)
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make install
#创建功能包
yxq@yxq-ThinkPad-S2:~/catkin_ws$ cd src/
#catkin_create_pkg [depend1][depend2]...[dependn] 依赖:需要用到的库
#std_msgs:ros中的标准消息结构
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ catkin_create_pkg test_pkg std_msgs roscpp rospy
#编译功能包
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ cd ..
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ source devel/setup.bash
#设置环境变量
yxq@yxq-ThinkPad-S2:~/catkin_ws$ source devel/setup.bash
#检查环境变量
yxq@yxq-ThinkPad-S2:~/catkin_ws$ echo $ROS_PACKAGE_PATH
/home/yxq/myproject/ros/guyue_learn/catkin_ws/src:/opt/ros/kinetic/share
package.xml 和 CMakeLists.txt
https://blog.csdn.net/ck784101777/article/details/108425116
cmake_minimum_required() #CMake的版本号
project() #项目名称
find_package() #找到编译需要的其他CMake/Catkin package
catkin_python_setup() #catkin新加宏,打开catkin的Python Module的支持
add_message_files() #catkin新加宏,添加自定义Message/Service/Action文件
add_service_files()
add_action_files()
generate_message() #catkin新加宏,生成不同语言版本的msg/srv/action接口
catkin_package() #catkin新加宏,生成当前package的cmake配置,供依赖本包的其他软件包调用
add_library() #生成库
add_executable() #生成可执行二进制文件
add_dependencies() #定义目标文件依赖于其他目标文件,确保其他目标已被构建
target_link_libraries() #链接
catkin_add_gtest() #catkin新加宏,生成测试
install() #安装至本机
<pacakge> 根标记文件
<name> 包名
<version> 版本号
<description> 内容描述
<maintainer> 维护者
<license> 软件许可证
<buildtool_depend> 编译构建工具,通常为 catkin
<depend> 指定依赖项为编译、导出、运行需要的依赖,最常用
<build_depend> 编译依赖项
<build_export_depend> 导出依赖项
<exec_depend> 运行依赖项
<test_depend> 测试用例依赖项
<doc_depend> 文档依赖项
同一个工作空间不允许存在同名功能包,不同工作空间允许存在同名功能包
创建功能包
#创建功能包
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
创建发布者代码
/**
* 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
*/
//包含头文件
#include
#include
int main(int argc, char *argv[])
{
//ROS节点初始化 前两个是(一般不关心的)参数,最后一个是节点名
ros::init(argc,argv,"velocity_publisher");
//创建节点句柄(管理API调用、节点资源)
ros::NodeHandle n;
//创建publisher,发布名为/turtle1/cmd_vel的话题topic,消息类型为geometry_msgs::Twist,队列长度10(表示publisher发布数据时等待发布的队列缓存,队列保持最新数据)
ros::Publisher turtle_vel_pub = n.advertise("/turtle1/cmd_vel",10);
//设置循环的频率
ros::Rate loop_rate(10);
int count = 0;
while(ros::ok()){
//初始化geometry_msgs::Twist类型的消息内容
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5;
vel_msg.angular.z = 0.2;
//发布消息
turtle_vel_pub.publish(vel_msg);
//类似于cout
ROS_INFO("Publish turtle velocity command[%0.2f m/s,%0.2f rad/s]",
vel_msg.linear.x,vel_msg.angular.z)
//按照循环频率延时
loop_rate.sleep();
}
return 0;
}
编写CMakeList.txt
add_executable(velocity_publisher
src/velocity_publisher.cpp
)
add_dependencies(velocity_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(velocity_publisher
${catkin_LIBRARIES}
)
编译运行
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ source devel/setup.bash
yxq@yxq-ThinkPad-S2:~/catkin_ws$ roscore
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun turtlesim turtlesim_node
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_topic velocity_publisher
运行结果(可执行文件)在catkin_ws/devel/lib/learning_topic中
little trick
打开文件管理器->Ctrl+H打开隐藏文件->双击bashrc->在别名(alias)那里添加alias sss=‘source devel/setup.bash’->重启终端,就可以用sss来设置环境变量了
用python作为可执行文件
创建订阅者代码
/**
* 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
*/
#include
#include "turtlesim/Pose.h"
//接收到订阅的消息后,将会进入消息回调函数 turtlesim::Pose消息类型,ConsrPtr&常指针
void poseCallback(const turtlesim::Pose::ConstPtr& msg){
//将接收到的消息打印出来
ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f",msg->x,msg->y);
}
int main(int argc, char *argv[])
{
//初始化ROS节点
ros::init(argc, argv, "pose_subscriber");
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为“/turtle1/pose”的topic,消息队列为10,注册回调函数poseCallback
ros::Subscriber pose_sub = n.subscribe("/turtle1/pose",10,poseCallback);
//循环等待回调函数(死循环),不断查看队列中有没有消息进来,如果有的话就执行回调函数
ros::spin();
return 0;
}
编写CMakeList.txt
add_executable(pose_subscriber
src/pose_subscriber.cpp
)
add_dependencies(pose_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(pose_subscriber
${catkin_LIBRARIES}
)
创建msg文件夹和msg文件夹下的msg文件
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ mkdir msg
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ cd msg
yxq@yxq-ThinkPad-S2:~/catkin_ws/src/msg$ touch Person.msg
编辑msg文件(注意是uint而不是unit!!)
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
在package.xml中添加功能包依赖
<build_depend>message_generationbuild_depend>
<exec_depend>message_runtimeexec_depend>
在CmakeList.txt中添加编译选项
#添加功能包
find_package(catkin REQUIRED COMPONENTS
...
message_generation
)
#把msg文件编译成对应的不同的程序文件的配置项
#把Person.msg作为定义的消息接口,编译的时候针对这个消息接口进行编译
add_message_files(
FILES Person.msg
)
#在编译Person.msg文件需要依赖的ROS已有的库、包等。(string、unit8是在std_msg中定义的)
generate_messages(DEPENDENCIES
std_msgs
)
#创建message运行的依赖(对应exec_depend)
catkin_package(
CATKIN_DEPENDS
message_runtime
# INCLUDE_DIRS include
# LIBRARIES learning_topic
# CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim
# DEPENDS system_lib
)
创建发布者代码
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
*/
#include
#include "learning_topic/Person.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "person_publisher");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
// 设置循环的频率
ros::Rate loop_rate(1);
int count = 0;
while (ros::ok())
{
// 初始化learning_topic::Person类型的消息
learning_topic::Person person_msg;
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = learning_topic::Person::male;
// 发布消息
person_info_pub.publish(person_msg);
ROS_INFO("Publish Person Info: name:%s age:%d sex:%d",
person_msg.name.c_str(), person_msg.age, person_msg.sex);
// 按照循环频率延时
loop_rate.sleep();
}
return 0;
}
创建订阅者代码
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
*/
#include
#include "learning_topic/Person.h"
// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
// 将接收到的消息打印出来
ROS_INFO("Subcribe Person Info: name:%s age:%d sex:%d",
msg->name.c_str(), msg->age, msg->sex);
}
int main(int argc, char **argv)
{
// 初始化ROS节点
ros::init(argc, argv, "person_subscriber");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
修改CmakeList.txt
add_executable(person_publisher
src/person_publisher.cpp
)
#让可执行文件与动态生成的程序产生依赖关系
add_dependencies(person_publisher ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(person_publisher
${catkin_LIBRARIES}
)
add_executable(person_subscriber
src/person_subscriber.cpp
)
add_dependencies(person_subscriber ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(person_subscriber
${catkin_LIBRARIES}
)
测试
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ sss
yxq@yxq-ThinkPad-S2:~/catkin_ws$ roscore
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_topic person_subscriber
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_topic person_publisher
此时将roscore关掉,不影响另外两个节点(节点连接已创建,”婚介所“退出了);但是如果此时要访问参数则不行了
创建功能包
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ catkin_create_pkg learning_service roscpp rospy std_msgs geometry_msgs turtlesim
创建客户端代码
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
*/
#include
#include
int main(int argc, char** argv)
{
// 初始化ROS节点
ros::init(argc, argv, "turtle_spawn");
// 创建节点句柄
ros::NodeHandle node;
// 发现/spawn服务(确保其存在)
ros::service::waitForService("/spawn");
//创建一个服务客户端,连接名为/spawn的service
ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
// 初始化turtlesim::Spawn的请求数据
turtlesim::Spawn srv;
srv.request.x = 2.0;
srv.request.y = 2.0;
srv.request.name = "turtle2";
// 请求服务调用
ROS_INFO("Call service to spwan turtle[x:%0.6f, y:%0.6f, name:%s]",
srv.request.x, srv.request.y, srv.request.name.c_str());
add_turtle.call(srv);
// 显示服务调用结果
ROS_INFO("Spwan turtle successfully [name:%s]", srv.response.name.c_str());
return 0;
};
配置客户端代码编译规则
add_executable(turtle_spawn src/turtle_spawn.cpp)
target_link_libraries(turtle_spawn ${catkin_LIBRARIES})
编译运行
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ roscore
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun turtlesim turtlesim_node
yxq@yxq-ThinkPad-S2:~/catkin_ws$ sss
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_service turtle_spawn
创建服务端代码
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
*/
#include
#include
#include
ros::Publisher turtle_vel_pub;
bool pubCommand = false;
// service回调函数,输入参数req,输出参数res(此处req为空)
bool commandCallback(std_srvs::Trigger::Request &req,
std_srvs::Trigger::Response &res)
{
pubCommand = !pubCommand;
// 显示请求数据
ROS_INFO("Publish turtle velocity command [%s]", pubCommand==true?"Yes":"No");
// 设置反馈数据
res.success = true;
res.message = "Change turtle command state!";
return true;
}
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "turtle_command_server");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个名为/turtle_command的server,注册回调函数commandCallback
ros::ServiceServer command_service = n.advertiseService("/turtle_command", commandCallback);
// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
// 循环等待回调函数
ROS_INFO("Ready to receive turtle command.");
// 设置循环的频率
ros::Rate loop_rate(10);
while(ros::ok())
{
// 查看一次回调函数队列
ros::spinOnce();
// 如果标志为true,则发布速度指令
if(pubCommand)
{
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5;
vel_msg.angular.z = 0.2;
turtle_vel_pub.publish(vel_msg);
}
//按照循环频率延时
loop_rate.sleep();
}
return 0;
}
配置客户端代码编译规则
add_executable(turtle_command_server src/turtle_command_server.cpp)
target_link_libraries(turtle_command_server ${catkin_LIBRARIES})
编译运行
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ roscore
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun turtlesim turtlesim_node
yxq@yxq-ThinkPad-S2:~/catkin_ws$ sss
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_service turtle_command_server
#terminal中发送请求(此时需要的请求为空)
rosservice call turtle_command "{}"
创建srv文件夹,在srv里添加并编写Person.srv文件
string name
uint8 age
uint8 sex
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
---
string result
package.xml中添加功能包依赖
<build_depend>message_generationbuild_depend>
<exec_depend>message_runtimeexec_depend>
CMakeList.txt中添加依赖选项
• find_package( ...... message_generation)
• add_service_files(FILES Person.srv)
generate_messages(DEPENDENCIES std_msgs)
• catkin_package(...... message_runtime)
编译生成语言相关文件
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
创建客户端和服务端代码
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程将请求/show_person服务,服务数据类型learning_service::Person
*/
#include
#include "learning_service/Person.h"
int main(int argc, char** argv)
{
// 初始化ROS节点
ros::init(argc, argv, "person_client");
// 创建节点句柄
ros::NodeHandle node;
// 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
ros::service::waitForService("/show_person");
ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");
// 初始化learning_service::Person的请求数据
learning_service::Person srv;
srv.request.name = "Tom";
srv.request.age = 20;
srv.request.sex = learning_service::Person::Request::male;
// 请求服务调用
ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]",
srv.request.name.c_str(), srv.request.age, srv.request.sex);
person_client.call(srv);
// 显示服务调用结果
ROS_INFO("Show person result : %s", srv.response.result.c_str());
return 0;
};
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程将执行/show_person服务,服务数据类型learning_service::Person
*/
#include
#include "learning_service/Person.h"
// service回调函数,输入参数req,输出参数res
bool personCallback(learning_service::Person::Request &req,
learning_service::Person::Response &res)
{
// 显示请求数据
ROS_INFO("Person: name:%s age:%d sex:%d", req.name.c_str(), req.age, req.sex);
// 设置反馈数据
res.result = "OK";
return true;
}
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "person_server");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个名为/show_person的server,注册回调函数personCallback
ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);
// 循环等待回调函数
ROS_INFO("Ready to show person informtion.");
ros::spin();
return 0;
}
配置CMakeList.txt
add_executable(person_client
src/person_client.cpp
)
add_dependencies(person_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(person_client
${catkin_LIBRARIES}
)
add_library(person_server
src/person_server.cpp
)
add_dependencies(person_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(person_server
${catkin_LIBRARIES}
)
编译运行
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ roscore
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun
yxq@yxq-ThinkPad-S2:~/catkin_ws$ sss
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_service person_server
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_service person_client
创建功能包
yxq@yxq-ThinkPad-S2:~/catkin_ws/src$ catkin_create_pkg learning_parameter roscpp rospy std_msgs
rosparam使用(以小海龟为例)
yxq@yxq-ThinkPad-S2:~$ roscore
yxq@yxq-ThinkPad-S2:~$ rosrun turtlesim turtlesim_node
help
yxq@yxq-ThinkPad-S2:~$ rosparam
rosparam is a command-line tool for getting, setting, and deleting parameters from the ROS Parameter Server.
Commands:
rosparam set set parameter
rosparam get get parameter
rosparam load load parameters from file
rosparam dump dump parameters to file
rosparam delete delete parameter
rosparam list list parameter names
rosparam list 查看当前有多少参数
yxq@yxq-ThinkPad-S2:~$ rosparam list
/background_b
/background_g
/background_r #背景颜色
/rosdistro #ros版本
/roslaunch/uris/host_yxq_thinkpad_s2__44041
/rosversion
/run_id
rosparam get /background_b 得到某个参数的值
yxq@yxq-ThinkPad-S2:~$ rosparam get /background_b
255
rosparam set /background_b 100 修改某个参数的值
yxq@yxq-ThinkPad-S2:~$ rosparam set /background_b 100
#向仿真器发送刷新请求(然后小海龟的背景就可以变色了)
yxq@yxq-ThinkPad-S2:~$ rosservice call /clear "{}"
rosparam dump param.yaml 保存当前参数
#保存在终端所处目录下
yxq@yxq-ThinkPad-S2:~$ rosparam dump param.yaml
background_b: 200
background_g: 86
background_r: 100
rosdistro: 'kinetic
'
roslaunch:
uris: {host_yxq_thinkpad_s2__44041: 'http://yxq-ThinkPad-S2:44041/'}
rosversion: '1.12.17
'
run_id: 94a5db9c-57fe-11eb-ac1d-ac2b6e5e86ac
rosparam load param.yaml 加载某个参数文件
yxq@yxq-ThinkPad-S2:~$ rosparam load param.yaml
#刷新
yxq@yxq-ThinkPad-S2:~$ rosservice call /clear "{}"
rosparam delete /background_g 删除某个参数
yxq@yxq-ThinkPad-S2:~$ rosparam delete /background_g
yxq@yxq-ThinkPad-S2:~$ rosparam list
/background_b
/background_r
/rosdistro
/roslaunch/uris/host_yxq_thinkpad_s2__44041
/rosversion
/run_id
yxq@yxq-ThinkPad-S2:~$ rosservice call /clear "{}"
在程序中实现以上功能(在刚才learning_parameter的src中创建parameter_config.cpp)
/***********************************************************************
Copyright 2020 GuYueHome (www.guyuehome.com).
***********************************************************************/
/**
* 该例程设置/读取海龟例程中的参数
*/
#include
#include
#include
int main(int argc, char **argv)
{
int red, green, blue;
// ROS节点初始化
ros::init(argc, argv, "parameter_config");
// 创建节点句柄
ros::NodeHandle node;
// 读取背景颜色参数
ros::param::get("/background_r", red);
ros::param::get("/background_g", green);
ros::param::get("/background_b", blue);
ROS_INFO("Get Backgroud Color[%d, %d, %d]", red, green, blue);
// 设置背景颜色参数
ros::param::set("/background_r", 255);
ros::param::set("/background_g", 255);
ros::param::set("/background_b", 255);
ROS_INFO("Set Backgroud Color[255, 255, 255]");
// 读取背景颜色参数
ros::param::get("/background_r", red);
ros::param::get("/background_g", green);
ros::param::get("/background_b", blue);
ROS_INFO("Re-get Backgroud Color[%d, %d, %d]", red, green, blue);
// 调用服务,刷新背景颜色
ros::service::waitForService("/clear");
ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear");
std_srvs::Empty srv;
clear_background.call(srv);
sleep(1);
return 0;
}
配置CMakeList.txt
add_executable(parameter_config
src/parameter_config.cpp
)
add_dependencies(parameter_config ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(parameter_config
${catkin_LIBRARIES}
)
编译运行
yxq@yxq-ThinkPad-S2:~/catkin_ws$ catkin_make
yxq@yxq-ThinkPad-S2:~/catkin_ws$ roscore
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun turtlesim turtlesim_node
yxq@yxq-ThinkPad-S2:~/catkin_ws$ sss
yxq@yxq-ThinkPad-S2:~/catkin_ws$ rosrun learning_parameter parameter_config
parameter其他使用方法
http://wiki.ros.org/Parameter%20Server