ROSは簡単な通信プログラミングを実現します
概要
インテリジェントロボットを使用して、簡単な通信プログラミングを実現します-
话题、服务、动作。
1.ワークスペースを作成します
1.ワークスペースとは
ワークスペース(workplace)は、プロジェクト開発関連のファイルを格納するためのフォルダーです。
src
:コードスペース(ソーススペース)build
:ビルドスペースdevel
:開発スペース(開発スペース)install
:設置スペース
2.ワークスペースを作成します
手順は次のとおりです。
mkdir -p ~/catkin_ws/src#创建文件夹
cd ~/catkin_ws/src#进入目录
catkin_init_workspace#初始化,使其成为ROS的工作空间
ワークスペースをコンパイルする
cd ..
catkin_make
環境変数を設定する
source /home/zxw/catkin_ws/devel/setup.bash#该环境变量设置只对当前终端有效,zxw是用户名
#将上面命令放置到~/.bashrc文件中,让其对所有终端都有效
sudo nano ~/.bashrc
環境変数を確認する
echo $ROS_PACKAGE_PATH
3.機能パッケージを作成します
手順は次のとおりです。
cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp
#catkin_create_pkg 功能包名字 依赖
#std_msgs:定义的标准的数据结构
#rospy:提供python编程接口
#roscpp:提供c++编程接口
コンパイル関数パッケージ
cd ~/catkin_ws
catkin_make
同一个工作空间下,不允许存在同名功能包;不同空间下,允许存在同名功能包。
4.作業スペースの範囲
rosワークスペースのオーバーレイメカニズム、つまりワークスペースのカバレッジ。
- ワークスペースのパスは、ROS_PACKAGE_PATH環境変数に順番に記録されます。
- 新しく設定されたパスは、ROS_PACKAGE_PATHの最前線に自動的に配置されます。
- 実行中、ROSは最初にフロントエンドワークスペースで指定された関数パッケージを探します。
- 存在しない場合は、他のワークスペースが順番に逆方向に検索されます。
2、コミュニケーションプログラミング-トピック
1.トピックプログラミングプロセス
- 出版社を作成する
- サブスクライバーを作成する
- コンパイルオプションを追加する
- 実行可能プログラムを実行する
2.発行者の実装
- ROSノードを初期化します。
- 公開されたトピックの名前やトピック内のメッセージタイプなど、ノード情報をROSマスターに登録します。
- ニュースを少しの頻度で回覧します。
talker.cpp
#include<sstream>
#include"ros/ros.h"
#include"std_msgs/String.h"
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"talker");
//创建节点句柄
ros::NodeHandle n;
//创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
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类型的消息
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;
}
3.加入者の実現
- ROSノードを初期化します。
- 必要なトピックを購読します。
- ループ内のトピックメッセージを待ち、メッセージを受信した後にコールバック関数に入ります。
- コールバック関数でメッセージ処理を完了します;
listener.cpp
#include"ros/ros.h"
#include"std_msgs/String.h"
//接收到订阅的消息,会进入消息的回调函数
void chatterCallback(const std_mmsgs::String::ConstPtr& msg)
{
//将接收到的消息打印处理
ROS_INFO("I heard:{%s}",msg->data.c_str());
}
int main(int argc,char **argv)
{
//初始化ROS节点
ros::init(argc,argv,"listener");
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback
ros::Subscriber sub=n.subscribe("chatter",1000,chatterCallback);
//循环等待回调函数
ros::spin();
return 0;
}
4.コードをコンパイルします
CMakeLists.txtファイルを設定します。
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${
catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${
catkin_LIBRARIES})
コンパイル
catkin_make
実行可能ファイルを実行します
roscore
rosrun learning_communication talker
rosrun learning_communication listener
5.カスタムトピック
メッセージファイルを定義する
mkdir ~/catkin_ws/src/learning_communication/msg
sudo nano Person.msg
person.msg
string name
uint8 sex
uint8 age
uint8 unknown=0
uint8 male=1
uint8 female=2
package.xmlに関数パッケージの依存関係を追加します
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
一部のROSバージョンでは、exec_dependをrun_dependに変更する必要があります
CMakeLists.txtにコンパイルオプションを追加し
ますカスタムメッセージを表示します
rosmsg show Person
三、コミュニケーションプログラミングサービス
1.サービスプログラミングプロセス
- サーバーを作成する
- クライアントを作成する
- コンパイルオプションを追加する
- 実行可能ファイルを実行します
カスタムサーバーの要求と応答
srvファイルを定義する
mkdir ~/catkin_ws/src/learning_communication/srv
sudo nano AddTwoInts.srv
AddTwoInts.srv
int64 a
int64 b
---
int64 sum
package.xmlに関数パッケージの依存関係を追加します
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
一部のROSバージョンでは、exec_dependをrun_dependに変更する必要があります
cmakelist.txtにコンパイルオプションを追加します
find_package(...... message_generation)
catkin_package(CATKIN_DEPENDS geometry roscpp rospy std_msgs message_runtime)
add_service_files(FILES AddTwolnts.srv)
2.サーバーの実現
- ROSノードを初期化します
- サーバーインスタンスを作成する
- ループでサービスリクエストを待ち、コールバック関数に入ります
- コールバック関数でサービス関数の処理を完了し、応答データ
server.cppをフィードバックします。
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
//service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
{
//将输入的参数中的请求数据相加,结果放到应答变量中
res.sum=req.a+req.b;
ROS_INFO("request: x=%1d,y=%1d",(long int)req.a,(long int)req.b);
ROS_INFO("sending back response:[%1d]",(long int)res.sum);
return true;
}
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"add_two_ints_server");
//创建节点句柄
ros::NodeHandle n;
//创建一个名为add_two_ints的server,注册回调函数add()
ros::ServiceServer service=n.advertiseService("add_two_ints",add);
//循环等待回调函数
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
3.クライアントの実装
- ROSノードを初期化します
- クライアントインスタンスを作成する
- サービスリクエストデータを公開する
- サーバー処理後の応答結果
client.cppを待機しています
#include<cstdlib>
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"add_two_ints_client");
//从终端命令行获取两个加数
if(argc!=3)
{
ROS_INFO("usage:add_two_ints_client X Y");
return 1;
}
//创建节点句柄
ros::NodeHandle n;
//创建一个client,请求add_two_ints_service
//service消息类型是learning_communication::AddTwoInts
ros::ServiceClient client=n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");
//创建learning_communication::AddTwoInts类型的service消息
learning_communication::AddTwoInts srv;
srv.request.a=atoll(argv[1]);
srv.request.b=atoll(argv[2]);
//发布service请求,等待加法运算的应答请求
if(client.call(srv))
{
ROS_INFO("sum: %1d",(long int)srv.response.sum);
}
else
{
ROS_INFO("Failed to call service add_two_ints");
return 1;
}
return 0;
}
4.コードをコンパイルします
CMakeLists.txtファイルを設定します
4、コミュニケーションプログラミング-アクション
1.カスタムアクションメッセージ
アクションファイルを定義する
mkdir ~/catkin_ws/src/learning_communication/action
sudo nano DoDishes.action
DoDishes.action
#定义目标信息
uint32 dishwasher_id
---
#定义结果信息
uint32 total_dishes_cleaned
---
#定义周期反馈的消息
float32 percent_complete
package.xmlに関数パッケージの依存関係を追加します
<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>
2.アクションサーバーを実装します
- ROSノードを初期化します
- アクションサーバーインスタンスを作成する
- アクションサーバーを起動します。アクションリクエストを待つ
- コールバック関数のアクションサービス関数の処理を完了し、進行状況情報をフィードバックします
- アクションが完了しました。終了メッセージを送信してください
DoDishes_server.cpp
#include "ros/ros.h"
#include "actionlib/server/simple_action_server.h"
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionServer<learning_communication::DoDishesAction> Server;
// 收到action的goal后调用该回调函数
void execute(const learning_communication::DoDishesGoalConstPtr &goal, Server *as)
{
ros::Rate r(1);
learning_communication::DoDishesFeedback feedback;
ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id);
// 假设洗盘子的进度,并且按照1Hz的频率发布进度feedback
for(int i = 1; i <= 10; i++)
{
feedback.percent_complete = i * 10;
as->publishFeedback(feedback);
r.sleep();
}
// 当action完成后,向客户端返回结果
ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id);
as->setSucceeded();
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "do_dishes_server");
ros::NodeHandle hNode;
// 定义一个服务器
Server server(hNode, "do_dishes", boost::bind(&execute, _1, &server), false);
// 服务器开始运行
server.start();
ros::spin();
return 0;
}
3.アクションクライアントを実装します
- ROSノードを初期化します
- アクションクライアントインスタンスを作成する
- アクションサーバーを接続する
- アクションターゲットを送信する
- さまざまなタイプのサーバーフィードバックに従って、コールバック関数
DoDishes_client.cppを処理します
#include "ros/ros.h"
#include "actionlib/client/simple_action_client.h"
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionClient<learning_communication::DoDishesAction> Client;
// 当action完成后会调用该回调函数一次
void doneCallback(const actionlib::SimpleClientGoalState &state
, const learning_communication::DoDishesResultConstPtr &result)
{
ROS_INFO("Yay! The dishes are now clean");
ros::shutdown();
}
// 当action激活后会调用该回调函数一次
void activeCallback()
{
ROS_INFO("Goal just went active");
}
// 收到feedback后调用该回调函数
void feedbackCallback(const learning_communication::DoDishesFeedbackConstPtr &feedback)
{
ROS_INFO("percent_complete : %f", feedback->percent_complete);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "do_dishes_client");
// 定义一个客户端
Client client("do_dishes", true);
// 等待服务器端
ROS_INFO("Waiting for action server to start.");
client.waitForServer();
ROS_INFO("Action server started, sending goal.");
// 创建一个 action 的 goal
learning_communication::DoDishesGoal goal;
goal.dishwasher_id = 1;
// 发送action的goal给服务端,并且设置回调函数
client.sendGoal(goal, &doneCallback, &activeCallback, &feedbackCallback);
ros::spin();
return 0;
}
4.コードをコンパイルします
CMakeLists.txtファイルを設定します
5、要約および参考資料
1.まとめ
ROS通信プログラミングの基本はある程度理解していて、まだ少し面倒ですが、インターネット上にも同様のチュートリアル資料があり、段階的に行うことができます。Baiduは途中で問題を解決します。
2.参考資料
ubuntu16.04(3/2)ROSの基本-ROS通信プログラミングの下でのROSオペレーティングシステム研究ノート。