15. ROSプログラミング学習:タートルを生成するサービス通信

目次

準備

C++ はサービス通信を通じてタートルを生成します

Python はサービス通信を通じてタートルを生成します


準備

開始する前に、まず起動ファイルを書き込みます

roslaunch wugui_ttest wugui_start.launch

すべての ROS サービスをリストする

rosservice list
rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosservice list
/clear
/key/get_loggers
/key/set_logger_level
/kill
/reset
/rosout/get_loggers
/rosout/set_logger_level
/spawn
/turtle1/get_loggers
/turtle1/set_logger_level
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/wugui_pose/get_loggers
/wugui_pose/set_logger_level

サービス通信では、サーバーとクライアントが同じサービス名で通信し、サービスの詳細をリストする必要があるため、対応するサービスを見つけるにはサービス名を見つける必要があります。

rosservice info
rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rosservice info /spawn 
Node: /turtle1
URI: rosrpc://rosmelodic-virtual-machine:54625
Type: turtlesim/Spawn
Args: x y theta name

ノードのノード名、Type サービスのデータ型名、Args サービスが受信したリクエスト パラメーター名。

特定のサービス データ タイプをクエリするには、カスタム サービス データ タイプをクエリするときに、そのデータ タイプが配置されているワークスペースに入力してクエリを実行する必要があることに注意してください。

rossrv info
rosmelodic@rosmelodic-virtual-machine:~/catkin_ws$ rossrv info turtlesim/Spawn
float32 x
float32 y
float32 theta
string name
---
string name

(メッセージ数 2) 6. ROS プログラミング学習: サービス通信 —— カスタムサービスデータ

要求データと応答データは --- で区切られ、rosservice info で表示されるサービスの詳細が同時に検索され、要求されたデータ型のみが表示されます。

コンソールターミナルのコマンドを使用して新しいタートルを生成してみます。

rosservice call
rosservice call /spawn "x: 2.0
y: 2.0
theta: 3.14
name: 'turtle2'"

 実際のアプリケーションでは論理的な関係があるため、ターミナル上のコマンドによってタートルを生成するだけでは満足できません。

C++ はサービス通信を通じてタートルを生成します

プログラムの C++ ヘッダー ファイルと Python ライブラリは Turtlesim パッケージを使用する必要があるため、turtlesim パッケージがインポートされているかどうかを判断する必要があります。

package.xmlファイルを確認してください

<build_depend>turtlesim</build_depend>
<exec_depend>turtlesim</exec_depend>

CMakeList.txtを確認してください

find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  std_msgs
  turtlesim
)

 ファイル wugui_service_client.cpp を作成します。

 wugui_service_client.cpp

クライアントの書き方は以下を参照してください。(2 メッセージ) 7. ROS プログラミング学習: カスタム サービス データ C++ call_mechanical コンピューター初心者ブログ - CSDN ブログhttps://blog.csdn.net/wzfafabga/article/details/127383302

#include "ros/ros.h"
#include "turtlesim/Spawn.h"

/* 
    乌龟生成的服务端已经有了,需要客户端给其发布消息
    服务名称:/spawn 通过rosservice list查询到的
    服务通信的消息数据类型:turtlesim/Spawn 通过rosservice info查询到的

    1.头文件
    2.初始化ROS节点
    3.初始化节点句柄
    4.创建客户端
    5.组织与发布数据
    6.处理响应
*/

int main(int argc, char *argv[])
{
    // 防止控制台中文乱码
    setlocale(LC_ALL,"");
    // 初始化ROS节点
    ros::init(argc,argv,"wugui_service_call");
    // 初始化节点句柄
    ros::NodeHandle n;
    // 创建客户端
    ros::ServiceClient client = n.serviceClient<turtlesim::Spawn>("/spawn");
    // 组织数据
    turtlesim::Spawn wugui_xiaoxi;
    wugui_xiaoxi.request.x = 3.0;
    wugui_xiaoxi.request.y = 3.0;
    wugui_xiaoxi.request.theta = 3.14;
    wugui_xiaoxi.request.name = "turtle2";
    // 等待服务端启动,客户端挂起
    client.waitForExistence();
    // 发布数据,并返回一个发布成功与否的布尔类型值
    bool tiaojian = client.call(wugui_xiaoxi);
    // 根据返回的布尔值,按照条件输出字符串
    if(tiaojian)
    {
        ROS_INFO("乌龟已经生成,名字是:%s",wugui_xiaoxi.response.name.c_str());
    }
    else
    {
        ROS_INFO("乌龟消息接收失败,乌龟生成失败!!!");
    }
    return 0;
}

 注意すべき点は、コンソールによって出力される文字列は c の文字列でなければならないということです。そうしないと、エラーが報告され、データ型が間違っています。

ROS_INFO("乌龟已经生成,名字是:%s",wugui_xiaoxi.response.name.c_str());

もう 1 つの注意点は、クライアントの作成後、クライアントの下で waitForExistence 関数が呼び出され、クライアントが最初にサーバーを起動してからエラーの報告を開始することを防ぐために、クライアントの一時停止関数が追加されることです。

client.waitForExistence();

CMakeList.txt ファイルを構成する

add_executable(wugui_service_client src/wugui_service_client.cpp)
add_dependencies(wugui_service_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(wugui_service_client
  ${catkin_LIBRARIES}
)

コンパイル

catkin_make

前のブログ投稿の起動ファイルを開始します

(メッセージ数 2) 14.ROS プログラミング学習: Turtle Pose_Machinery Professional Computer に関するトピックの購読 Xiaobai のブログ - CSDN ブログhttps://blog.csdn.net/wzfafabga/article/details/127495303

roslaunch wugui_ttest wugui_start.launch

クライアントを起動する

roslaunch はデフォルトで roscore (ROS マスター) を開始するため、roscore は必要ないことに注意してください。

rosrun wugui_ttest wugui_service_client 

結果

 クライアントノードを起動ファイルに入れます

<!-- 启动乌龟GUI和键盘控制节点 -->
<launch>
    <!-- 乌龟GUI -->
    <node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen"/>
    <!-- 键盘控制 -->
    <node pkg="turtlesim" type="turtle_teleop_key" name="key" output="screen"/>
    <!-- 乌龟位姿订阅 -->
    <node pkg="wugui_ttest" type="test01_sub_pose_p.py" name="wugui_pose" output="screen"/>
    <!-- 加一个乌龟 -->
    <node pkg="wugui_ttest" type="wugui_service_client" name="wugui_spawn" output="screen"/>
</launch>

起動ファイルを再度開始します

rosrun wugui_ttest wugui_service_client 

Python はサービス通信を通じてタートルを生成します

 wugui_service_client_p.py を作成する

 wugui_service_client_p.py

#! /usr/bin/env python
# -*- coding: UTF-8 -*-

""" 
    乌龟生成的服务端已经有了,需要客户端给其发布消息
    服务名称:/spawn 通过rosservice list查询到的
    服务通信的消息数据类型:turtlesim/Spawn 通过rosservice info查询到的

    1.导入包
    2.初始化ROS节点
    3.创建客户端
    4.组织与发布请求数据
    5.处理响应
"""

import rospy
from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse
import logging
logging.basicConfig()

if __name__ == "__main__":
    rospy.init_node("wugui_service_call_p")
    client = rospy.ServiceProxy(name="/spawn", service_class=Spawn)
    request = SpawnRequest()
    request.x = 4.0
    request.y = 4.0
    request.theta = 3.14
    request.name = "turtle3"
    client.wait_for_service()
    try:
        response = client.call(request)
        rospy.loginfo("生成乌龟的名字:%s",response.name)
    except Exception as e:
        rospy.logerr("请求失败")
    # response = client.call(request)
    # rospy.loginfo("生成乌龟的名字:%s",response.name)

注 1: client.call の前に client.wait_for_service() を追加して、サーバーが開かれる前にクライアントがハングするようにします。

注2:

インポートログ

logging.basicConfig() は、rospy.logerr がエラーを報告するのを防ぎます。

実行権限を追加する

chmod +x *.py

CMakeList.txtの設定(メロディックバージョンは必要ありません)

catkin_install_python(PROGRAMS
  scripts/wugui_service_client_p.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

コンパイル(メロディックバージョンは必要ありません)

catkin_make

開始前の起動ファイル

roslaunch wugui_ttest wugui_start.launch

クライアントを起動する

rosrun wugui_ttest wugui_service_client_p.py 

結果

 このクライアント ノードを起動ファイルに追加します

<!-- 启动乌龟GUI和键盘控制节点 -->
<launch>
    <!-- 乌龟GUI -->
    <node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen"/>
    <!-- 键盘控制 -->
    <node pkg="turtlesim" type="turtle_teleop_key" name="key" output="screen"/>
    <!-- 乌龟位姿订阅 -->
    <node pkg="wugui_ttest" type="test01_sub_pose_p.py" name="wugui_pose" output="screen"/>
    <!-- 加一个乌龟 -->
    <node pkg="wugui_ttest" type="wugui_service_client" name="wugui_spawn" output="screen"/>
    <!-- 加另一个乌龟 -->
    <node pkg="wugui_ttest" type="wugui_service_client_p.py" name="wugui_spawn_p" output="screen"/>
</launch>

ノードの起動は起動ファイルに従って順番に開始されるわけではないことに注意してください。また、カメ ノードの名前は異なっていなければなりません。そうしないと、サービス リクエストが失敗します。これは、このサーバーの特性です。

おすすめ

転載: blog.csdn.net/wzfafabga/article/details/127507114