【古月居】ros21讲 https://www.bilibili.com/video/BV1zt411G7Vn?from=search&seid=765777793691750397
【代码】https://github.com/tshooting/ros21guyueju/tree/master
安装ubuntu https://www.cnblogs.com/rollupbytian/p/14526163.html
安装ros https://www.cnblogs.com/rollupbytian/p/14528968.html
ros3:命令
3.1命令
cd pwd mkdir ls ll touch mv cp rm sudo
ros4 C++/Python极简基础
4.1 安装g++ python
sudo apt-get install g++
sudo apt-get install python
ros5 安装ROS系统
5.1 测试小乌龟
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
ros6 ROS是什么
6.1
ros = 通信机制+开发工具+应用功能+生态系统 提高机器人研发中的软件复用率
通信机制 松耦合分布式通信
开发工具 QT Rviz gazebo TF坐标变换
应用功能 Navigation slam movelt
生态系统:
发行版 软件源 ROS wiki 邮件列表 ROS answers blog
ros7.ROS中的核心概念
7.1节点 node 执行单元
执行具体任务的进行、独立运行的可执行文件; 分布式;在系统中的名字唯一
7.2节点管理器 node master 控制中心
为节点提供命名和注册服务;
跟踪和记录话题服务的通信,辅助节点互相查找 建立链接;
提供参数服务器,节点使用此服务器存储和检索运行时的参数
7.3 话题 topic 异步通信机制
节点间用来传输数据的重要总线
使用发布和订阅模式,数据由发布者传输到订阅者
7.4 消息 message 话题数据
具有一定类型和数据结构,包括ros提供的标准类型和用户自定义类型
使用编程语言无关的.msg文件定义,编译过程中生成对应的代码文件
7.5 服务通信
服务 service 同步通信机制
使用C/S,请求request和应答response,使用的是.srv文件定义请求和应答数据结构,编译过程中生成对应的代码
7.6 参数 parameter 全局共享字典
可以通过网络访问的共享、多变量字典
节点使用此服务器来存储和检索运行时的参数
适合存储静态、非二进制的配置参数,不存储动态配置的数据
7.7 文件系统
功能包(Package)
ros软件中的基本单元,包含节点源码、配置文件、数据定义等。
功能包清单 package manifest
记录功能包的基本信息,包含作者信息,许可信息,依赖选项、编译标志等
元功能包 metapackages
组织多个用于同一目的功能包
ros8.ROS命令行工具的使用
8.1 以小海龟为例
roscore 【ros master】
rosrun turtlesim turtlesim_node 【rosrun 功能包的名字 功能包里面的节点】
rosrun turtlesim turtle_teleop_key 【rosrun 功能包的名字 功能包里面的节点】
8.2rqt_graph : 用qt写的,可以看到系统中的运行图
显示两个节点,仿真器节点和键盘控制节点, 和话题
8.3rosnode list 显示系统中所有的节点,rosout是采集所有节点的日志提交给上面的界面所做显示
8.4rosnode info /turtlesim 显示节点的信息
现在这个节点,会发布一些话题,然后订阅一个话题,提供一些服务
8.5rostopic list 显示当前所有的话题
发布话题消息 -r是循环 10是每秒10次,话题 消息
8.6rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist "linear:
x: 1.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 1.0"
8.7rosmsg show geometry_msgs/Twist 可以查看这个消息的类型 有线速度和角速度
8.8rosservice list 查看所有的服务
8.9发布请求服务 生成一个新的海龟
rosservice call /spawn "x: 2.0
y: 4.0
theta: 0.0
name: 'turtle2'"
会有一个response
发现话题多了turtle2有了
8.10话题记录
rosbag record -a -O ~/Desktop/cmd_record
结束之后按ctrl+s 不要按ctrl+z
先执行上面3个命令,然后再开启这个话题记录终端,然后再使用键盘让小乌龟运动,之后按ctrl+s 然后关闭所有的命令roscore之类的
8.11 话题复现
只打开roscore和仿真器节点,然后运行 rosbag play ~/Desktop/cmd_record.bag
ros9.创建工作空间与功能包
9.1工作空间(workspace)是存放工程开发相关文件的文件夹
src(代码空间),build(编译空间),devel(开发空间),install(安装空间)
9.2创建工作空间
mkdir -p ~/catkin_ws/src【可以只执行这一步】
cd ~/catkin_ws/src
catkin_init_workspace
编译
cd ~/catkin_ws/
catkin_make[进入这个文件夹去编译]
设置环境变量
source devel /setup.bash
检查环境变量
echo $ROS_PACKAGE_PATH
9.3 创建功能包
cd ~/catkin_ws/src
catkin_create_pkg test_pkg std_msgs rospy roscpp
编译功能包
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash【不能在fish下面,要在最初的终端下面】
同一个工作空间下,不允许存在同名功能包,到那时不同工作空间下就允许存在同名的功能包了
使用sudo gedit ~/.bashrc 可以查看
ros10.发布者Publisher的编程实现
10.1创建一个功能包 然后添加依赖
cd ~/catkin_ws/src
catkin_create_pkg learning_topic roscpp rospy std_msgs geometry_msgs turtlesim
10.2 创建发布者代码
(1)首先创建ros节点
(2)向ros master 注册节点信息,包括 发布的话题名字和话题中的消息类型 还有就是队列长度(只保留最新的10个)
(3)创建消息数据
(4)按照一定频率循环发布消息
调试,在vscode里面写代码发现没有ros/ros.h的路径,执行下面
https://blog.csdn.net/baidu_38634017/article/details/99875321
https://blog.csdn.net/suoniyusanxing/article/details/107325660?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
扩展程序会根据当前系统环境配置基本信息,因此有可能配置不完整,这时需要通过生成c_cpp_properties.json
文件来配置缺少的信息:
ctrl+shift+P
打开Command Palette,运行C/Cpp: Edit configurations...
生成c_cpp_properties.json:
在includePath中添加"/opt/ros/kinetic/include/*" ,也就是本地安装的ros路径
/** * 发布的是turtle1/cmd_vel话题,消息类型geometry_msgs::Twist * */include<ros/ros.h>
include<geometry_msgs/Twist.h>
int main(int argc,char ** argv)
{
// ros node init the name of publisher node
ros::init(argc,argv,"velocity_publisher");</span><span style="color: #008000;">//</span><span style="color: #008000;"> create node handle node master</span>
ros::NodeHandle n;
</span><span style="color: #008000;">//</span><span style="color: #008000;"> create a publisher && topic name && msg type && queue length</span> ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist> (<span style="color: #800000;">"</span><span style="color: #800000;">/turtle1/cmd_vel</span><span style="color: #800000;">"</span>,<span style="color: #800080;">10</span><span style="color: #000000;">); </span><span style="color: #008000;">//</span><span style="color: #008000;">set cycle frequency 10times/sec</span> ros::Rate loop_rate (<span style="color: #800080;">10</span><span style="color: #000000;">); </span><span style="color: #0000ff;">int</span> count = <span style="color: #800080;">0</span><span style="color: #000000;">; </span><span style="color: #0000ff;">while</span><span style="color: #000000;">(ros::ok()){ </span><span style="color: #008000;">//</span><span style="color: #008000;">init msg </span>
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5;//now y and z is zero
vel_msg.angular.z = 0.2;</span><span style="color: #008000;">//</span><span style="color: #008000;">publish msg</span>
turtle_vel_pub.publish(vel_msg);
</span><span style="color: #008000;">//</span><span style="color: #008000;">like cout</span> ROS_INFO(<span style="color: #800000;">"</span><span style="color: #800000;">Publish turtle velocity command [%0.2f m/s, %0.2f rad/s]</span><span style="color: #800000;">"</span><span style="color: #000000;">,vel_msg.linear.x,vel_msg.angular.z); </span><span style="color: #008000;">//</span><span style="color: #008000;">delay according to cycle frequency </span>
loop_rate.sleep();
}
return 0;}
10.3 配置发布者代码编译规则
在CMakeLists.txt中编译规则
154行,因为会分区域,build区域,install 区域
add_executable(velocity_publisher src/velocity_publisher.cpp)
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})
10.4 编译并且运行发布者
(1) 先去编译
cd ~/catkin_ws
catkin_make[编译]
source devel/setup.bash[以前设置过这一句话,现在就不用再设置了]
(2)启动命令
roscore [启动 master]
rosrun turtlesim turtlesim_node[启动仿真器节点,仿真器节点会订阅 /turtle1/cmd_vel 话题,我们自己设置的发布者就是发布这个话题的]
rosrun learning_topic velocity_publisher[启动功能包下面的节点]
就会发现小海龟在动起来了,终端learning_topic velocity_publisher下面会打印rosinfo的信息
对于Python 要注意是让这个.py的源代码的属性变为可以编译成可执行文件的
ros11.订阅者Subscriber的编程实现
1 /** 2 * 现在是实现一个订阅者 3 * 首先初始化ros节点【这个时候还不知道这个节点的角色,一个节点可以是发布者同时也可以是订阅者】 4 * 创建句柄 5 * 6 * 创建订阅者 让这个节点去订阅话题 7 * 循环等待话题消息,接收到消息后进入回调函数 8 * 在回调函数中完成消息的处理 9 * 10 * */ 11 12 #include<ros/ros.h> 13 #include"turtlesim/Pose.h" 14 void poseCallback(const turtlesim::Pose::ConstPtr & msg) 15 { 16 ROS_INFO("Turtle Pose : x:%0.6f,y:%0.6f",msg->x,msg->y); 17 } 18 int main( int argc,char ** argv){ 19 //初始化ros节点 20 ros::init(argc,argv, "pose_subscriber"); 21 22 //创建句柄 23 ros::NodeHandle n; 24 25 //创建一个订阅者,订阅者的名字和队列长度,注册回调函数 26 ros::Subscriber pose_sub = n.subscribe("/turtle1/pose",10,poseCallback); 27 28 //循环等待回调函数 29 ros::spin(); 30 31 return 0; 32 } 33 add_executable(pose_subscriber src/pose_subscriber) 34 target_link_libraries(pose_subscriber ${catkin_LIBRARIES})
ros12.话题消息的定义与使用
12.1
(1)首先定义一个msg文件(在learning_topic下面创建一个msg文件夹,在里面创建)
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male = 1
uint8 female = 2
(2)然后在Package.xml[learning_topic下面的Package.xml]里面添加功能包编译依赖和运行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
,最后需要在CMakeLists.txt里面添加编译选项
find_package( ...... message_generation)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
catkin_package(...... message_runtime)
(3)编译之后会自动生成.h文件,在catkin_ws 下面编译 catkin_make
12.2 然后定义一个发布者和订阅者测试代码
1 /** 2 * 3 * 现在是创建一个话题的发布者 4 * 1 初始化ros节点 5 * 2 创建句柄 6 * 3 创建发布者 话题名字 队列长队 7 * 4 设置发布频率 8 * 5 创建循环,设置消息,发送消息,按照频率进行延迟 9 * 10 * */ 11 #include<ros/ros.h> 12 #include "learning_topic/Person.h" 13 int main(int argc,char ** argv) 14 { 15 //初始化ros节点 16 ros::init(argc,argv,"person_publisher"); 17 //创建句柄 18 ros::NodeHandle n; 19 //创建一个发布者 20 ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info",10); 21 //设置循环频率 22 ros::Rate loop_rate(1); 23 int count = 0; 24 while(ros::ok()){ 25 //初始化learning_topic::Person 类型的消息 26 learning_topic::Person person_msg; 27 person_msg.name = "Tom"; 28 person_msg.age = 18; 29 person_msg.sex = learning_topic::Person::male; 30 //发布消息 31 person_info_pub.publish(person_msg); 32 ROS_INFO("Publish Person Info : name : %s age : %d sex : %d",person_msg.name.c_str(),person_msg.age,person_msg.sex); 33 //按照循环频率延时 34 loop_rate.sleep(); 35 36 } 37 return 0; 38 } 39 /** 40 * 创建一个订阅者,需要导入消息的类 41 * 定义回调函数 42 * 初始化ros节点 43 * 创建句柄 44 * 创建订阅者 45 * 循环等待回调函数 46 * */ 47 #include<ros/ros.h> 48 #include"learning_topic/Person.h" 49 void personInfoCallback(const learning_topic ::Person::ConstPtr & msg){ 50 ROS_INFO("Subscribe Person Info : name : %s age : %d sex: %d",msg->name.c_str(),msg->age,msg->male); 51 } 52 int main(int argv,char ** argc){ 53 //init node 54 ros::init(argv,argc,"person_subscriber"); 55 56 ros::NodeHandle n; 57 58 ros::Subscriber person_info_sub = n.subscribe("/person_info",10,personInfoCallback); 59 60 ros::spin(); 61 return 0; 62 } 63 CMakeLists.txt 64 add_executable(person_publisher src/person_publisher.cpp) 65 target_link_libraries(person_publisher ${catkin_LIBRARIES}) 66 add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp) 67 68 69 add_executable(person_subscriber src/person_subscriber.cpp) 70 target_link_libraries(person_subscriber ${catkin_LIBRARIES}) 71 add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp) 72 73
写完之后进行编译
cd ~/catkin_ws
catkin_make
roscore
rosrun learning_topic person_publisher
rosrun learning_topic person_subscriber
ros 13.客户端Client的编程实现
(1)创建一个节点
(2)发现某个服务之后,创建一个客户端, (请求的数据类型也要知道)
(3)初始化请求数据
(4)请求服务调用,会有响应显示调用的结果
catkin_create_pkg learning_service roscpp rospy std_msgs geometry_msgs turtlesim
1 /** 2 * 创建一个客户端,请求/spawn,服务的数据类型是 turtlesim::Spawn 3 * 初始化ros节点 4 * 发现服务创建一个客户端实例 5 * 设置请求服务数据,发布请求 6 * 等待server处理之后的应答结果 7 * */ 8 #include<ros/ros.h> 9 #include<turtlesim/Spawn.h> 10 int main(int argc, char ** argv) 11 { 12 //初始化节点 创建句柄 13 ros::init(argc,argv,"turtle_spawn"); 14 ros::NodeHandle node; 15 //发现服务 创建客户端 16 ros::service::waitForService("/spawn"); 17 ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn> ("/spawn"); 18 //初始化turtlesim::Spwn 的请求数据 19 turtlesim::Spawn srv; 20 srv.request.x = 2.0; 21 srv.request.y = 2.0; 22 srv.request.name = "turtle2"; 23 //请求服务调用 24 ROS_INFO("Call service to spawn turtle [x : %0.6f,y:%0.6f ,name :%s]",srv.request.x,srv.request.y,srv.request.name); 25 add_turtle.call(srv); 26 27 //显示服务调用结果 28 ROS_INFO("Spawn turtle successfully [name :%s]",srv.response.name.c_str()); 29 30 return 0; 31 } 32 add_executable(turtle_spawn src/turtle_spawn.cpp) 33 target_link_libraries(turtle_spawn ${catkin_LIBRARIES})
rosrun turtlesim turtlesim_node
rosrun learning_service turtle_spawn
ros14.服务端Server的编程实现
(1)创建一个节点【可以再节点里面注册发布者,注册服务】
(2)创建server实例
(3)循环等待服务请求,进入回调函数
(4)在回调函数中完成服务功能的处理,并反馈应答数据
1 /** 2 * 现在要实现的就是一个服务器 3 * 初始化ros节点 4 * 创建服务端 5 * 循环等待服务请求,进入回调函数响应请求 6 * 在回调函数中完成服务功能的处理并反馈给客户端应答数据 7 * 8 * */ 9 10 #include<ros/ros.h> 11 #include<geometry_msgs/Twist.h> 12 #include<std_srvs/Trigger.h> 13 ros::Publisher turtle_vel_pub; 14 bool pubCommand = false; 15 bool commandCallback(std_srvs::TriggerRequest & req, std_srvs::TriggerResponse & res){ 16 17 pubCommand = !pubCommand; 18 //显示请求数据 19 ROS_INFO ("publish turtle velocity command [%s]", pubCommand == true ? "Yes":"No"); 20 //设置反馈数据 21 res.success = true; 22 res.message = "Change turtle command state!"; 23 24 } 25 int main(int argc,char ** argv ) 26 { 27 //初始化创建句柄 28 ros::init(argc,argv,"turtle_command_server"); 29 ros::NodeHandle n; 30 //创建一个服务 注册回调函数 31 ros::ServiceServer command_service = n.advertiseService("/turtle_command",commandCallback); 32 //创建一个发布者 设置循环发布消息 33 turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10); 34 //循环等待回调函数 因为这是一个服务段,要一直等待响应客户端的请求 35 ROS_INFO("Ready to receive turtle command."); 36 //设置循环频率 37 ros::Rate loop_rate(10); 38 while(ros::ok()){ 39 //查看一次回调函数队列 40 ros::spinOnce(); 41 //如果标志为true,则发布速度指令 42 if(pubCommand){ 43 geometry_msgs::Twist vel_msg; 44 vel_msg.linear.x = 0.5; 45 vel_msg.angular.z = 0.2; 46 turtle_vel_pub.publish(vel_msg); 47 } 48 //按照循环频率延时 49 loop_rate.sleep(); 50 } 51 52 return 0; 53 } 54 add_executable(turtle_command_server src/turtle_command_server.cpp) 55 target_link_libraries(turtle_command_server ${catkin_LIBRARIES})
rosrun turtlesim turtlesim_node
rosrun learning_service turtle_command_server
rosservice call /turtle_command "{}"
ros15.服务数据的定义与使用
自己创建一个服务端一个客户端,自己编写服务数据类型
15.1自定义服务数据
(1)创建服务数据文件
Person.srv
string name
uint8 age
unit8 sex
uint8 unknown = 0
unit8 male = 1
uint8 female = 2
---
string result
(2)在Package.xml 里面添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
(3)在CMakeLists.tst 添加编译选项
find_package( ...... message_generation)
add_service_files(FILES Person.srv)
generate_messages(DEPENDENCIES std_msgs)
15.2创建服务端和客户端
问题:在vscode里面,会出现找不到.h的情况这个时候在c_cpp_properties.json 设置
15.2.1实现一个服务端
初始化节点
创建服务端,注册回调函数
循环等待回调函数
客户端
创建节点
发现服务 然后创建客户端
设置数据
调用服务
查看返回结果
1 /** 2 * 创建一个服务端 执行/show_person 服务,参数类型是learning_service::Person 3 * 初始化节点 4 * 创建服务端,注册回调函数 5 * 循环等待回调函数 6 * 7 * */ 8 #include<ros/ros.h> 9 #include "learning_service/Person.h" 10 bool personCallback(learning_service::Person::Request & req, 11 learning_service::Person::Response & res) 12 { 13 ROS_INFO("Person : name : %s age : %d sex : %d",req.name.c_str(),req.age,req.male); 14 //设置反馈数据 15 res.result = "OK"; 16 17 } 18 int main(int argc,char ** argv) 19 { 20 ros::init(argc,argv,"person_server"); 21 ros::NodeHandle n; 22 ros::ServiceServer person_service = n.advertiseService("/show_person",personCallback); 23 //循环等待回调函数 24 ROS_INFO("Ready to show person information."); 25 ros::spin(); 26 return 0; 27 } 28 /** 29 * 现在是客户端代码 30 * 初始化节点 31 * 发现服务然后创建客户端 32 * 初始化数据 发送请求 33 * 请求响应的结果 34 * 35 * */ 36 #include<ros/ros.h> 37 #include "learning_service/Person.h" 38 int main(int argc,char ** argv) 39 { 40 //初始化 41 ros::init(argc,argv,"person_client"); 42 ros::NodeHandle node; 43 //等待服务 创建客户端 44 ros::service::waitForService("/show_person"); 45 ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person"); 46 //初始化learning_service::Person 47 learning_service::Person srv; 48 srv.request.name = "Tom"; 49 srv.request.age = 20; 50 srv.request.sex = learning_service::Person::Request::male; 51 //请求服务调用 52 ROS_INFO("Call service to show person [name :%s,age : %d,sex:%d]", 53 srv.request.name.c_str(),srv.request.age,srv.request.sex 54 ); 55 //调用服务 56 person_client.call(srv); 57 //显示服务调用结果 58 ROS_INFO("show person result : %s ",srv.response.result.c_str()); 59 60 61 return 0; 62 } 63 add_executable(person_publisher src/person_publisher.cpp) 64 target_link_libraries(person_publisher ${catkin_LIBRARIES}) 65 add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp) 66 67 68 add_executable(person_subscriber src/person_subscriber.cpp) 69 target_link_libraries(person_subscriber ${catkin_LIBRARIES}) 70 add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)
rosrun learning_service person_server
rosrun learning_service person_client
ros16.参数的使用与编程方法
16.1 ros master 里面有一个parameter server【全局字典】 里面有各种参数以及对应的值
启动roscore
启动 rosrun turtlesim turtlesim_node
(1)rosparam list [列出当前参数]
/background_b
/background_g
/background_r
/rosdistro
/roslaunch/uris/host_tian_nl__39943
/rosversion
/run_id
(2)显示某一个参数
rosparam get /background_b
(3)设置某个参数值
osparam set /background_b 0
为了显示已经改变了参数的值,可以刷新一下显示小乌龟的背景
rosservice call /clear "{}"
(4)保存参数到文件 文件后缀是.yaml
rosparam dump now_param.yaml
(5)从文件读取参数
rosparam load now_param.yaml
rosservice call /clear "{}"
(6) 删除参数
rosparam delete param_key
16.2 参数编程
初始化ros节点
get 函数获取参数
set函数设置参数
1 /** 2 * 设置海龟历程中的参数 3 * */ 4 #include<string> 5 #include<ros/ros.h> 6 #include<std_srvs/Empty.h> 7 int main(int argc,char ** argv) 8 { 9 int red,green , blue; 10 //ros 初始化和创建句柄 11 ros::init(argc,argv,"parameter_config"); 12 ros::NodeHandle node; 13 //读取背景颜色 14 ros::param::get("/background_r",red); 15 ros::param::get("/background_g",green); 16 ros::param::get("/background_b",blue); 17 //输出读取的背景颜色 18 ROS_INFO("Get Background Color [%d ,%d,%d]",red,green,blue); 19 //设置背景颜色参数 20 ros::param::set("/background_r",255); 21 ros::param::set("/background_g",255); 22 ros::param::set("/background_b",255); 23 ROS_INFO("Get Background Color [255,255,255]"); 24 //因为已经被修改了 再读取背景颜色 25 ros::param::get("/background_r",red); 26 ros::param::get("/background_g",green); 27 ros::param::get("/background_b",blue); 28 ROS_INFO("Re-get Background Color [%d ,%d,%d]",red,green,blue); 29 //调用服务,刷新背景颜色 等待服务 服务找到之后就设置参数 调用服务 30 ros::service::waitForService("/clear"); 31 ros::ServiceClient clear_background = node.serviceClient<std_srvs::Empty>("/clear"); 32 std_srvs::Empty srv; 33 clear_background.call(srv); 34 sleep(1); 35 return 0; 36 } 37 add_executable(parameter_config src/parameter_config.cpp) 38 target_link_libraries(parameter_config ${catkin_LIBRARIES})
启动roscore
启动 rosrun turtlesim turtlesim_node
启动 rosrun learning_parameter parameter_config
ros17.ROS中的坐标系管理系统
17.1坐标变化 就是 P2 = R(P1)+t
17.2 TF 功能包能干什么
5秒钟以前,机器人头部的坐标系相对于全局坐标系的关系是怎么样的
机器人夹取的物体相对于机器人中心坐标系的位置在哪里
机器人中心坐标相对于全局坐标的位置在哪里
TF坐标变换是如何实现的
广播TF变换
监听 TF变换
17.3 演示
sudo apt-get install ros-melodic-turtle-tf
roslaunch turtle_tf turtle_tf_demo.launch [乌龟2会追着乌龟1 ,不要求他们的头指向同一方向,但是身子要重叠]
rosrun turtlesim turtle_teleop_key
rosrun tf view_frames【会在当前目录下生成 frames.pdf】
rosrun tf tf_echo turtle1 turtle2[可以看到两个小乌龟的位姿]
rosrun rviz rviz -d `rospack find turtle_tf` /rviz/turtle_rviz.rviz 【在Fixed Frame 变成world || Add-> TF】
ros18.tf坐标系广播与监听的编程实现
roscore
rosrun turtlesim turtlesim_node
rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1【turtle1_tf_broadcaster 会替换掉代码里面设置的节点名字 arg[1] = trutle1】
rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
rosrun learning_tf turtle_tf_listener
rosrun turtlesim turtle_teleop_key rostopic list
rosnode list
1 roscore 2 3 rosrun turtlesim turtlesim_node 4 5 rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1【turtle1_tf_broadcaster 会替换掉代码里面设置的节点名字 arg[1] = trutle1】 6 rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2 7 8 rosrun learning_tf turtle_tf_listener 9 10 rosrun turtlesim turtle_teleop_key rostopic list 11 12 rosnode list 13 14 15 /** 16 * 现在是实现一个tf广播器 17 * 创建坐标变换值 18 * 发布坐标变换 19 * 20 * */ 21 #include<ros/ros.h> 22 #include<tf/transform_broadcaster.h> 23 #include<turtlesim/Pose.h> 24 std::string turtle_name; 25 void poseCallback(const turtlesim::PoseConstPtr & msg){ 26 //创建tf的广播器 27 static tf::TransformBroadcaster br; 28 //初始化tf的数据 29 tf::Transform transform; 30 //平移 31 transform.setOrigin(tf::Vector3(msg->x,msg->y,0)); 32 //四元数 33 tf::Quaternion q; 34 q.setRPY(0,0,msg->theta); 35 transform.setRotation(q); 36 37 //广播world与海龟坐标系之间的tf数据 38 br.sendTransform( 39 tf::StampedTransform( 40 transform, 41 ros::Time::now(), 42 "world", 43 turtle_name 44 ) 45 ); 46 47 } 48 int main(int argc,char ** argv){ 49 ros::init(argc,argv,"my_tf_broadcaster"); 50 if(argc!=2){ 51 ROS_ERROR("need turtle name as argument"); 52 return -1; 53 } 54 turtle_name = argv[1]; 55 //订阅海龟的位子话题 56 ros::NodeHandle node; 57 ros::Subscriber sub = node.subscribe(turtle_name+"/pose",10,&poseCallback); 58 //循环等待回调函数 59 ros::spin(); 60 return 0; 61 } 62 /** 63 * 定义tf监听器 64 * 查找坐标变换 65 * */ 66 #include<ros/ros.h> 67 #include<tf/transform_listener.h> 68 #include<geometry_msgs/Twist.h> 69 #include<turtlesim/Spawn.h> 70 int main(int argc,char ** argv){ 71 //初始化ros节点和句柄 请求产生乌龟 72 ros::init(argc,argv,"my_tf_listener"); 73 ros::NodeHandle node; 74 ros::service::waitForService("/spawn"); 75 ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn"); 76 turtlesim::Spawn srv; 77 add_turtle.call(srv); 78 //创建发布turtle速度控制指令的发布者 79 ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel",10); 80 //创建tf的监听器 81 tf::TransformListener listener; 82 ros::Rate rate(10.0); 83 while (ros::ok()) 84 { 85 //获取两个海龟坐标系之间的tf数据 86 tf::StampedTransform transform; 87 try 88 { 89 listener.waitForTransform("/turtle2","/turtle1",ros::Time(0),ros::Duration(3.0)); 90 listener.lookupTransform("/turtle2","/turtle1",ros::Time(0),transform); 91 92 } 93 catch(tf::TransformException &ex) 94 { 95 ROS_ERROR("%s",ex.what()); 96 // ros::Duration(1.0)这里代表时长 97 ros::Duration(1.0).sleep(); 98 continue; 99 } 100 //根据两个乌龟之间的位置关系,发布turtle的速度控制指令 101 geometry_msgs::Twist vel_msg; 102 //arctan(y/x); 103 vel_msg.angular.z = 4.0 * atan2( 104 transform.getOrigin().y(), 105 transform.getOrigin().x() 106 ); 107 vel_msg.linear.x = 0.5* sqrt( 108 pow(transform.getOrigin().x(),2) + 109 pow(transform.getOrigin().y(),2) 110 ); 111 112 turtle_vel.publish(vel_msg); 113 } 114 115 return 0; 116 } 117 add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp) 118 target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES}) 119 120 add_executable(turtle_tf_listener src/turtle_tf_listener.cpp) 121 target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
ros19.launch启动文件[xml]的使用方法
19.1launch 文件语法
1 <launch> 2 <node pkg = "learning_topic" type = "person_subscriber" name="talker" output="screen"/> 3 <node pkg = "learning_topic" type = "person_publisher" name="listener" output="screen"/> 4 5 </launch> 6 <!-- 7 node:启动节点 8 pkg:节点所在的功能包名称 9 type: 节点的可执行文件名称 10 name:节点运行时的名称 【相当于我虽然写了一个cpp 里面我也确实初始化了一个节点 11 并且这个节点也有名字,但是现在我用name来代替我一开始写的节点的名字 12 这样我多几个name就多了几个节点但是只写了一份代码 13 】 14 output: 打印在哪里 15 创建一个功能包 不添加任何依赖 learning_launch 在下面添加launch文件夹 把.xml launch文件 放入到文件下面 16 roslaunch learning_launch simple.launch 17 rostopic list 18 -->
1 <launch> 2 <param name = "/turtle_number" value = "2"/> 3 <node pkg="turtlesim" type="turtlesim_node" name="turtlesim_node"> 4 <param name = "turtle_name1" value = "Tom"/> 5 <param name = "turtle_name2" value = "Jerry"/> 6 <rosparam 7 file = "$(find learning_launch)/config/param.yaml" 8 command = "load" 9 /> 10 </node> 11 12 <node 13 pkg="turtlesim" 14 type="turtle_teleop_key" 15 name = "turtle_teleop_key" 16 output = "screen" 17 18 /> 19 </launch> 20 <!-- 21 设置ros系统中运行的参数,存储在参数服务器中 22 23 param: 24 name: 25 value: 26 加载参数文件中的多个参数 27 rosparam 28 file 29 command 30 ns="params" 31 roslaunch learning_launch turtlesim_parameter_config.launch 32 rosparam list 33 -->
1 <launch> 2 <node 3 pkg="turtlesim" 4 type="turtlesim_node" 5 name = "sim" 6 /> 7 <node 8 pkg="turtlesim" 9 type="turtle_teleop_key" 10 name = "teleop" 11 output = "screen" 12 /> 13 <node 14 pkg="learning_tf" 15 type="turtle_tf_broadcaster" 16 name = "turtle1_tf_broadcaster" 17 args="/turtle1" 18 /> 19 <node 20 pkg="learning_tf" 21 type="turtle_tf_broadcaster" 22 name = "turtle2_tf_broadcaster" 23 args="/turtle2" 24 /> 25 <node 26 pkg="learning_tf" 27 type="turtle_tf_listener" 28 name = "listener" 29 30 /> 31 32 33 </launch> 34 <!-- 35 roslaunch learning_launch start_tf_demo_c++.launch 36 -->
1 <launch> 2 3 <include file="$(find learning_launch)/launch/simple.launch"/> 4 <node pkg="turtlesim" type = "turtlesim_node" name="turtlesim_node"> 5 <remap from="/turtle1/cmd_vel" to="/cmd_vel"/> 6 </node> 7 </launch> 8 <!-- 9 remap 重映射 ros计算图资源的命名 10 roslaunch learning_launch turtlesim_remap.launch 11 rostopic list 12 rostopic pub /cmd_vel geometry_msgs/Twist "linear: 13 x: 5.0 14 y: 0.0 15 z: 0.0 16 angular: 17 x: 0.0 18 y: 0.0 19 z: 2.0" 20 --> 21
ros20.常用可视化工具的使用
20.1rqt_console 【 日志输出工具 对日志信息进行筛选 】
rqt_graph [计算图可视化工具]
rqt_plot[ 数据绘图工具 把信息绘制成图 在topic那里选择订阅的话题]
rqt_image_view [图形渲染工具 链接图像]
rqt 集成了ros qt的所有的工具,可以把很多的工具就行堆叠
20.2
rosrun rviz rviz
3D视图区 工具栏 显示项列表 视觉设置区 时间显示区
如果先看什么就点击add 但是都需要订阅对应的话题
gazebo
roslaunch gazebo_ros willowgarage_world.launch