学习笔记11/06/2024 Cardiff
0 致自己
又是美好的一天,下次早餐鸡蛋煮久一点,8min应该能熟。今天不是休息日,记得去运动。
3 ROS基础
大概搂了一眼本章内容,好像开始‘helloworld环节’了,话说ROS的吉祥物是只龟龟欸(托腮)。看来在实践之前得完成一下虚拟机以及ROS的安装。
本章主要包含:工作空间和功能包创建,集成开发环境的搭建,话题和服务的实现方法,ROS中的命名空间及解析方法,ROS分布式通信的方法。【个人理解:读完之后感觉确实都覆盖到了,而且十分有必要实操辅助,一边看一边学能领悟更深。为没安装好ROS的自己伤心1s】
3.1给了一个前提概要,当然这个实际案例也不是毫无作用,引用文中的解释:'一方面可以验证ROS是否安装成功,另一方面也可以对ROS有一个 初步的认识。'
3.1.1引出介绍一个’turtlesim功能包‘。回顾:ROS功能包->主要包含config、include、scripts、src、launch、msg、srv、action、CMakeLists.txt、package.xml等;原文:‘每一个ROS功能包都是一个独立的功能,其中可能包含一个或者多 个节点,这些功能对外使用话题、服务、参数等作为接口。其他开发者 在使用这个功能包时,可以不用关注内部的代码实现,只需要知道这些接口的类型和作用,就可以集成到自己的系统中。’【个人理解:’就好比在JAVA中我import了一个Math,其中的ADD_Function我不知道其工作原理,只知道Function ADD(a,b)可以将数据a和数据b相加‘,不过我认为如果理解原理,应该会更好明白类似于:Function ADD(string('a'),string('b'))=195】
3.1.2给了实际控制台指令,(个人觉得跟着做更好理解)
##【提示:同一个系统里面可以开多个终端】
##在Ubuntu系统中打开一个终端
$roscore
##然后打开一个新终端(第二个),使用rosrun命令启动turtlesim仿真器节点
$rosrun turtlesim turtlesim_node
##需要载打开一个新终端(第三个),运行键盘控制的节点
$rosrun turtlesim turtle_teleop_key
3.2 创建工作空间和功能包
【个人理解:有点像归类文件夹->就像利用unity进行游戏开发的时候往往会把场景文件放在Assets里面,而脚本文件的话放在Scripts文件夹里面】
3.2.1 工作空间
3.2.1.1 定义:
‘工作空间(workspace)是一个存放工程开发相关文件的文件夹。’
经典的工作空间一般包含src(代码空间)、build(编译空间)、devel(开发空间)、install(安装空间)【个人理解:工作空间就好比一个厂房,其中有不同的车间---存储,分拣,组装,封装】
3.2.1.2 创建工作空间
##运行ROS工作空间初始化命令
$mkdir -p ~/catkin_ws/src
$cd ~/catkin_ws/src
$catkin_init_workspace
##编译整个空间
$cd ~/catkin_ws/
$catkin_make
##使用source命令运行devel文件夹产生的几个setup.*sh形式的环境变量设置脚本文件,使其生效
$source devel/setup.bash
3.2.1.3 创建功能包
- 在package/路径下一般有package.xml文件(提供功能包元信息,类似于清单)和CMakeLists.txt文件(记录功能包编辑规则)。
- ROS不允许在某个功能包中嵌套其他功能包,多个功能包必须平行 放置在代码空间中。
##ROS提供直接创建功能包的命令catkin_create_pkg
##$catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
|
|
V
##首先进入代码空间,使用catkin_create_pkg命令创建功能包
$cd ~/catkin_ws/src
$catkin_create_pkg learning_communication std_msgs rospy roscpp
##然后回到工作空间的根目录下进行编译,并且设置环境变量
$cd ~/catkin_ws
$catkin_make
$source ~/catkin_ws/devel/setup.bash
3.2.2 工作空间的覆盖
’OS允许多个工作空间并存,每个工作空间的创建、编译、运行方 法都相同,用户可以在不同项目的工作空间中创建所需要的功能包。但 有一种情况:不同的工作空间中可能存在相同命名的功能包,如果这些 工作空间的环境变量都已经设置,那么在使用该功能包的时候,是否会 发生冲突?如果不会,ROS又会帮我们选择哪一个功能包呢?‘【读到这里感觉“工作空间”就像是libraries文件夹,同时可以存在多个library(也像是在一个代码文件中可以import多个library一样)。在代码中也是要小心不同library中的同名function】
3.2.2.1 ROS中工作空间覆盖
机制——Overlaying。’所有工作空间的路径会依次在ROS_PACKAGE_PATH环境变量中记 录,当设置多个工作空间的环境变量后,新设置的路径在 ROS_PACKAGE_PATH中会自动放置在最前端。在运行时,ROS会优 先查找最前端的工作空间中是否存在指定的功能包,如果不存在,就顺 序向后查找其他工作空间,直到最后一个工作空间为止。‘【个人理解:像叠罗汉,解除也得从最上面的先搬开】
3.4 Eclipse开发环境(略)
没有实操很难受,所以先放放,过两天配置好之后记得回来看!!!
3.5 RoboWare开发环境(略)
(同上)
3.6 话题中的Publisher与Subscriber
Publisher(发布者)/ Subscriber(订阅者)
【果然,‘hello world’要来哩】
3.6.2 如何创建Publisher
- 头文件部分
#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;
/*·收到SIGINT信号(Ctrl+C)。
·被另外一个相同名称的节点踢掉线。
·节点调用了关闭函数ros::shutdown()。
·所有ros::NodeHandles句柄被销毁。*/
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.6.3 如何创建Subscriber
#include "ros/ros.h"
#include "std_msgs/String.h"
// 接收到订阅的消息后,会进入消息回调函数
void chatterCallback(const std_msgs::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的话题,注册回调函数chatterCallback
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
其中void chatterCallback(){}是个会调和函数。回调函数是订阅节点接受消息的基础机制,当有消息到达时会自动一消息指针作为参数。
3.6.4 编译功能包(C++专属)
’节点的代码已经完成,C++是一种编译语言,在运行之前需要将代 码编译成可执行文件,如果使用Python等解析语言编写代码,则不需要 进行编译,可以省去此步骤。‘【疑问,但是我记得不是指针也是C类型语言专属的么,那如果用python编译的话,虽然可以省区编译的步骤但是前面的回调函数部分应该怎么做出改变】
3.6.5 运行Publisher & Subscriber
0.设置环境变量(否则无法找到功能包最终编译生成的可执行文件
$cd ~/catkin_ws
$source ./devel/setup.bash
1.启动roscore
$roscore
2.启动Publisher
$rosrun learning_communication talker
3.启动Subscriber
$rosrun learning_communication listener
3.6.6 自定义话题消息
‘这些常量在发布或订阅消息数据时可以直接使用,相当于C++中的 宏定义’
【个人理解:这里的消息就是变量,可以有不同种类型】
其中:
- seq是消息的顺序标识,不需要手动设置,Publisher在发布消 息时会自动累加;
- stamp是消息中与数据相关联的时间戳,可以用于时 间同步;
- frame_id是消息中与数据相关联的参考坐标系id。
此处定义的 消息类型较为简单,也可以不加头信息。 为了使用这个自定义的消息类型,还需要编译msg文件。msg文件 的编译需要注意以下两点
- 在package.xml中添加功能包依赖
<build_depend>message_generation</build_depend>
<run_depend>message_runtime</run_depend>
- 在CMakeLists.txt中添加编译选项
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
roscpp
rospy
std_msgs
message_generation
)
3.7 服务中的Server和Client
3.8 Ros中的命名空间
3.9 分布式多机通信
【小日记:今天去健身毫无动力,下午喝着咖啡看书居然差点睡着。还是实操更加让人振奋呀。早上安装VMware装虚拟机的效果不佳(卡顿+bug),明天捣鼓捣鼓看看能不能分100G的盘出来,装个Linux系统到电脑上玩玩。】
【话说今天徐哥回国了,屋子里面又空荡了几分;】
【还有,晚上看见外面一堆人,原来是隔壁球场开演唱会;】
【嘿,呆瓜,0:30了,还不睡觉,什么奇怪强迫症,非要整理完再睡觉么,困。晚安呆不拉几】