【古月居】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