基于古月居的ros入门
前言
由于前段时间的学习总结的习惯不好,决定新开一栏用于ros基础学习。有一说一,通过和学长的进度比较,总感觉自己是个废物。
虚拟机的安装
不要装机械盘,运行慢。使用VMware
ubantu系统18
linux基本命令行
1 2 3 4 5 6 7 8 9 10 11 12
| cd ls mv rm -r cp pwd mkdir touch
shutdown -h now reboot sudo
|
基本命令行
1 2
| sudo apt-get update source ~/catkin_ws/devel/setup.bash
|
前置安装
1 2 3 4 5 6 7 8 9
| sudo apt-get install g++
sudo apt-get install python
sudo apt install vim
wget http:
|
ros的核心概念
节点(node)与节点管理器(ros master)
节点名称唯一
话题(topic)与服务(serve)
话题:单向
- 发布者
- 订阅者
- 消息(massage):话题的数据由.msg文件定义
服务:双向
参数(parameter)—全局共享字典
适合静态,非二进制的配置参数
文件系统
- 功能包(package) :含节点源码,配置文件,数据定义
- 功能包清单: 作者信息,许可信息,依赖选项
- 元功能包:组织多个同一目的的功能包
ros命令行工具
1 2 3 4 5 6
| rostopic rosservice rosnode rosparam rosmsg rossrv
|
小海龟
1 2 3 4 5 6
| roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key
|
工具
1 2 3 4 5 6 7 8 9
| rqt_graph rosnode rostopic rosmsg
rosservice
rosbag record -a -O cmd_record rosbag play cmd_record.bag
|
ros的文件结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| WorkSpace --- 自定义的工作空间
|--- build:编译空间,用于存放CMake和catkin的缓存信息、配置信息和其他中间文件。
|--- devel:开发空间,用于存放编译后生成的目标文件,包括头文件、动态&静态链接库、可执行文件等。
|--- src: 源码
|-- package:功能包(ROS基本单元)包含多个节点、库与配置文件,包名所有字母小写,只能由字母、数字与下划线组成
|-- CMakeLists.txt 配置编译规则,比如源文件、依赖项、目标文件
|-- package.xml 包信息,比如:包名、版本、作者、依赖项...(以前版本是 manifest.xml)
|-- scripts 存储python文件
|-- src 存储C++源文件
|-- include 头文件
|-- msg 消息通信格式文件
|-- srv 服务通信格式文件
|-- action 动作格式文件
|-- launch 可一次性运行多个节点
|-- config 配置信息
|-- CMakeLists.txt: 编译的基本配置
|
创建工作空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace
cd catkin_ws/ catkin_make
catkin_make install
source devel/setup.bash
echo $ROS_PACKAGE_PATH
|
功能包创建与编译
1 2 3 4 5 6 7 8 9 10
| cd ~/catkin_ws/src catkin_create_pkg my_package_name rospy roscpp std_msgs
cd catkin_ws/ catkin_make
source ~/catkin_ws/devel/setup.bash
|
问题:我需要在原有的ROS工程基础之上,新建一个ROS功能包。我直接复制了其他目录下原有的一个包,进行修改。然后问题来了:catkin_make后竟然没有反应。甚至没有检测到我新改写的cmake
解决:ros允许多个工作空间使用相同功能包,但多个工作空间source不要放在脚本里,手动敲,否则会被覆盖,在catkin_make之前source一下,之后再source一下。而且要多次执行,如下。注意要先开下roscore,py文件要给其可执行权限.
1 2 3 4 5 6
| //将文件复制过来后,在工作空间目录下打开终端 source ~/ws_space/devel/setup.bash catkin_make source ~/ws_space/devel/setup.bash catkin_make source ~/ws_space/devel/setup.bash
|
脚本文件的source只在新的终端开启时才运行
发布者与订阅者
以海龟为例
python文件要记得给可执行权限
发布者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
import rospy from geometry_msgs.msg import Twist
def velocity_publisher(): rospy.init_node('velocity_publisher', anonymous=True)
turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=10)
rate = rospy.Rate(10)
while not rospy.is_shutdown(): 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
|
订阅者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
|
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(): rospy.init_node('pose_subscriber', anonymous=True)
rospy.Subscriber("/turtle1/pose", Pose, poseCallback)
rospy.spin()
if __name__ == '__main__': pose_subscriber()
|
消息的自定义
定义msg文件
在功能包的src同级目录下创建msg文件夹
1 2 3 4 5 6 7 8 9 10
| // 举例,该文件名为Person.msg string name uint8 age uint8 sex
uint8 unknown = 0 uint8 male = 1 uint8 female = 2
|
launch文件
使用 launch 文件,可以一次性启动多个 ROS 节点
launch文件自动启动ROS Master
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
<launch> <node pkg="helloworld" type="demo_hello" name="hello" output="screen" /> <node pkg="turtlesim" type="turtlesim_node" name="t1"/> <node pkg="turtlesim" type="turtle_teleop_key" name="key1" />
<param name="output_feame" value="odom"/> <rosparam= file="params.yaml" command="load" ns="params"/>
<remap from="/turtlebot/cmd_vel"to="/cmd_vel"/>
<include file="$(dirname)/other.launch"/> </launch>
|
客户端与服务端
客户端
rosservice call /clear “{}”
参数的使用
parameter Server 全局变量存储空间
1 2 3 4 5 6 7 8 9 10 11 12
| // 列出当前有多个参数 rosparam list // 显示某个参数值 rosparam get param_key // 设置某个参数值 rosparam set param_key param_value //保存参数到文件 rosparam dump file_name // 从文件读取参数 rosparam load file_anme // 删除参数 rosparam delete param_key
|
yaml 参数文件
在程序里实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
import sys import rospy from std_srvs.srv import Empty
def parameter_config(): rospy.init_node('parameter_config', anonymous=True)
red = rospy.get_param('/background_r') green = rospy.get_param('/background_g') blue = rospy.get_param('/background_b')
rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)
rospy.set_param("/background_r", 255); rospy.set_param("/background_g", 255); rospy.set_param("/background_b", 255);
rospy.loginfo("Set Backgroud Color[255, 255, 255]");
red = rospy.get_param('/background_r') green = rospy.get_param('/background_g') blue = rospy.get_param('/background_b')
rospy.loginfo("Get Backgroud Color[%d, %d, %d]", red, green, blue)
rospy.wait_for_service('/clear') try: clear_background = rospy.ServiceProxy('/clear', Empty)
response = clear_background() return response except rospy.ServiceException, e: print "Service call failed: %s"%e
if __name__ == "__main__": parameter_config()
|
TF坐标管理系统
tf功能包,默认10秒
实现机制
- 广播TF变换
- 监听TF变换
1 2 3 4 5 6 7 8
| sudo apt-get install ros-melodic-turtle-tf
roslaunch turtle tfturtle tf demo.launch
rosrun turtlesim turtle teleop_key
rosrun tf view frames
|
tf工具
- 命令行工具
rosrun tf tf_echo turtle1 turtle2
- 可视化工具
rosrun rviz rviz -d rospack find turtle tf /rviz/turtle rviz.rviz
tf坐标的广播与监听
单词释义
quaternion 四元数
radian 弧度
degree 角度
常用可视化工具
QT工具箱
- 日志输出rqt_console
- 计算图ret_graph
- 数据绘图rqt_plot
- 图像渲染rqt_image_view
rviz
gazebo
进阶
- 控制与仿真 gazebo + ros +ros_control