ROS入门-笔记上,有问题可以留言,我们一起成长
本人跟着古月老师ROS入门21讲进行,汇集了本人的笔记,每一步都有代码,以及其中的代码实现和小误区,和古月老师的视频搭配观看效果最佳,b站就可以找到视频,入门下为第十三讲和二十一讲
一、ROS介绍
1、ROS学习曲线陡峭,上手不易
2、要懂C++、Python、Linux
二、Linux系统介绍
1、Linux开源
2、Linux企鹅作为标志
三、Linux系统基础操作
3.1 配置系统软件源
- 软件源:就是后续下载软件它是从什么地方下载的
- 点击开ubuntu软件,点击上面,然后点击软件和更新
- 家庭网选择aliyun镜像,如果是学校网就选择edu的后缀速度会比较快,如果实在不知道选择哪一个,就点击选择最佳服务器会自动帮你选择
- 然后点击选择服务器,输入密码,关闭,发现软件源更改要求重新载入,点击即可
3.2 终端
1、点击软件,右键打开软件与更新,在这里可以进行更改镜像,一般家里用mirrors.aliyun.com,校园网使用edu结尾的
2、命令行终端ctrl+alt+T
3.3 常用指令命令行
熟悉一些指令,首先打开终端,
1、查看当前终端所在路径:
pwd
2、切换路径到/xxx/xx,通过:
cd /xxx/xx
跳到上一级目录:cd ..
3、创建一个新的文件夹xxx:
mkdir xxx
4、查看当前路径下的文件
ls
5、在当前路径,新创建一个文件xxx_file:
touch xxx.file
6、剪切(移动)当前路径下文件文件xxx_file到路径 /xxx/xx
mv xxx.file /xxx/xx
7、copy当前路径下文件文件xxx_file到路径 /xxx/xx
cp xxx.file /xxx/xx
8、删除当前路径下文件xxx_file
rm xxx.file
9、递归的删除当前路径下文件夹xxx
rm -r xxx
10、提升用户的权限
sudo
10.1 重新载入,更新系统的软件源列表
sudo apt-get update
11、使用帮助指令,看到指令的使用方法
rm --help
四、C++/Python极简基础
4.1 安装g++编译器,指令:
sudo apt-get install g++
安装python编译器,指令为:
sudo apt-get install python
4.2 c++文件和python文件的实现
4.2.1 C++代码需要用g++对文件进行编译
首先,在对应路径下创建c++_for.cpp文件
然后编译:
g++ c++_for.cpp -o c++_for
-o后面是我们创建的可执行文件的名字,然后会发现该路径下多了我们刚才创建的一个新的可执行文件,windows可以双击执行,linux仍需要终端执行命令可使用:
./c++_for
4.2.2 python文件的直接指令即可:
创建python_for.py文件:
然后直接可以执行
python python_for.py
五、ROS是什么
1、松藕合分布式通信
2、ROS中的开发工具
3、ROS中的应用功能
4、ROS中的生态系统
六、ROS的核心理念
1、节点(Node)–执行单元
1.1、执行具体任务的进程、独立运行的可执行文件;
1.2、不同节点可使用不同的编程语言,可分布式运行在不同的主机;
1.3、节点在系统中的名称必须是唯一的。
2、节点管理器(ROS Master)
2.1、为节点提供命名和注册服务;
2.2、跟踪发和记录话题/服务通信,辅助节点相互查找、建立连接;
2.3、提供参数服务器,节点使用此服务器存储和检索运行时的参数。
3、话题(Topic)–异步通信机制
3.1、节点间用来传输数据的重要总线;
3.2、使用发布/订阅模型。数据有发布者传输到订阅者,同一个话题的订阅者或发布者可以不唯一。
4、消息(Message)–话题数据
4.1、具有一定的类型和数据结构,包括ROS提供的标准类型和用户自定义类型;
4.2、使用编程语言无关的.msg文件定义,编译过程中生成对应的代码文件
5、服务(Service)–同步通信机制
5.1、使用客户端/服务端(C/S)模型,客户端发送请求数据,服务器完成处理后返回应答数据;
5.2、使用编程语言无关的.srv文件定义请求和应答数据结构,编译过程中生成对应的代码文件。
6、参数(Parameter)–全局共享字典
6.1、可通过网络访问的共享,多变量字典;
6.2、节点使用此服务器来存储和检索运行时的参数;
6.3、适合存储静态、非二进制的配置参数,不适合存储动态配置的数据。
7、功能包(Package)
7.1、ROS软件中的基本单元,包含节点源码、配置文件、数据定义等
7.2、一般功能包是完成一些功能的,比如人脸识别,可以做成一个单独的功能包
8、功能包清单(Package manifest)
8.1、记录功能包的基本信息,包含作者信息,许可信息、依赖选项、编译标志灯。
9、元功能包(Meta Package)
9.1、很多功能包聚合在一切的大的功能包,组织多个用于同一目的功能包
10 工作空间的覆盖
- 工作空间的路径依次在ROS_PACKAGE_PATH环境变量中记录
- 新设置的路径在ROS_PACKAGE_PATH中会自动放置在最前端
- 运行时,ROS会优先查找最前端的工作空间中是否存在指定的功能包
- 如果不存在,就顺序向后查找其他工作空间
- 可以使用
env | grep ros
来查看所有与ros相关的环境变量
- 首先确保ros的一些历程安装
sudo apt-get install ros-melodic-roscpp-tutorials
- 安装之后看一下,ros从哪一个路径下帮我们去找到功能包(系统路径下的功能包)
bupo@bupo-vpc:~$ rospack find roscpp_traits
/opt/ros/melodic/share/roscpp_traits
- 如果创建一个新的工作空间catkin_ws,并且把功能包放进该新的工作空间,然后source一下,那么就会先查找到该工作空间下的同名工作包,然后停止查找(工作空间下的功能包)
bupo@bupo-vpc:~$ rospack find roscpp_traits
/home/bupo/lianxi/catkin_ws_15ke/src/roscpp_traits
- 这是因为查找路径是有一个顺序的,按照这个顺序进行
七、ROS命令行工具的使用
7.1常用命令:
rostopic
rosservice
rosnode
rosparam
rosmsg
rossrv
7.2 命令行演示
- 首先启动小海龟
在三个不同的终端中分别执行
roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
- 可视化图形指令
rqt_graph
- 显示所有节点相关的信息指令
rosnode
之后会出一些帮助
比如:系统中所有节点都列出来
rosnode list
/rosout默认的节点信息
查看某一个节点信息:
rosnode info /turtlesim
可以看到节点在发布哪些话题,服务,主机号
- 查看topic的一些信息,和rosnode用法相同
可以通过指令给话题发布数据:
rostopic pub /turtle1/cmd_vel geometry_msgs/Twist "linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0"
这里pub后面加不加 -数字 都可以
rostopic pub /话题名 发布的消息结构 “消息结构里具体数字”
在pub后面加上-r+数字是循环发布,一直发布,不停息,下面例子是1s
发布十次,10hz
rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist "linear:
x: 1.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 1.0"
- 查看message的一些信息,可以查看发布消息的格式,和rosnode用法相同:
rosmsg
使用:
rosmsg show 消息名称
rosmsg show geometry_msgs/Twist (例子)
得到:
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z
- 查看srevice的一些信息,和rosnode用法相同:
rosservice
这里我们可以多个海龟:
rosservice call /spawn "x: 2.0
y: 2.0
theta: 0.0
name: 'turtle2'"
定义海龟诞生的xy和角度坐标,以及它的名字
- 话题记录的工具rosbag
话题记录:
rosbag record -a -o cmd_record
-a就是all把所有的数据都保存下来
-o把保存的数据保存成压缩包,压缩包的名字就是后面的内容cmd_record,如果是小写的o,就会在名字后面加上日期时间,如果是大写的O就只会使用你给的名字
保存的路径是当前终端的路径
注意:输入上述指令之后才开始记录
记录结束之后直接ctrl+c就可以结束并且自动保存下来了
话题复现:
rosbag play cmd_record.bag
八 、创建工作空间与工具包
8.1工作空间(workspace)是一个存放工程开发相关文件的文件夹
src:代码空间(Source Space)
build:编译空间(Build Space)
devel:开发空间(Development Space)
install:安装空间(Instal Space)
编译不会产生install,必须使用命令:
catkin_make install
8.2 创建工作空间
2.1、创建工作空间:
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_init_workspace # 有这就一句说明当前路径是ros的编译空间啦
2.2、编译工作空间
cd ~/catkin_ws/
catkin_make
这样是没有install文件夹的,如果想要产生install文件夹,就是命令:
catkin_make install
- src:放后面功能包的源码
- install:安装空间,最后编译生成的可执行文件放进来
- devel:开发空间,放开发过程中的可执行文件,包括一些库,devle和intall功能是类似的,intsall是开发后分享给别人使用的文件
- build:编译过程中的中间文件,一般是用不到的
2.3、设置环境变量
source devel/setup.bash
可进入.bashrc文件设置
2.4、检查环境变量
echo $ROS_PACKAGE_PATH
8.3 创建功能包
- 放置源码的最小单元
3.1、创建功能包代码:
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
后面跟了好多依赖,也就是编译时需要依赖哪些功能包库
3.2、实操创建功能包
cd ~/catkin_make/src
catkin_create_pkg test_pkg std_msgs rospy roscpp
3.3、编译功能包
cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash
同一工作下,不允许存在同名功能包
不同工作空间下,允许
九、发布者Publisher的编程实现
1、创建功能包learning_topic:
cd ~/roslianxi/catkin_ws/src/
catkin_create_pkg learning_topic rospy roscpp std_msgs geometry_msgs turtlesim
2、创建velocity_publisher.cpp文件:
cd ~/roslianxi/catkin_wa/src/learning_topic/src/
touch velocity_publisher.cpp
然后代码为:
/**
* 该历程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
*/
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"velocity_publisher");
//创建节点句柄
ros::NodeHandle n;
//创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twists,队列长度为10
ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
//设置循环的频率
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
//初始化geometry_msgs::Twists类型的消息
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5;
vel_msg.angular.z = 0.2;
//发布消息
turtle_vel_pub.publish(vel_msg);
ROS_INFO("Publish turtle velocity command[%0.2f m/s, %0.2f rad/s]",vel_msg.linear.x, vel_msg.angular.z);
//按照循环频率延时
loop_rate.sleep();
}
return 0;
}
3、创建发布者步骤-如何实现一个发布者
3.1、初始化ROS节点
3.2、向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
3.3、创建消息数据;
3.4、按照一定频率循环发布消息
4、配置发布者代码编译规则
4.1、如何配置CMakeList.txt中的编译规则
4.1.1、设置需要编译的代码和生成的可执行文件
4.1.2、设置链接库
在learning_topic下的CMakeList.txt下添加:
add_executable(velocity_publisher src/velocity_publisher.cpp)
#描述把哪一个文件编译成哪一个可执行文件的,后面的编译成前面的
target_link_libraries(velocity_publisher ${catkin_LIBRARIES})
#用来帮助把可执行文件和ros相关的库链接的
5、编译并运行发布者
cd ~/catkin_ws
catkin_make
source devel/setup.bash
-
这里如果不想每次都要设置环境变量,可以把source这句话房间根目录的.bashrc文件里面
-
可以通过在主文件夹下ctrl+h显示隐藏文件,手动添加
-
也可以使用命令
vim ~/.bashrc
打开./bashrc文件
roscore
新开终端
rosrun turtlesim turtlesim_node
新开终端
rosrun learning_topic velocity_publisher
6 python的实现
- 一般把python文件放在scripts文件夹里面,这是为了区分开c++文件,这里创建了名为velocity_publisher.py的文件,内容为:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将发布turtle1/cmd_vel话题,消息类型geometry_msgs::Twist
import rospy
from geometry_msgs.msg import Twist
def velocity_publisher():
# ROS节点初始化
rospy.init_node('velocity_publisher', anonymous=True)
# 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度10
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
#设置循环的频率
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# 初始化geometry_msgs::Twist类型的消息
vel_msg = Twist()
vel_msg.linear.x = 0.5
vel_msg.angular.z = 0.2
# 发布消息
turtle_vel_pub.publish(vel_msg)
rospy.loginfo("Publsh turtle velocity command[%0.2f m/s, %0.2f rad/s]",
vel_msg.linear.x, vel_msg.angular.z)
# 按照循环频率延时
rate.sleep()
if __name__ == '__main__':
try:
velocity_publisher()
except rospy.ROSInterruptException:
pass
- py文件一定要有可执行权限,右键文件,属性的权限里面,要确定允许作为程序执行文件,点成对勾才可以
- py执行直接执行即可
十、订阅者Subscriber的编程实现
1、创建订阅者代码
1.1、如何实现一个订阅者
a、初始化ROS节点;
b、订阅需要的话题;
c、循环等待话题消息,接收到消息后进入回调函数;
d、在回调函数中完成消息处理。
1.2、代码如下:
/**
* 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
*/
#include <ros/ros.h>
#include "turtlesim/Pose.h"
//#include "std_msgs/String.h"
// 接收到订阅的消息后,会进入消息回调函数
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
// 将接收到的消息打印出来
ROS_INFO("Turtle pose: x:%0.6f, y:%0.6f", msg->x, msg->y);
}
int main(int argc, char **argv)
{
//初始化ROS节点
ros::init(argc,argv,"pose_subscriber");
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
ros::Subscriber pose_sub = n.subscribe("turtle1/pose", 10, poseCallback);
//循环等待回调函数
ros::spin();
return 0;
}
这里出现了一个问题,搞了半天,发现是我把main写成了mian,。。。。。
1.3、编译执行
在CMakeList.txt文件下
add_executable(pose_subscriber src/pose_subscriber.cpp)
target_link_libraries(pose_subscriber ${catkin_LIBRARIES})
然后编译执行:
cd ~/roslianxi/catkin_ws
catkin_make
source devel/setup.bash
roscore
新终端
rosrun turtlesim turtlesim_node
新终端
rosrun learning_topic velocity_publisher
2 python实现的效果
- 在scripts文件夹中创建py文件pose_subsccriber.py文件,内容为:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程将订阅/turtle1/pose话题,消息类型turtlesim::Pose
import rospy
from turtlesim.msg import Pose
def poseCallback(msg):
rospy.loginfo("Turtle pose: x:%0.6f, y:%0.6f", msg.x, msg.y)
def pose_subscriber():
# ROS节点初始化
rospy.init_node('pose_subscriber', anonymous=True)
# 创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
# 循环等待回调函数
rospy.spin()
if __name__ == '__main__':
pose_subscriber()
- 同样右键确认下可执行权限是对号
十一、话题消息的定义与使用
1、如何自定义话题消息(例)
1.1、定义Preson.msg文件(记得首字母大写);
在对应功能包下创建msg文件夹,必须放在该路径下,然后创建Preson.msg文件
string name
uint8 sex
uint8 age
uint8 unknown = 0
uint8 male =1
uint8 female = 2
1.2、在package.xml中添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
1.3、在CMakeLists.txt添加编译选项
find_package(...... message_generation)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)
catkin_package( CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs turtlesim message_runtime)
# 这些原文是注释掉了,我们可以选择修改注释或者直接加上
1.4、编译生成语言相关文件
cd ~/catkin_ws
catkin_make
然后就可以看到在catkin_ws/devel/include/learning_topic/learning_topic
下有一个Preson.h
可以使用命令
bupo@bupo-vpc:~$ rosmsg show Preson
[learning_communication/Preson]:
uint8 unknown=0
uint8 male=1
uint8 female=2
string name
uint8 sex
uint8 age
1.5、进行实战
这里提供了两个cpp文件,分别是person_publisher.cpp和person_subscriber.cpp,路径在learning_topic/src下,
person_publisher.cpp代码为:
/**
* 该例程将发布/person_info话题,自定义消息类型learning_topic::Person
*/
#include <ros/ros.h>
#include "learning_topic/Person.h"
int main(int argc, char **argv)
{
// ROS节点初始化
ros::init(argc, argv, "person_publisher");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Publisher,发布名为/person_info的topic,消息类型为learning_topic::Person,队列长度10
ros::Publisher person_info_pub = n.advertise<learning_topic::Person>("/person_info", 10);
// 设置循环的频率
ros::Rate loop_rate(1);
int count = 0;
while (ros::ok())
{
// 初始化learning_topic::Person类型的消息
learning_topic::Person person_msg;
person_msg.name = "Tom";
person_msg.age = 18;
person_msg.sex = learning_topic::Person::male;
// 发布消息
person_info_pub.publish(person_msg);
ROS_INFO("Publish Person Info: name:%s age:%d sex:%d",
person_msg.name.c_str(), person_msg.age, person_msg.sex);
// 按照循环频率延时
loop_rate.sleep();
}
return 0;
}
person_subscriber.cpp代码为:
/**
* 该例程将订阅/person_info话题,自定义消息类型learning_topic::Person
*/
#include <ros/ros.h>
#include "learning_topic/Person.h"
// 接收到订阅的消息后,会进入消息回调函数
void personInfoCallback(const learning_topic::Person::ConstPtr& msg)
{
// 将接收到的消息打印出来
ROS_INFO("Subcribe Person Info: name:%s age:%d sex:%d",
msg->name.c_str(), msg->age, msg->sex);
}
int main(int argc, char **argv)
{
// 初始化ROS节点
ros::init(argc, argv, "person_subscriber");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个Subscriber,订阅名为/person_info的topic,注册回调函数personInfoCallback
ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
// 循环等待回调函数
ros::spin();
return 0;
}
同样在这里不要忘记了在CMakeLists.txt里加上:
add_executable(person_publisher src/person_publisher.cpp)
target_link_libraries(person_publisher ${catkin_LIBRARIES})
add_dependencies(person_publisher ${PROJECT_NAME}_generate_messages_cpp)
add_executable(person_subscriber src/person_subscriber.cpp)
target_link_libraries(person_subscriber ${catkin_LIBRARIES})
add_dependencies(person_subscriber ${PROJECT_NAME}_generate_messages_cpp)
在这里多了一个add_dependencies,有一些代码是动态生成的,可执行文件与动态生成的头文件做链接
然后进行编译执行:
cd ~/catkin_ws/
catkin_make
source devel/setup.bash
roscore
新开终端
rosrun learning_topic person_publisher
新开终端
rosrun learning_topic person_subscriber
在节点运行的时候,即使关闭了master节点,节点仍然会运行,因为rosmaster是帮助topic之间建立连接的,连接之后,就可以不需要rosmaster了