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オペレーティングシステム研究ノート

おすすめ

転載: blog.csdn.net/QWERTYzxw/article/details/114917159