1.查找相应的元功能包,下面是示例
- 浏览器搜索ros navigation
找到这种网页navigation - ROS Wiki - Robot Operating Systemhttp://wiki.ros.org/navigation
- 进入后找github的链接
- 再点进去,都是一些元功能包
- 随便一个点进去,和4-1讲的一样,只有配置文件,是一个虚包
注意:lauch文件更改后不需要编译,直接用即可
2.launch文件的属性
<node pkg="功能包名" type="包含节点的可执行源文件名" name="给节点另起的一个名字,防止节点重名,随便起" ,output="默认是log,只有是screen时想要输出的日志才会打印在屏幕上" />
eg: <node pkg="turtlesim" type="turtlesim_node" name="turtle_pose" output="screen" />
args="xxx xxx xxx" (可选) 将参数传递给节点
像命令行传参,rosrun 功能包 可执行文件 参数1 参数2
动态传参时,args可以传入启动过的节点但name=turtle1的乌龟运动获取动态位姿
<node pkg="tf_turtle" type="pose_turtle_pub" name="pose_turtle1" args="turtle1" />
<node pkg="tf_turtle" type="pose_turtle_pub" name="pose_turtle2" args="turtle2" />
respawn="true | false" (可选) 如果节点退出,是否自动重启
- 在机器人上,以无人车为例,雷达退出了紧接着要启动;这个比较实用
- 像乌龟画面出来的那个节点,手动关闭之后,若有这个命令,还会自动出来
respawn_delay=" N" (可选) 如果 respawn 为 true, 那么延迟 N 秒后启动节点
<!-- 作用:设置节点的命名空间,避免重名问题 --!>
ns="xxx" (可选) 在指定命名空间 xxx 中启动节点
interest@interest:~/tongxin2$ rosnode list
/hello/turtle_pose //会把launch文件中ns="hello"加在name="turtle_pose",这个节点名前
/key
/rosout
其它,没有重点说明演示的
machine="机器名" 在指定机器上启动节点(不同设备)
required="true | false" (可选)
该节点是否必须,如果为 true,那么如果该节点退出,将杀死整个 roslaunch
clear_params="true | false" (可选) 在启动前,删除节点的私有空间的所有参数;慎用
3.lauch文件的子级标签
(一)remap
turtle乌龟内置的键盘控制节点不太好用,自己做机器人想用键盘控制noetic有对应包,命令行安装
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
会报错,就先下载
sudo apt-get install ros-noetic-teleop-twist-keyboard
再运行键盘控制节点,
然而乌龟运动节点和键盘控制节点使用的话题不一样,订阅不到就要使用remap
remap实现不同节点之间的话题通信
<node pkg="turtlesim" type="turtlesim_node" name="turtle_pose" output="screen" >
<remap from="使用的原话题" to="要修改成的话题" />
<remap from="/turtle1/cmd_vel" to="/cmd_vel" />
</node >
注意:node标签中在哪加/的问题,表示语句的结束;不合适会报错,下面链接是示例http://t.csdn.cn/DOQH1
launch文件报这种错误说明没有刷新环境变量source./devel/setup.bash即可
interest@interest:~/tongxin2$ roslaunch turtle_test start_turtle.launch
RLException: [start_turtle.launch] is neither a launch file in package [turtle_test] nor is [turtle_test] a launch file name
The traceback for the exception was written to the log file
内置的键盘控制
(二)rosparam
使用rosparam时yaml文件报错:参数设置:后要加空格
解决问题的链接:http://t.csdn.cn/01kDm
节点查看 | rosnode list |
向参数服务器设置参数的查看 | rosparam list |
/bg_B /turtle_pose/bg_B //私有命名空间,就 是节点中的name | |
参数设置值查看 | |
//不带前缀的 roaparam get bg_B //带前缀的rosparam get /turtle_pose/bg_B |
arg标签命令行动态传参
roslaunch launch1_basic arg.launch car_length:=0.6
4.在任意目录下使用工作空间(避免功能包重名问题)
- Ctrl+H,打开主目录下的隐藏文件
- 在.bashrc文件中刷新环境变量,最后一行添加,
- devel目录下有一个setup.bash文件,在终端中打开,pwd复制路径
- source /-----pwd复制路径-------------/devel/setup.bash
- 保存
- 就可以在任意目录下使用刚配置过的工作空间了
- 配置好后终端source .bashrc刷新环境变量且不用在工作空间下
- source ./devel/setup.bash 需要在工作空间下
#刷新环境变量配置
source /opt/ros/noetic/setup.bash
source /home/rosdemo/demo01_ws/devel/setup.bash
#后刷新的环境变量优先级高
source /home/rosdemo/demo02_ws/devel/setup.bash
------------------------------------------------
#查看工作空间覆盖情况,三个工作空间下都有一个命名同样的功能包;容易有安全隐患4.3
$ echo $ROS_PACKAGE_PATH
/home/rosdemo/demo02_ws/src:/home/rosdemo/demo01_ws/src:/opt/ros/noetic/share
5.除了源文件.cpp/.py其他类型的文件都不用编译,但新建的功能包要编译一次
6.话题重名,案例显示,remap
先运行,控制乌龟运动节点的launch文件
再运行rosrun teleop_twist_keyboard teleop_twist_keyboard.py
- 命令行设置命名空间
rosrun turtlesim turtlesim_node __ns:=/xxx
- 使用命令行修改话题:
rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel
- 使用命令行设置参数:
rosrun turtlesim turtlesim_node _=radius:=3.54 (默认私有方式设置参数名)
- 编码设置参数,在命令行执行时,最后还要加上自己命名的命名空间
rosrun turtlesim turtlesim_node __ns:=/xxx
常用名词 | 解释 |
欧拉角 | 俯仰(沿y)、翻滚(沿x)、偏航(沿z) |
四元数 | 可以看作欧拉角的另一种表现形式,坐标变换的常用消息 |
欧拉角(x=0,y=0,z=0)转换四元数(x=0,y=0,z=0,w=1) | |
ros消息 | 通信机制中的数据传递自定义消息msg |
rviz坐标系查看 | 红轴x,绿轴y,蓝轴z; 窗体方格:横向是x轴,纵向是y轴;一小格是1m |
TF坐标变换 | |
tf2_geometry_msgs:可以将ROS消息转换成tf2消息。 tf2: 封装了坐标变换的常用消息。 tf2_ros:为tf2提供了roscpp和rospy绑定,封装了坐标变换常用的API。(为坐标变换发布订阅提供条件) 坐标与坐标之间的转换,要靠算法;但算法已经被封装进tf2,不用管 |
rostopic list | 找出TF话题 |
rostopic echo /tf_static | 打印话题的具体内容 |
5.TF坐标转换的错误http://t.csdn.cn/otgZ7
[ WARN] [1673581874.588791288]: Shutdown request received.
[ WARN] [1673581874.589361201]: Reason given for shutdown:
[[/static_brocast] Reason:
new node registered with same name]
是配置文件时没有改好文件名,节点名重名覆盖了
6. ROS 系统已经封装好了专门的节点实现静态坐标系相对信息发布
rosrun tf2_ros static_transform_publisher x偏移量 y偏移量 z偏移量
z偏航角度 y俯仰角度 x翻滚角度 父级坐标系 子级坐标系
示例:rosrun tf2_ros static_transform_publisher 0.2 0 0.5
0 0 0 /baselink /laser
//欧拉角的值---负值是逆时针,y是正值是顺时针
//偏移量是障碍物相对子坐标系的
//欧拉角也是子极坐标系相对父极坐标系的
//子坐标系的坐标值是相对参考坐标系(父级坐标系)的(世界坐标系)
7.查看内置乌龟运动消息
//启动乌龟节点
rosrun turtlesim turtlesim_node
//查看话题
rostopic list-----------------/turtle1/pose
//查看消息格式
rostopic info /turtle1/pose--------Type: turtlesim/Pose
Publishers:
Subscribers:
//查看消息类型里的具体格式
rosmsg info turtlesim/Pose------
float32 x
float32 y
float32 theta
float32 linear_velocity
float32 angular_velocity
//查看节点
rosnode list----------------/turtlesim
//查看节点信息
rosnode info /turtlesim-----------------
Node [/turtlesim]
Publications:
* /rosout [rosgraph_msgs/Log]
* /turtle1/color_sensor [turtlesim/Color]
* /turtle1/pose [turtlesim/Pose]
Subscriptions:
* /turtle1/cmd_vel [unknown type]
Services:
* /clear
* /kill
* /reset
* /spawn
* /turtle1/set_pen
* /turtle1/teleport_absolute
* /turtle1/teleport_relative
* /turtlesim/get_loggers
* /turtlesim/set_logger_level
contacting node http://interest:36227/ ...
Pid: 179354
Connections:
* topic: /rosout
* to: /rosout
* direction: outbound (54789 - 127.0.0.1:49680) [24]
* transport: TCPROS
8.vscode左边目录字体放大
- 9.tf坐标关系两只乌龟跟随实操
<!-- 启动乌龟节点与键盘控制节点 -->
<node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen" />
<node pkg="turtlesim" type="turtle_teleop_key" name="key_control" output="screen"/>
-----这是内置的乌龟启动节点----------他运动订阅的话题是/turtle1/cmd_vel
//所以只能控制第一只乌龟运动,必须被订阅相同的话题
interest@interest:~/tf5$ rostopic list
/rosout
/rosout_agg
/turtle1/cmd_vel //第1只乌龟运动订阅的话题
/turtle1/color_sensor
/turtle1/pose //第1只乌龟位姿获取订阅的话题
/turtle2/cmd_vel //第2只乌龟运动订阅的话题
/turtle2/color_sensor
/turtle2/pose //第1只乌龟位姿获取订阅的话题
-------想要第2只乌龟可以运动------第2只乌龟被服务端响应的话题是/spawn
interest@interest:~/tf5$ rostopic pub -r 10 /turtle2/cmd_vel
tab键自动补齐geometry_msgs/Twist "linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 1.0"
- 动态传参的方法实现获取两只乌龟位姿
添加代码1:
//声明变量接收传递的参数
std::string turtle_name;
添加代码2:
//关键点2:动态传入
//tfs.child_frame_id = "turtle1";
tfs.child_frame_id = turtle_name; //header.frame_id = "world"
添加代码3:
/* 解析 launch 文件通过 args 传入的参数 */
if (argc!=2)
{
ROS_ERROR("请传入一个参数");
return 1;
}else
{
turtle_name=argv[1];
}
//注意:要放在ros::init(argc,argv,"dynamic_tf_pub");下面!!!!!!!
否则rviz不会显示坐标系
添加代码4:
// 关键点1:订阅的话题名称 turtle1或turtle2 动态传入
//ros::Subscriber sub = nh.subscribe<turtlesim::Pose>("/turtle1/pose",1000,doPose);
ros::Subscriber sub = nh.subscribe<turtlesim::Pose>(turtle_name+"/pose",1000,doPose);
获取量坐标系相对关系并发布跟随者的速度
/*
主要是控制第2只乌龟运动,第1只乌龟运动靠键盘控制;2跟随1
需求1:换算出turtle1相对于turtle2的关系
需求2:计算角速度和线速度并发布
*/
//A.创建发布对象
ros::Publisher pub=nh.advertise<geometry_msgs::Twist>("turtle2/cmd_vel",100);
// 5.解析订阅信息中获取的 turtle1 坐标系原点与 turtle2 坐标系原点的相对关系
geometry_msgs::TransformStamped tfs = buffer.lookupTransform("turtle2","turtle1",ros::Time(0));
//B.根据相对计算并组织速度消息
geometry_msgs::Twist twist;
//组织速度,只需要设置线速度的x,和角速度的
twist.linear.x=0.5*sqrt(pow(tfs.transform.translation.x,2)
+(tfs.transform.translation.y,2));
twist.angular.z=4*atan2(tfs.transform.translation.y,tfs.transform.translation.x);
//C.发布
pub.publish(twist);
---------------------------------------------------------
注意:循环频率不能太小,不然跟随的小乌龟会转圈圈。
ros::Rate r(10); //1秒100次就可以
数学知识
- 已知:导弹(turtle2,跟随方)和车(turtle1,键盘控制方);导弹为了击中正在走的 车;TF坐标变换实操里一种好理解的比喻
- 疑问:为什么计算两坐标系相对关系时,计算的是 turtle1(子级,原坐标系) 坐标系原 点对turtle2 (父级,目标坐标系)坐 标系原点的相对关系,而不是 turtle2 坐标系 原点对turtle1坐标系原点的相对关系
- 猜想:车是先动的,导弹要跟着车运动而运动(有多个变量);所以无法把导弹当做参 考;应该是以车运动(只有这一个变量)做参考算相对关系导弹再进行调整
- 进一步:代码逻辑的问题,不能简单的改两个参数就可以了;所以坐标转换的时候要分 清子级和父级
1.turtlesim源码 - 搜索 (bing.com)https://cn.bing.com/search?q=turtlesim%E6%BA%90%E7%A0%81&FORM=QSRE2
2.turtlesim - ROS Wikihttp://wiki.ros.org/turtlesim
8.添加可执行权限报错,说明python文件名后缀.py写错