ROS 通信机制(已整理)

节点与节点管理器

在这里插入图片描述
图形化说明
在这里插入图片描述

ROS通信机制

1. 话题通信

在这里插入图片描述
在这里插入图片描述
这里的/image_data是话题,message是传递的话题内容
在这里插入图片描述

msg是消息中间件,数据载体,方便通信
适用于不断更新的数据传输相关的应用场景

ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。
在这里插入图片描述
在这里插入图片描述

1.1 基本话题通信

1.1.1 C++实现
发布方 demo01_pub.cpp
#include"ros/ros.h"
#include"std_msgs/String.h"
#include<sstream>
/*
    发布方实现:
        1.包含头文件
            ROS中文本类型--->std_msgs/String.h
        2.初始化ROS节点
        3.创建节点句柄
        4.创建发布者对象
        5.编写发布逻辑并发布数据
*/

int main(int argc,char *argv[])
{
    // 解决中文乱码问题
    setlocale(LC_ALL,"");
    // 2.初始化ROS节点
    ros::init(argc,argv,"erGouZi");//ergouzi是节点名称,相当于是相亲对象,这里的ergouzi就是talker

    // 3.创建节点句柄
    ros::NodeHandle nh;

    // 4.创建发布者对象
    ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
    //缓存10条数据,话题名称是fang,队列长10,由于网络阻塞,没有发出去,则存储在这里,最大容量是10,超出阈值后先放进去的先销毁

    // 5.编写发布逻辑并发布数据
    
    // 5.1 创建被发布的消息
    std_msgs::String msg;

    // 5.2 要求以10HZ 的频率发布数据,并且文本后添加编号
    // 5.2.1 发布频率
    ros::Rate rate(1);//每秒发布10次
    // 5.2.2 设置编号
    int count = 0;

    // 订阅时,第一条数据丢失;原因: 发送第一条数据时, publisher 还未在 roscore 注册完毕
    ros::Duration(3).sleep();//延迟3秒

    // 5.3 编写循环,循环要发布的消息
    while(ros::ok())//如果节点还活着,循环成立
    {
        count++;
        //msg.data = "hello";
        //实现字符串的拼接
        std::stringstream ss;
        ss << "hello ---> " << count;
        msg.data = ss.str();
        pub.publish(msg);
        //添加日志:
        ROS_INFO("发布的数据是:%s",msg.data.c_str());
        rate.sleep();// 发布一次,睡0.1秒
        ros::spinOnce();//每次循环完都回头一次,spinOnce()只调用一次回调函数,之后会继续往下执行,官方建议,处理回调函数
    }
    return 0;
}
订阅方 demo01_sub.cpp
#include "ros/ros.h"
#include"std_msgs/String.h"
/*
    订阅方实现:
        1.包含头文件
            ROS中文本类型--->std_msgs/String.h
        2.初始化ROS节点
        3.创建节点句柄
        4.创建订阅者对象
        5.处理订阅到的数据
        6.spin()函数
*/

void doMsq(const std_msgs::String::ConstPtr &msg)//std_msgs String类型常量指针的引用,保证传入的实参是常量
{
    //通过msg获取并且操作订阅到的数据
    ROS_INFO("翠花订阅的数据:%s",msg->data.c_str());//指针的引用
    // ROS_INFO("我听见:%s",(*msg_p).data.c_str());
}

int main(int argc, char *argv[])
{
    //解决乱码问题
    setlocale(LC_ALL,"");
    // 2.初始化ROS节点
    ros::init(argc,argv,"cuiHua");//节点名称具有唯一性
    // 3.创建节点句柄
    ros::NodeHandle nh;
    // 4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("fang",10,doMsq);//fang是两者的共同话题,doMsq是回调函数
    // 5.处理订阅到的数据

    ros::spin();//spin意思是回头,main函数从上往下一次执行,回头调用doMsq函数,doMsq需要被频繁执行
    return 0;
}
1.1.2 Python
发布方 demo01_pub_p.py
#! /usr/bin/env python

import rospy
from std_msgs.msg import String # 发布的消息类型
"""
    使用python实现消息发布:
        1.导包;
        2.初始化ros节点
        3.创建发布者对象
        4.编写发布逻辑并发布数据

"""
if __name__ == "__main__":

    # 2.初始化ros节点
    rospy.init_node("sanDai") # 传入节点名称
    # 3.创建发布者对象
    pub = rospy.Publisher("che",String, queue_size = 10) # che是话题名称,类型是String,消息队列大小为10
    # 4.编写发布逻辑并发布数据
    # 4.1 创建数据类型
    msg = String()

    # 4.2 指定发布频率
    rate = rospy.Rate(1)

    # 4.3 设置计数器
    count = 0

    # 休眠3s,完成在master下面的注册
    rospy.sleep(3)

    # 4.4 循环发布数据
    while not rospy.is_shutdown(): # 判断当前节点是否已经关闭,没有关闭则发布数据
        count += 1 # 如果要将count追加到hello后面,则需要将其变为字符串
        msg.data = "hello" + str(count)
        # 4.5 发布数据
        pub.publish(msg)
        # 4.6 添加日志输出
        rospy.loginfo("发布的数据:%s",msg.data)
        rate.sleep()
订阅方 demo01_sub_p.py
#! /usr/bin/env python

import  rospy
from std_msgs.msg import String
"""
    订阅实现流程:
        1.导包
        2.初始化ROS节点
        3.创建订阅者对象
        4.回调函数处理数据
        5.spin()
"""

def doMsg(msg): #将订阅到的数据传进来
    rospy.loginfo("订阅的数据:%s",msg.data) #data是数据

if __name__ == "__main__":

    # 2.初始化ROS节点
    rospy.init_node("huaHua")
    # 3.创建订阅者对象
    sub = rospy.Subscriber("che",String,doMsg,queue_size = 10)
    # sub = rospy.Subscriber("fang",String,doMsg,queue_size = 10) 跨语言通信
    # 4.回调函数处理数据
    # 5.spin()
    rospy.spin()

1.2 自定义msg话题通信

1.2.1 C++实现
发布方 demo02_pub_person.cpp
#include"ros/ros.h"
#include"plumbing_pub_sub/Person.h"
/*
    发布方:发布人的消息
        1.包含头文件
        #include"plumbing_pub_sub/Person.h"
        2.初始化ROS节点
        3.创建节点句柄
        4.创建发布者对象
        5.编写发布逻辑,发布数据
*/

int main(int argc, char  *argv[])
{
    // 解决中文乱码问题
    setlocale(LC_ALL,"");

    // 添加日志
    ROS_INFO("这是消息发布方");

    // 2.初始化ROS节点
    ros::init(argc, argv,"banZhuRen");

    // 3.创建节点句柄
    ros::NodeHandle nh;

    // 4.创建发布者对象
    ros::Publisher pub = nh.advertise<plumbing_pub_sub::Person>("liaoTian",10); // 消息类型是功能包plumbing_pub_sub下面的Person
    
    // 5.编写发布逻辑,发布数据
    // 5.1 创建被发布的数据
    plumbing_pub_sub::Person person;
    person.name = "张三";
    person.age = 1;
    person.height = 1.73;

    // 5.2 设置发布频率
    ros::Rate rate(1);

    // 5.3 循环发布数据
    while(ros::ok())
    {
        //修改数据
        person.age += 1;
        //核心:数据发布
        pub.publish(person);
        //打印消息
        ROS_INFO("发布的消息:%s,%d,%.2f",person.name.c_str(),person.age,person.height);
        //休眠
        rate.sleep();
        //建议:使用回调函数
        ros::spinOnce();
    }
    return 0;
}
订阅方 demo02_sub_person.cpp
#include"ros/ros.h"
#include"plumbing_pub_sub/Person.h"

/*
    订阅方:订阅的消息
        1.包含头文件
        #include"plumbing_pub_sub/Person.h"
        2.初始化ROS节点
        3.创建节点句柄
        4.创建订阅者对象
        5.处理订阅的数据
        6.spin()
*/
void doPerson(const plumbing_pub_sub::Person::ConstPtr& person){
    ROS_INFO("订阅人的信息:%s,%d,%.2f",person->name.c_str(),person->age,person->height);
}

int main(int argc, char *argv[])
{
    // 中文乱码问题
    setlocale(LC_ALL,"");
    
    //添加日志
    ROS_INFO("订阅方实现");

    // 2.初始化ROS节点
    ros::init(argc,argv,"jiaZhang");

    // 3.创建节点句柄
    ros::NodeHandle nh;

    // 4.创建订阅者对象
    ros::Subscriber sub = nh.subscribe("liaoTian",10,doPerson);

    // 5.处理订阅的数据
    // 6.spin()
    ros::spin();
    return 0;
}
1.2.2 Python实现
发布方 demo02_pub_person_p.py
#! /usr/bin/env python
"""
    发布方:发布人的消息
        1.导包
        2.初始化ROS节点
        3.创建发布者对象
        4.组织发布逻辑并发布数据

"""
import rospy
from plumbing_pub_sub.msg import Person

if __name__ == "__main__":

    # 2.初始化ROS节点
    rospy.init_node("daMa")
    # 3.创建发布者对象
    pub = rospy.Publisher("jiaoSheTou",Person,queue_size=10)
    # 4.组织发布逻辑并发布数据
    # 4.1 创建Person
    p = Person()
    p.name = "奥特曼"
    p.age = 8
    p.height = 1.85
    # 4.2 创建Rate对象
    rate = rospy.Rate(1)
    # 4.3 循环发布数据
    while not rospy.is_shutdown():
        pub.publish(p)
        rospy.loginfo("发布的消息:%s,%d,%.2f",p.name,p.age,p.height)
        rate.sleep()
订阅方 demo02_sub_person_p.py
#! /usr/bin/env python
"""
    订阅方:订阅人的消息
        1.导包
        2.初始化ROS节点
        3.创建订阅者对象
        4.处理订阅的数据
        5.spin()

"""

import rospy
from plumbing_pub_sub.msg import Person

def doPerson(p):
    rospy.loginfo("小伙子的数据:%s,%d,%.2f",p.name,p.age,p.height)

if __name__ == "__main__":
    # 2.初始化ROS节点
    rospy.init_node("daYe")
    # 3.创建订阅者对象
    sub = rospy.Subscriber("jiaoSheTou",Person,doPerson,queue_size=10)
    # 4.处理订阅的数据
    # 5.spin()
    rospy.spin()

2. 服务通信

在这里插入图片描述
在这里插入图片描述
服务通信模型

在这里插入图片描述

适用于对时时性有要求、具有一定逻辑处理的应用场景。基于请求响应模式的,是一种应答机制。一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。

ROS Master 负责保管 Server 和 Client 注册的信息,并匹配话题相同的 Server 与 Client ,帮助 Server 与 Client 建立连接,连接建立后,Client 发送请求信息,Server 返回响应信息。

在这里插入图片描述

和话题通信相比,服务通信必须是服务端先启动,然后客户端启动。就是说客户端发起请求时,服务端已经启动

srv包括请求+响应

srv目录下的AddInts里面进行设置时除了32后面其他地方不能加空格

2.1 服务通信实现

2.1.1 C++实现
服务端 demo01_server.cpp
#include "ros/ros.h"
#include "plumbing_server_client/AddInts.h"
/*
    服务端实现:解析客户端提交的数据,并运算再产生响应
        1.包含头文件
        2.初始化ROS节点
        3.创建节点句柄
        4.创建一个服务端对象
        5.处理请求并产生响应
        6.spin()
*/

bool doNums(plumbing_server_client::AddInts::Request &request,
            plumbing_server_client::AddInts::Response &response){
    //1.处理请求
    int num1 = request.num1;
    int num2 = request.num2;
    ROS_INFO("收到的请求数据:num1 = %d,num2 = %d",num1,num2);
    //2.组织响应
    int sum = num1 + num2;
    response.sum = sum;
    ROS_INFO("求和的结果:sum = %d",sum);

    return true;
}
int main(int argc, char *argv[])
{
    //解决乱码问题
    setlocale(LC_ALL,"");

    // 2.初始化ROS节点
    ros::init(argc,argv,"heiShui");//节点名称

    // 3.创建节点句柄
    ros::NodeHandle nh;

    // 4.创建一个服务对象
    ros::ServiceServer server = nh.advertiseService("addInts",doNums);//addInts是话题名称,用于连接二者
    ROS_INFO("服务器端启动");

    // 5.处理请求并产生响应
    // 6.spin()
    ros::spin();
    
    return 0;
}
客户端 demo02_client.cpp
#include "ros/ros.h"
#include "plumbing_server_client/AddInts.h"
/*
    客户端:提交两个整数,并处理响应的结果
        1.包含头文件
        2.初始化ROS节点
        3.创建节点句柄
        4.创建一个客户端对象
        5.提交请求并产生响应

    实现参数的动态提交:
        1.格式:rosrun xxxx xxxxx 12 34 后面两个是需要相加的参数
        2.节点执行时,需要获取命令中的参数 并组织进request

    问题:
        如果先启动客户端,那么会请求异常
    需求:
        如果先启动,不要直接抛出异常,而是挂起,等服务器启动后,再正常请求。
    解决:
        在ROS中提供内置相关函数,可以让客户端启动后挂起,等待服务端启动
        client.waitForExistence();
        ros::service::waitForService("话题名称")
*/

//  char* argv[]:是一个数组,每个元素存储的一个指针,就是穿进去的参数的地址。
int main(int argc, char  *argv[])//字符串数组,数组中存放的是数据的地址,读取时是读取数组里存储的地址对应的数据
{
    //解决乱码问题
    setlocale(LC_ALL,"");

    //优化实现,获取命令中参数,实现动态 // 有1个参数argc为2,函数本身1+参数1=argc2
    if(argc != 3){
        ROS_INFO("提交的参数个数不对。");
        return true;
    }

    // 2.初始化ROS节点
    ros::init(argc,argv,"daBao");

    // 3.创建节点句柄
    ros::NodeHandle nh;

    // 4.创建一个客户端对象
    ros::ServiceClient client = nh.serviceClient<plumbing_server_client::AddInts>("addInts");//话题是addInts

    // 5.提交请求并产生响应
    plumbing_server_client::AddInts ai;
    // 5.1 组织请求
    ai.request.num1 = atoi(argv[1]);//argv[1]表示的是12,atoi将字符串变成整型
    ai.request.num2 = atoi(argv[2]);//argv[2]表示的是34
    // 5.2 处理响应
    //判断服务器状态的函数
    //函数1
    //client.waitForExistence();//客户端等待,实现挂起功能
    //函数2
    ros::service::waitForService("addInts");
    bool flag = client.call(ai);// true表示正常处理,否则为失败
    if(flag)
    {
        ROS_INFO("响应成功");
        //获取结果
        ROS_INFO("响应结果:%d",ai.response.sum);
    }
    else{
        ROS_INFO("处理失败");
    }

    return 0;
}
2.1.2 Python实现
服务端 demo01_server_p.py
#! /usr/bin/env python # 指定编译器
"""
    服务端:解析客户端请求,产生响应。

        1.导包
        2.初始化ROS节点
        3.创建服务端对象
        4.处理逻辑
        5.spin()
"""

import rospy
from plumbing_server_client.srv import AddInts,AddIntsRequest,AddIntsResponse
# import plumbing_server_client import *

# 回调函数
# 参数:封装了请求数据 返回值:响应数据
def doNum(request):
    # 1. 解析提交的两个整数
    num1 = request.num1
    num2 = request.num2

    # 2. 求和
    sum = num1 + num2

    # 3. 将结果封装进响应
    response = AddIntsResponse()
    response.sum = sum # 将sum赋值给响应对象的sum,即可完成封装
    rospy.loginfo("服务器解析的数据:num1 = %d, num2 = %d,响应的结果:sum = %d",num1,num2,sum)
    return response

if __name__ == "__main__":
    
    # 2.初始化ROS节点
    rospy.init_node("heiShui")

    # 3.创建服务端对象
    server = rospy.Service("addInts",AddInts,doNum)# Addints表示消息对应类型,addInts表示话题名称
    rospy.loginfo("服务器已经启动了")
    # 4.处理逻辑
    # 5.spin()
    rospy.spin()
  • 问题:如果先启动客户端,那么会请求异常
  • 需求:如果先启动,不要直接抛出异常,而是挂起,等服务器启动后,再正常请求
  • 解决:在ROS中提供内置相关函数,可以让客户端启动后挂起,等待服务端启动
  • client.waitForExistence()
  • ros::service::waitForService(“话题名称”)
客户端 demo02_client_p.py
#! /usr/bin/env python # 指定编译器
"""
    客户端:组织并提交请求,处理服务端响应
        1.导包
        2.初始化ROS节点
        3.创建客户端对象
        4.组织请求数据,并且发送请求
        5.处理来自服务端的响应

    优化实现:
        可以在执行节点时,动态传入参数,使用sys
    
    
    问题:
        客户端先于服务端启动,那么会抛出异常
    需求:
        如果客户端先启动,不要直接抛出异常,而是挂起,等服务器启动后,再正常请求。
    解决:
        在ROS中提供内置相关函数,可以让客户端启动后挂起,等待服务端启动
"""

import rospy
from plumbing_server_client.srv import AddInts,AddIntsRequest,AddIntsResponse
import sys

if __name__ == "__main__":

    # 判断参数长度
    if len(sys.argv) != 3:
        rospy.loginfo("传入的参数个数不对")
        sys.exit(1)

    # 2.初始化ROS节点
    rospy.init_node("erHei")

    # 3.创建客户端对象
    client = rospy.ServiceProxy("addInts",AddInts)

    # 4.组织请求数据,并且发送请求,call函数就是发请求的
    # 解析传入的参数 argv[0]表示程序名
    num1 = int(sys.argv[1])
    num2 = int(sys.argv[2]) # 将字符串转化为整型

    # 在客户端之后,发送请求之前调用。等待服务器启动
    # client.wait_for_service()
    rospy.wait_for_service("addInts")

    response = client.call(num1,num2)

    # 5.处理来自服务端的响应
    rospy.loginfo("相应的数据:%d",response.sum)
  • 问题:客户端先于服务端启动,那么会抛出异常
  • 需求:如果客户端先启动,不要直接抛出异常,而是挂起,等服务器启动后,再正常请求
  • 解决:在ROS中提供内置相关函数,可以让客户端启动后挂起,等待服务端启动
  • 法1:client.wait_for_service()
  • 法2:rospy.wait_for_service(“addInts”)

3. 参数服务器

实现不同节点之间的数据共享

参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,不同的节点也可以往其中存储数据。

  • rosparam list:可以列出参数服务器里的参数
  • rosparam get /type:得到类型参数的具体值
  • rosparam get /type_param

3.1 增改

3.1.1 C++实现 demo01_param_set.cpp
#include"ros/ros.h"
/*
    需要实现参数的新增和修改
    需求:属县设置机器人的共享参数,类型,半径(0.15m)
        再修改半径(0.2m)
    实现:
        ros::NodeHandle
            setParam("键",值)
        ros::param
            set("键",值)
    修改,只需要继续调研 setParam 或者 set函数,保证键是已经存在的,那么值会覆盖
*/

int main(int argc, char *argv[])
{
    // 初始化ROS节点
    ros::init(argc,argv,"set_param_c");

    // 创建ROS节点句柄
    ros::NodeHandle nh;

    // 参数增-------------------------
    // 方案1:nh
    nh.setParam("type","xiaoHuang");// 类型
    nh.setParam("radius",0.15);// 半径
    // 方案2:ros::param
    ros::param::set("type_param","xiaoBai");
    ros::param::set("radius_param",0.15);

    // 参数改-------------------------
    // 方案1:nh
    nh.setParam("radius",0.2);//参数的覆盖
    
    // 方案2:ros::param
    ros::param::set("radius_param",0.25);

    return 0;
}
3.1.2 Python实现 demo01_param_set_p.py
#! /usr/bin/env python

import rospy
"""
    演示参数的新增与修改
    需求:子阿参数服务器中设置机器人属性:型号,半径

"""

if __name__ == "__main__":
    # 初始化ros节点
    rospy.init_node("param_set_p")

    # 新增参数
    rospy.set_param("type_p","xiaoHuangChe") # 设置 键,值
    rospy.set_param("radius_p",0.5)
    
    # 修改参数
    rospy.set_param("radius_p",0.2) # 后面的语句会覆盖前面的值

3.2 查

3.2.1 C++实现 demo02_param_get.cpp
#include "ros/ros.h"
/*
    演示参数查询
    实现:
        ros::NodeHandle--------------------
            param(键,默认值) 
            存在,返回对应结果,否则返回默认值

            getParam(键,存储结果的变量)
                存在,返回 true,且将值赋值给参数2
                若果键不存在,那么返回值为 false,且不为参数2赋值

            getParamCached键,存储结果的变量)--提高变量获取效率
                存在,返回 true,且将值赋值给参数2
                若果键不存在,那么返回值为 false,且不为参数2赋值

            getParamNames(std::vector<std::string>)
                获取所有的键,并存储在参数 vector 中 

            hasParam(键)
                是否包含某个键,存在返回 true,否则返回 false

            searchParam(参数1,参数2)
                搜索键,参数1是被搜索的键,参数2存储搜索结果的变量

        ros::param-------------------------
            set("键",值)
*/

int main(int argc, char *argv[])
{
    // 设置编码
    setlocale(LC_ALL,"");

    // 初始化ROS节点
    ros::init(argc,argv,"get_param_c");

    // 创建节点句柄
    ros::NodeHandle nh;

    // ros::NodeHandle--------------------
    // 1.param
    double radius = nh.param("radius",0.5);//查询键为radius的值,没有的话返回0.5
    ROS_INFO("radius = %.2f",radius);

    // 2.getParam
    double radius2 = 0.0;
    bool result = nh.getParam("radius",radius2);// 第1个是键,第2个是存储结果的变量
    if(result)
    {
        ROS_INFO("获取的半径是:%.2f",radius2);
    }else{
        ROS_INFO("被查询的变量不存在");
    }

    // 3.getParamCached 与getParam类似,底层性能有提升,一般测试下,看不出来
    // double radius3 = 1.0;
    // bool result = nh.getParamCached("radius",radius3);
    // if(result)
    // {
    //     ROS_INFO("获取的半径是:%.2f",radius3);
    // }else{
    //     ROS_INFO("被查询的变量不存在");
    // }

    // 4.getParamNames
    std::vector<std::string> names;
    nh.getParamNames(names);
    // 遍历names,获取每个键的名称
    for(auto &&name : names)
    {
            ROS_INFO("遍历的元素:%s",name.c_str());//转化成c风格的字符串
    }

    // 5.hasParam 判断元素是否存在
    bool flag1 = nh.hasParam("radius");
    bool flag2 = nh.hasParam("radiusxxx");
    ROS_INFO("radius 存在吗? %d",flag1);
    ROS_INFO("radiusxxx 存在吗? %d",flag2);

    // 6.searchParam 搜索键
    std::string key;
    nh.searchParam("radius",key);
    ROS_INFO("搜索结果:%s",key.c_str());

    // ros::param-------------------------
    double radius_param = ros::param::param("radius",10);// 如果查询不到,就用默认值
    ROS_INFO("radius_param = %.2f",radius_param);

    std::vector<std::string> names_param;
    ros::param::getParamNames(names_param);
    for(auto &&name : names_param)
    {
        ROS_INFO("键:%s",name.c_str());// 转成c风格
    }

    return 0;
}
3.2.2 Python实现 demo02_param_get_p.py
#! /usr/bin/env python

import rospy
"""
     参数服务器操作之查询_Python实现:    
        get_param(键,默认值)
            当键存在时,返回对应的值,如果不存在返回默认值
        get_param_cached 
            和get_param 使用一致,效率高
        get_param_names
            获取所有参数键的集合
        has_param
            判断是否包含某个键
        search_param
            查找某个参数的键,并返回完整的键名

"""

if __name__ == "__main__":

    rospy.init_node("get_param_p")
    # 1.get_param 根据键获取参数的值
    radius1 = rospy.get_param("radius_p",0.5)
    radius2 = rospy.get_param("radius_pxxx",0.5)

    rospy.loginfo("radius1 = %.2f",radius1)
    rospy.loginfo("radius2 = %.2f",radius2)

    # 2.get_param_cached  效率比第1个高
    radius3 = rospy.get_param("radius_p",0.5)
    radius4 = rospy.get_param("radius_pxxx",0.5)

    rospy.loginfo("radius3 = %.2f",radius1)
    rospy.loginfo("radius4 = %.2f",radius2)

    # 3.get_param_names 遍历包
    names = rospy.get_param_names()
    for name in names:
        rospy.loginfo("name = %s",name)

    # 4.has_param 判断某个键是否存在
    flag1 = rospy.has_param("radius_p")
    if flag1:
        rospy.loginfo("radius_p 存在")
    else:
        rospy.loginfo("radius_p 不存在")

    flag2 = rospy.has_param("radius_pxxx")
    if flag2:
        rospy.loginfo("radius_pxxx 存在")
    else:
        rospy.loginfo("radius_pxxx 不存在")

    # 5.search_param 查询是否存在,存在则返回键名
    key = rospy.search_param("radius_p")
    rospy.loginfo("key = %s",key)

3.3 删

3.3.1 C++实现 demo03_param_del.cpp
#include"ros/ros.h"

/*
    实现:
        ros::NodeHandle
            deleteParam()
        ros::param
            del()
*/

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc,argv,"param_del_c");

    ros::NodeHandle nh;

    //删除:NodeHandle
    bool flag1 = nh.deleteParam("radius");
    if(flag1)
    {
        ROS_INFO("删除成功");
    }else{
        ROS_INFO("删除失败");
    }

    //删除:ros::param
    bool flag2 = ros::param::del("radius_param");
    if(flag2)
    {
        ROS_INFO("radius_param删除成功");
    }else{
        ROS_INFO("radius_param删除失败");
    }
    return 0;
}
3.3.2 Python实现 demo03_param_del_p.py
#! /usr/bin/env python

import rospy
"""
    演示参数删除:
        delete_param()
"""

if __name__ == "__main__":
    rospy.init_node("del_param_p")

    # 使用try捕获异常,使它不显示错误(第2次删除会抛出异常)
    try:
        # 删除参数
        rospy.delete_param("radius_p")
    except Exception as e:
        rospy.loginfo("被删除的参数不存在")
  • 2
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021 Nqq

你的鼓励是我学习的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值