赵老师课件链接:http://www.autolabor.com.cn/book/ROSTutorials/
1.1 Hello world!实现

mkdir -p 自定义空间名称/src
cd 自定义空间名称
catkin_make
cd src
catkin_create_pkg 自定义ROS包名 roscpp rospy std_msgs
先进入用户目录。

按住Ctrl+t,创建一个工作空间。

mkdir -p hello_world/src //创建一个叫“hello_world"的工作目录,目录下有叫"src”的目录
cd hello_world //进入目录“hello_world"
catkin_make //编译

然后会发现除了src,还多了build和devel两个目录。

cd src //目录src
catkin_create_pkg hello_world roscpp rospy std_msgs
//创建功能包 功能包的名称 三个依赖包
src目录中会出现两个包体

进入目录中的src目录(不要把两个src目录弄混)

创建.cpp文件
#include "ros/ros.h"
int main(int argc,char *argv[])
{
ros::init(argc,argv,"hello_node");//初始化ros节点
ROS_INFO("hello world!");//ros中的输出函数
return 0;
}
CMakLists.txt配置
打开CMakeLists.txt文件

找到136行

回到工作空间的目录

打开终端(窗口1)
catkin_make
编译

编译成功
再新开一个窗口2(Ctrl+T)
roscore
启动ROS核心

回到原窗口
source ./devel/setup.bash//修改环境变量
rosrun helloworld haha
//运行 包名 映射名
输出如图

1.2 VScode实现Hello world

在VScode里创建目录
经典创建文件

mkdir -p test2/src //创建目录下有src目录的test2目录
cd test2 //打开test2
catkin_make //编译
code . //启动vscode

配置使Ctrl+Shift+B能编译文件
Ctrl+Shift+B呼出任务栏(快捷选项和选中的文件夹有关)

打开后将内容替换为:
{
// 有关 tasks.json 格式的文档,请参见
// https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"label": "catkin_make:debug", //代表提示的描述性信息
"type": "shell", //可以选择shell或者process,如果是shell代码是在shell里面运行一个命令,如果是process代表作为一个进程来运行
"command": "catkin_make",//这个是我们需要运行的命令
"args": [],//如果需要在命令后面加一些后缀,可以写在这里,比如-DCATKIN_WHITELIST_PACKAGES=“pac1;pac2”
"group": {"kind":"build","isDefault":true},
"presentation": {
"reveal": "always"//可选always或者silence,代表是否输出信息
},
"problemMatcher": "$msCompile"
}
]
}
使Ctrl+Shitf+B可以编译文件
右键src,下滑,选择"Create Catkin Package“

输入一个name(随意)

输入这三个依赖

创建文件如下:

在src右键新建文件
编码

#include "ros/ros.h"
int main(int argc,char *argv[])
{
ros::init(argc,argv,"hello"); //初始化
ROS_INFO("hello world"); //输出
return 0;
}
然后我们会发现莫名其妙的报错(其实运行起来没问题)
让VScode不会乱报错
打开文件,修改成酱紫
{
"configurations": [
{
"browse": {
"databaseFilename": "", //这项
"limitSymbolsToIncludedHeaders": true //这项
},
"includePath": [
"/opt/ros/noetic/include/**",
"/home/elysian-realm/textbook/src/helloworld/include/**",//这项
"/usr/include/**"
],
"name": "ROS",
"intelliSenseMode": "gcc-x64",
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17", //这项
"cppStandard": "c++17" //这项
}
],
"version": 4
}
这样就不会莫名其妙报错了
打开文件

具体配置看CMakLists.txt配置
VScode中运行代码
编译后打开新终端
启动核心

再新建终端

rosrun中第二个名称为映射名
中文乱码问题
在main里面加入
setlocale(LC_ALL,"");
1.3 launch文件

新建launch文件夹,文件格式是.xml

文件基本格式

launch文件的运行代码

source ./devel/setup.bash
roslaunch hello_vscode start_turtle.launch
// 包名 文件名
然后继续填写launch文件

<launch>
<!-- 添加被执行的节点 -->
<node pkg="turtlesim" type="turtlesim_node" name="turtle_GUI"/>
//包名 节点 命名
<node pkg="hello_vscode" type="hello_vscode_c" name="" output="screen"/>
//输出到屏幕上
</launch>
1.4 ROS文件系统
2.0 话题通信理论模型


2.1.1 话题通信理论模型
整个流程由以下步骤实现:
0.Talker注册
Talker启动后,会通过RPC在 ROS Master 中注册自身信息,其中包含所发布消息的话题名称。ROS Master 会将节点的注册信息加入到注册表中。
1.Listener注册
Listener启动后,也会通过RPC在 ROS Master 中注册自身信息,包含需要订阅消息的话题名。ROS Master 会将节点的注册信息加入到注册表中。
2.ROS Master实现信息匹配
ROS Master 会根据注册表中的信息匹配Talker 和 Listener,并通过 RPC 向 Listener 发送 Talker 的 RPC 地址信息。
3.Listener向Talker发送请求
Listener 根据接收到的 RPC 地址,通过 RPC 向 Talker 发送连接请求,传输订阅的话题名称、消息类型以及通信协议(TCP/UDP)。
4.Talker确认请求
Talker 接收到 Listener 的请求后,也是通过 RPC 向 Listener 确认连接信息,并发送自身的 TCP 地址信息。
5.Listener与Talker件里连接
Listener 根据步骤4 返回的消息使用 TCP 与 Talker 建立网络连接。
6.Talker向Listener发送消息
连接建立后,Talker 开始向 Listener 发布消息。
注意1:上述实现流程中,前五步使用的 RPC协议,最后两步使用的是 TCP 协议
注意2: Talker 与 Listener 的启动无先后顺序要求
注意3: Talker 与 Listener 都可以有多个
注意4: Talker 与 Listener 连接建立后,不再需要 ROS Master。也即,即便关闭ROS Master,Talker 与 Listern 照常通信。
1.发布方逻辑实现
老流程,在src目录里"Create Catkin Package“,导入依赖包。
新建.cpp文件,编码如下
#include "ros/ros.h"
#include "std_msgs/String.h"
/*
发布方实现:
1.包含头文件:
ros中文本类型 ---> std_msgs/String.h
2.初始化ROS节点
3.创建节点句柄
4.创建发布者对象
5.编写发布逻辑并发布数据
*/
int main(int argc, char *argv[])
{
//2.初始化ROS节点
ros::init(argc,argv,"ErGouZi");//第三个参数是节点名称
//3.创建节点句柄B
ros::NodeHandle nh;
//4.创建发布者对象
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
//5.编写发布逻辑并发布数据
//先创建被发布的信息
std_msgs::String msg;
//编写循环,循环中发布数据
while(ros::ok())
{
msg.data = "hello";
pub.publish(msg);
}
return 0;
}
关于前几条数据丢失的补充(important)
发送数据之前要现在master那里注册,然而经常会出现注册完成之前发送就已经开始的情况,酱紫会导致前几条数据丢失,所以经常在循环前进行如下操作:
ros::Duration(3).sleep();
让程序休眠3秒,给注册留足时间
老规矩,调CMakeLists包

代码详解:
NodeHandle
ros::NodeHandle nh;

ros::NodeHandle nh; // 创建NodeHandle对象
// 创建一个发布器
ros::Publisher pub = nh.advertise<std_msgs::String>("example_topic", 10);
// 创建一个订阅器
ros::Subscriber sub = nh.subscribe("example_topic", 10, callback);


advertise
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);

ros::Publisher advertise<MsgType>(const std::string &topic, uint32_t queue_size, bool latch = false);


ros::ok()
while(ros::ok())

2.发布逻辑实现
将代码做出如下修改

#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");//第三个参数是节点名称
//3.创建节点句柄B
ros::NodeHandle nh;
//4.创建发布者对象
ros::Publisher pub = nh.advertise<std_msgs::String>("fang",10);
//5.编写发布逻辑并发布数据
//先创建被发布的信息
std_msgs::String msg;
//设置发布频率
ros::Rate rate(10);//10HZ
//设置计数器
int count=0;
//编写循环,循环中发布数据
while(ros::ok())
{
count++;
//msg.data = "hello";
//创建对象
std::stringstream ss;
//将数据插入ss的缓冲区
ss<<"hello--->"<< count;
//从ss中提取字符串(string)并传递给msg
msg.data=ss.str();
pub.publish(msg);
//从ss中提取字符串,转化为c风格并传递给%s
ROS_INFO("发布的数据是:%s",ss.str().c_str());
//根据rate设置的频率延时(类似于delay)
rate.sleep();
}
return 0;
}
代码详解:
std::stringstream ss;
ss << "hello--->" << count;
msg.data = ss.str();
pub.publish(msg);
ROS_INFO("发布的数据是:%s", ss.str().c_str());
数据流分析

ss.str().c_str()分析

3.订阅逻辑实现
新建.cpp文件,编码如下

#include "ros/ros.h"
#include "std_msgs/String.h"
/*
发布方实现:
1.包含头文件:
ros中文本类型 ---> std_msgs/String.h
2.初始化ROS节点
3.创建节点句柄
4.创建订阅者对象
5.处理订阅到的数据
6.spin()函数
*/
//5.处理订阅到的数据
void doMsg(const std_msgs::String::ConstPtr &msg)
{
ROS_INFO("翠花订阅的数据:%s",msg->data.c_str());
}
int main(int argc, char *argv[])
{
//2.初始化ROS节点
ros::init(argc,argv,"CuiHua");//节点不能重名,要有唯一性
//3.创建节点句柄
ros::NodeHandle nh;;
//4.创建订阅者对象
ros::Subscriber sub = nh.subscribe("fang",10,doMsg);//泛型会自动识别
ros::spin();
return 0;
}
记得配置CMakeLists

代码详解:
ConstPtr
void doMsg(const std_msgs::String::ConstPtr &msg)
{
ROS_INFO("翠花订阅的数据:%s",msg->data.c_str());
}

对msg补充

spin()
ros::spin();
据弹幕说和单片机的中断很像
机制上确实很像

2.1.2话题通信自定义msg
在资源包下方创建文件夹

在文件夹里创建文件(一般为.msg格式)

在文件中定义需要录入的message(和结构体很像)
类型后面的数字表示数据的位数
然后找到package.xml

找到CMakeLists.txt(步骤很多)
1. 10行找到find_package表示编译时需要依赖于msg功能包

2. 51行找到add_messge_files(里面的两个message文件仅仅是示例)

修改成酱紫

3. 71行,放开
表示编译Person.msg要依赖于std_msgs
因为Person.msg中每一条消息的实现都是标准消息,所以要构建这种依赖关系

4. 108行,放开,添加message_runtime
catkin_package和find_package相对应,编译时依赖于find_package,find_package又依赖于catkin_package。
find_package出错会导致编译出错
catkin_package出错可能编译不会有问题,但是运行结果会出问题

编译
然后会生成许多文件
其中,Person.h是c++的头文件
_Person.py是python的

配置vscode(主要是防止异常报错,不配置也能正常运行)
右键,在集成终端中打开

pwd,打印当前路径

添加到c_cpp_properties.json的includePath里
其中的“**”表示该路径里的任意文件

自定义msg的使用
发布方实现
代码如下

#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,"");
//2.初始化ROS节点
ros::init(argc,argv,"BanZhuRen");
//3.创建节点句柄
ros::NodeHandle cc;
//4.创建发布者对象
ros::Publisher pub = cc.advertise<plumbing_pub_sub::Person>("chat",10);
//5.编写发布逻辑并发布数据
plumbing_pub_sub::Person person;
//5-1.传建被发布的数据
person.name = "张三";
person.age = 1;
person.height = 1.73;
//5-2.设置发布频率
ros::Rate rate(1);
//5-3.循环发布数据
while(ros::ok())
{
//修改发布数据
person.age++;
//核心:数据发布
pub.publish(person);
//休眠
rate.sleep();
//建议
ros::spinOnce();
}
return 0;
}
配置CMakeLists.txt

调用头部包

代码详解:
spinOnce()
ros::spinOnce();

add_dependencies
add_dependencies(demo03_pub_person ${PROJECT_NAME}_generate_messages_cpp)
为了防止源文件被编译时头文件没有被被编译而导致出错,先编译头文件,再编译源文件。
Add:关于回调机制
大致可以类比为单片机中的中断(interrupt)

spin() 函数
堵塞当前进程并保持活跃等待回调。
spinOnce()函数
不堵塞当前进程但是会在回调时相应。
回调事件例如:

回调函数则例如之前编写的doMsg函数:
void doMsg(const std_msgs::String::ConstPtr &msg)
{
ROS_INFO("翠花订阅的数据:%s",msg->data.c_str());
}
ros::Subscriber sub = nh.subscribe("fang",10,doMsg);//泛型会自动识别
订阅方实现
其实和之前差不多,源代码需要对这些做改动

需要注意的是person和结构体不一样,不能用person.xxx
在CMakeLists.txt的配置上和发布方相同。
2.2服务通信

0.Server在Master中注册自己的话题和RPC地址(远程通话地址)
1.Client在Master里注册个人信息(只有话题)
2.Master将ROS RPC地址传递给Client(不是原本的RPC地址,这个地址经过ROS的封装)
4.Client拿到地址后对Server进行请求
5.Server收到请求后产生相应给Client(TCP通信)
2.2.1服务端实现
先新建文件(在1.2里有)
在src的子目录里创建srv文件夹,在srv文件夹里创建.srv文件,格式如下

# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum
配置package
祖宗之法,不可变也

配置CMakeLists
配置方式和话题通信相同,除了这里

配置c_cpp_properties.json
1.打开devel下的include文件夹,右键,在集成终端中打开
2.pwd:复制当前文件的地址
3.打开c_cpp_properties.json
4.在"includePash"里加入路径如图

新建.cpp,编码如下

#include "ros/ros.h"
#include "plumbing_server_client/AddInts.h"
/*
服务端实现:解析客户端提交的数据,并运算再产生响应
1.包含头文件
*/
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("soyo的道歉次数:sum1=%d,sum2=%d",num1,num2);
//2.组织响应
int sum=num1+num2;
response.sum=sum;
ROS_INFO("你这个人,真的满脑子都是自己呢x%d",sum);
return true;
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//2.初始化ROS节点
ros::init(argc,argv,"soyo");//节点名称唯一
//3.创建节点句柄
ros::NodeHandle nh;
//4.创建一个服务对象
ros::ServiceServer server=nh.advertiseService("addInts",doNums);//有回调函数后泛型会自动推导
ROS_INFO("你能在五秒内说八次对不起吗?");
//5.处理服务对象并产生响应
//6.spin()
ros::spin();
return 0;
}
配置CMakeLists
148行第一个是映射名,第二个是固定格式,相当于“功能包+_gencpp"
意为先编译头文件,再编译源文件

运行
调用ros的service服务,call后面跟话题,空格,Tab按两次补齐
修改参数,回车得到结果

2.2.2客户端实现
新建.cpp文件
编码如下

#include "ros/ros.h"
#include "plumbing_server_client/AddInts.h"
/*
客户端实现:提交两个整数,并处理结果
1.包含头文件
2.初始化ROS节点
3.创建节点句柄
4.创建一个客户端对象
5.提交请求并处理响应
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//2.初始化ROS节点
ros::init(argc,argv,"DaBao");
//3.创建节点句柄
ros::NodeHandle nh;
//4.创建一个客户端对象
ros::ServiceClient client = nh.serviceClient<plumbing_server_client::AddInts>("addInts");
//5.提交请求并处理响应
plumbing_server_client::AddInts ai;
//5-1.组织请求
ai.request.num1 = 10;
ai.request.num2 = 20;
//5-2.处理响应
bool flag = client.call(ai);
if (flag)
{
ROS_INFO("响应成功!");
//获取结果
ROS_INFO("sum=%d",ai.response.sum);
}
else
{
ROS_INFO("处理失败!");
}
return 0;
}
配置CMakeLists
将这三处复制并改为客户端的就行。

代码详解:
ros::ServiceClient client = nh.serviceClient<plumbing_server_client::AddInts>("addInts");

服务客户端和服务端必须使用相同的 .srv 文件定义并共享相同的服务名称
bool flag = client.call(ai);
client呼叫服务端并返回值(一般为运行结果)
返回值来自doNums的返回值

2.2.3客户端优化实现
修改代码

#include "ros/ros.h"
#include "plumbing_server_client/AddInts.h"
/*
客户端实现:提交两个整数,并处理结果
1.包含头文件
2.初始化ROS节点
3.创建节点句柄
4.创建一个客户端对象
5.提交请求并处理响应
实现参数的动态提交:
1.格式: rosrun xxxx xxxx num num
2.节点执行时,需要获取命令中的参数,并组织进 request
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//实现优化,获取命令中的参数
if(argc!=3)
{
ROS_INFO("输入错误,请重试!");
return 0;
}
//2.初始化ROS节点
ros::init(argc,argv,"DaBao");
//3.创建节点句柄
ros::NodeHandle nh;
//4.创建一个客户端对象
ros::ServiceClient client = nh.serviceClient<plumbing_server_client::AddInts>("addInts");
//5.提交请求并处理响应
plumbing_server_client::AddInts ai;
//5-1.组织请求
// ai.request.num1 = 10;
// ai.request.num2 = 20;
ai.request.num1 = atoi(argv[1]);
ai.request.num2 = atoi(argv[2]);
//5-2.处理响应
bool flag = client.call(ai);
if (flag)
{
ROS_INFO("响应成功!");
//获取结果
ROS_INFO("sum=%d",ai.response.sum);
}
else
{
ROS_INFO("处理失败!");
}
return 0;
}
实现效果

代码解析:
if(argc!=3)
{
ROS_INFO("输入错误,请重试!");
return 0;
}
//2.初始化ROS节点
ros::init(argc,argv,"DaBao");
关于这里为什么后进行初始化

可以看到init会自动解析数据并剔除无用内容,此处argv[0]为文件名
关于atoi
ai.request.num1 = atoi(argv[1]);
ai.request.num2 = atoi(argv[2]);


2.2.4注意事项

应位于组织数据之前,发送请求之后

实现效果

2.3参数服务器
2.3.1 参数服务器理论模型
2.3.2 对参数的增/改
新建功能包和源文件,编码如下

#include "ros/ros.h"
/*
需要实现参数的新增与修改
*/
int main(int argc, char *argv[])
{
ros::init(argc,argv,"set_param_set");
ros::NodeHandle nh;
//参数新增:
//manner1:句柄.setParam("键",值)
nh.setParam("type","daHuang");
nh.setParam("radius",0.15);
//manner2:ros::param::set("键",值)
ros::param::set("type_1","xiaoBai");
ros::param::set("radius_1",0.15);
//参数修改:同上,本质是覆盖
nh.serParam("type","xiaoHuang");
return 0;
}
CMakeLists配置

实现结果

rosparam list:展示当前参数服务器的所有参数
rosparam get /键:查询键的值
2.3.3 参数服务器获取参数
API 1:
参数服务器操作之查询_C++实现: 在 roscpp 中提供了两套 API 实现参数操作 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 ----- 与 NodeHandle 类似
解析:getParamCached:
查询缓存中是否已经有该键(之前是否被调用过),若有,则直接调用,没有,执行远程调用。
getParamNames:

ros::NodeHandle nh;
std::vector<std::string> names;
nh.getParamNames(names);
for(auto &&name: names)
{
ROS_INFO("遍历的元素:%s",name.c_str());
}
std::vector<std::string> names;
1.声明和初始化
std::vector<std::string> names; // 空的字符串向量
std::vector<std::string> names = {"Alice", "Bob", "Charlie"}; // 初始化列表
2.添加元素
names.push_back("David"); // 在末尾添加 "David"
3.访问元素
std::cout << names[0] << std::endl; // 访问第一个元素(不安全)
std::cout << names.at(0) << std::endl; // 安全访问第一个元素
4.删除元素
names.pop_back(); // 删除末尾元素
names.erase(names.begin() + 1); // 删除第二个元素
5.插入元素
names.insert(names.begin(), "Eve"); // 在开头插入 "Eve"
6.迭代元素
for (const auto& name : names) {
std::cout << name << std::endl; // 打印每个名字
}
7.获取大小和容量
std::cout << names.size() << std::endl; // 当前元素个数
std::cout << names.capacity() << std::endl; // 当前分配的容量
8.清空元素
names.clear(); // 清空向量
循环解析:

实现效果:

searchParam:

实现效果:

API 2:
使用的是param命名空间下的函数(ros::param::function)实际作用可根据名称与上面一一对应

2.3.4参数服务器删除函数
参数服务器操作之删除_C++实现: ros::NodeHandle deleteParam("键") 根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false ros::param del("键") 根据键删除参数,删除成功,返回 true,否则(参数不存在),返回 false
2.4常用命令
2.4.1 rosnode
rosnode ping 测试到节点的连接状态
rosnode list 列出活动节点
rosnode info 打印节点信息
rosnode machine 列出指定设备上节点
rosnode kill 杀死某个节点
rosnode cleanup 清除不可连接的节点
可以使用rosnode列出相关指令

rosnode xx -h可以详细查询

打开话题通信

rosnode list效果如下
其中rosout是roscore启动的节点

rosnode ping查看节点连接状况

rosnode info查看节点信息

rosnode machine查看某设备上的节点

rosnode kill效果如下


rosnode cleanup:
启动乌龟节点和控制节点,再关闭

节点依然被认为存活
可以用cleanup清除

2.4.2 rostopic
rostopic bw 显示主题使用的带宽
rostopic delay 显示带有 header 的主题延迟
rostopic echo 打印消息到屏幕
rostopic find 根据类型查找主题
rostopic hz 显示主题的发布频率
rostopic info 显示主题相关信息
rostopic list 显示所有活动状态下的主题
rostopic pub 将数据发布到主题
rostopic type 打印主题类型
打开话题通信
rostopic list

后两个是和日志相关的
rostopic echo 获取相应话题传递的消息

需要注意的是,如果使用的是自定义类型的消息,需要进入相关目录才能使用
rostopic pub可以发布消息

格式:rostopic pub (-r num(消息发布的频率,可不谢)) 话题 消息类型 后面可以用Tab补齐
rostopic info
查看话题的相关信息

rostopic hz查看话题发布频率(每发布一次,打印一次)

2.4.3 rosservice
rosservice args 打印服务参数
rosservice call 使用提供的参数调用服务
rosservice find 按照服务类型查找服务
rosservice info 打印有关服务的信息
rosservice list 列出所有活动的服务
rosservice type 打印服务类型
rosservice uri 打印服务的 ROSRPC uri
启动服务端

rosservice list

后四个与日志相关
rosservice call 服务(两次Tab补齐,数据修改后回车)

rossevice info

rosservice type打印服务的数据类型

2.4.4 rosmsg
rosmsg show 显示消息描述
rosmsg info 显示消息信息
rosmsg list 列出所有消息
rosmsg md5 显示 md5 加密后的消息
rosmsg package 显示某个功能包下的所有消息
rosmsg packages 列出包含消息的功能包
rosmsg list | grep -i msg名称,查询相关消息(全部列出很多,不方便使用)

rosmsg show显示消息描述(和info作用好像一样?)
2.4.5 rossrv
rossrv show 显示服务消息详情
rossrv info 显示服务消息相关信息
rossrv list 列出所有服务信息
rossrv md5 显示 md5 加密后的服务消息
rossrv package 显示某个包下所有服务消息
rossrv packages 显示包含服务消息的所有包
和msg一模一样,直接参考msg就行
2.4.6 rosparam
rosparam set 设置参数
rosparam get 获取参数
rosparam load 从外部文件加载参数
rosparam dump 将参数写出到外部文件
rosparam delete 删除参数
rosparam list 列出所有参数
rosparam list(这里全是roscore的)

rosparam set

rosparam get

rosparam delete

rosparam dump xx.yaml将参数保存到磁盘上(序列化)



重启roscore
rosparam load xx.yaml将磁盘上的数据载入到内存中

2.5 实操
2.5.1 控制乌龟运动
1.话题与消息获取
列出话题,打开计算图确定是哪一个


获取话题下的消息类型

获取消息的格式

分别为线速度和角速度
线速度中的xyz对于三维坐标系中的坐标表示的含义
角速度中的xyz可以参考文档:2.5.1 实操01_话题发布 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程
视频:098实操01_话题发布03_速度格式_Chapter2-ROS通信机制_哔哩哔哩_bilibili
2.验证速度消息
挂起

控制乌龟运动获得消息
2.5 实操
2.5.1 控制乌龟运动
1.话题与消息获取
列出话题,打开计算图确定是哪一个


获取话题下的消息类型

获取消息的格式

分别为线速度和角速度
线速度中的xyz对于三维坐标系中的坐标表示的含义
角速度中的xyz可以参考文档:2.5.1 实操01_话题发布 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程
视频:098实操01_话题发布03_速度格式_Chapter2-ROS通信机制_哔哩哔哩_bilibili
2.验证速度消息
挂起

控制乌龟运动获得消息





被折叠的 条评论
为什么被折叠?



