ROS学习之服务通信

根据b站赵老师的视频进行学习,下面给出代码

服务通信,可以用于两个无人车之间的通信。

(补充:动作通信可用于雷达之间的持续通信。

在客户端给出两个数 在服务端输出两个数之和

在前面的准备工作(如,创建工作空间,创建功能包等不再一一给出,详细请参考这一

ROS中话题通信之C++实现-CSDN博客

关于C++的服务端:

#include "rclcpp/rclcpp.hpp"
#include "base_interfaces/srv/addints.hpp"


//using namespace std::chrono_literals;
using base_interfaces::srv::Addints;
using std::placeholders::_1;
using std::placeholders::_2;

class AddintsServer: public rclcpp::Node{
public:
  AddintsServer():Node("add_ints_server_node_cpp"){
    RCLCPP_INFO(this->get_logger(),"server create!");
    server_ = this->create_service<Addints>("add_ints",std::bind(&AddintsServer::add,this,_1,_2));//创建服务端
    // use: ros2 topic echo /chatter 检测接收方 是否接受到
    //timer_ = this->create_wall_timer(1s,std::bind(&AddintsServer::on_timer,this));
  }
private:
//创建回调函数
  void add(const Addints::Request::SharedPtr req, const Addints::Response::SharedPtr res){
    res->sum = req->num1 + req->num2;
    RCLCPP_INFO(this->get_logger(),"%d + %d = %d",req->num1,req->num2,res->sum);
  }
  rclcpp::Service<Addints>::SharedPtr server_;
  //rclcpp::TimerBase::SharedPtr timer_;
  //size_t count;
};
int main(int argc, char ** argv)
{

  rclcpp::init(argc,argv);
  rclcpp::spin(std::make_shared<AddintsServer>());

  rclcpp::shutdown();
  return 0;
}

关于C++的客户端:

// listen 订阅发布的消息 并且在终端输出
// 1、包含头文件 2、初始化客户端 3、自定义节点类 4、调用spin函数 并且传入节点指针 5、支援释放
// 3.1、创建订约方 3、2 解释并且输出数据
#include "rclcpp/rclcpp.hpp"
#include "base_interfaces/srv/addints.hpp"

using base_interfaces::srv::Addints;
using namespace std::chrono_literals;
class AddintsClient: public rclcpp::Node{
public:
    AddintsClient():Node("add_ints_client_node_cpp"){
        RCLCPP_INFO(this->get_logger(),"client create!");
        //subscription_ = this->create_subscription<std_msgs::msg::String>("chatter",10,std::bind(&AddintsClient::do_cb,this,std::placeholders::_1));
        client_ = this->create_client<Addints>("add_ints");

    }
    bool connect_server(){
        // 在1s内 连接服务器 链接上返回true 否着 False
        //client_->wait_for_service(1s);
        while (!client_->wait_for_service(1s))
        {
            if (!rclcpp::ok())// 针对crtl+c 的特殊处理
            {
                RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Connect false in force...");
                return false;
                /* code */
            }
            
            RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"Connecting...");
            /* code */
        }
        
        return true;
    }
    rclcpp::Client<Addints>::FutureAndRequestId send_request(int num1,int num2){
        auto request = std::make_shared<Addints::Request>();
        request->num1 = num1;
        request->num2 = num2;
        return client_->async_send_request(request);
    }
private:
    rclcpp::Client<Addints>::SharedPtr client_;

    //rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};
int main(int argc, char const *argv[])
{
    if(argc != 3)
    {
        RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"give:num1 and num2");
        return 1;
    }
    rclcpp::init(argc,argv);
    //rclcpp::spin(std::make_shared<AddintsClient>());
    auto client = std::make_shared<AddintsClient>();
    bool flag = client->connect_server();
    if (!flag)
    {
        RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"false connect!");
        return 0;
        /* code */
    }

    auto future = client->send_request(atoi(argv[1]),atoi(argv[2]));
    if (rclcpp::spin_until_future_complete(client,future) == rclcpp::FutureReturnCode::SUCCESS)
    {
        /* code */
        RCLCPP_INFO(client->get_logger(),"success!sum = %d",future.get()->sum);
    }
    else
    {
        RCLCPP_INFO(client->get_logger(),"False");
    }
    
    rclcpp::shutdown();

    /* code */
    return 0;
}

相关的Cmakelist修改:

cmake_minimum_required(VERSION 3.8)
project(cpp02_service)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(base_interfaces REQUIRED)

add_executable(demo01_server src/demo01_server.cpp)
add_executable(demo02_client src/demo02_client.cpp)
target_include_directories(demo01_server PUBLIC
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
  $<INSTALL_INTERFACE:include>)
target_compile_features(demo01_server PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
ament_target_dependencies(
  demo01_server
  "rclcpp"
  "base_interfaces"
)

ament_target_dependencies(
  demo02_client
  "rclcpp"
  "base_interfaces"
)

install(TARGETS demo01_server
  DESTINATION lib/${PROJECT_NAME})

install(TARGETS demo02_client
  DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

ament_package()

结果如下:

下面给出Python相关代码:

import rclpy
from rclpy.node import Node
from base_interfaces.srv import Addints


class Addintsserver(Node):
    def __init__(self):
        super().__init__("add_ints_server_node_py")
        self.get_logger().info("server create!(py)")
        self.server = self.create_service(Addints,"add_ints",self.add)


    def add(self,request,response):
        response.sum = request.num1 + request.num2
        self.get_logger().info("%d + %d = %d" % (request.num1,request.num2,response.sum))
        return response


def main():

    rclpy.init()
    rclpy.spin(Addintsserver())
    rclpy.shutdown()


if __name__ == '__main__':
    main()

客户端:

import rclpy
import sys
from rclpy.logging import get_logger
from rclpy.node import Node
from base_interfaces.srv import Addints


class Addintsclient(Node):
    def __init__(self):
        super().__init__("add_ints_client_node_py")
        self.get_logger().info("client create!(py)")
        self.client = self.create_client(Addints,"add_ints")
        while not self.client.wait_for_service(1.0):
            self.get_logger().info("COnnetcing...")


    def send_request(self):
        request = Addints.Request()
        request.num1 = int(sys.argv[1])
        request.num2 = int(sys.argv[2])
        self.future = self.client.call_async(request)


def main():
    if len(sys.argv) != 3:
        get_logger("rclpy").info("Need two nums")
        return

    rclpy.init()
    client = Addintsclient()
    client.send_request()
    rclpy.spin_until_future_complete(client,client.future)
    try:
        response = client.future.result()
        client.get_logger().info("result: sum = %d" % response.sum)
    except Exception:
        client.get_logger().error("client fail")

    
    rclpy.shutdown()


if __name__ == '__main__':
    main()

需要对setup.py进行修改:

from setuptools import find_packages, setup

package_name = 'py02_service'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='xwh',
    maintainer_email='xwh@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'demo01_server_py = py02_service.demo01_server_py:main',
            'demo02_client_py = py02_service.demo02_client_py:main'
        ],
    },
)

运行后的结果,与C++的相同。

本篇与ROS学习之动作通信-CSDN博客这一篇是一起学习的,上传的程序代码包含了话题、服务、动作通信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值