ROS内置的turtlesim案例
区别
/turtle1/cmd_vel:控制小乌龟运动的节点
发布:rostopic info /turtle1/cmd_vel(turtle1/cmd_vel是话题)
Type: geometry_msgs/Twist
Publishers: /teleop_turtle (http://rosnoetic-VirtualBox:33275/)
Subscribers: /turtlesim (http://rosnoetic-VirtualBox:40025/)
订阅:rostopic info /turtle1/pose
Type: turtlesim/Pose
Publishers: /turtle1 (http://rosnoetic-VirtualBox:46159/)
Subscribers: None
话题发布
1. 获取话题 /turtle1/cmd_vel
方式1:rqt_graph —— 启动计算图获取话题
左右两端是节点信息
方式2:rostopic list
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
2. 获取消息类型
rostopic info /turtle1/cmd_vel(turtle/cmd_vel是话题)
Type: geometry_msgs/Twist
Publishers: /teleop_turtle (http://rosnoetic-VirtualBox:33275/)
Subscribers: /turtlesim (http://rosnoetic-VirtualBox:40025/)
或者rostopic type /turtle1/cmd_vel
geometry_msgs/Twist
3. 获取消息格式
- rosmsg show geometry_msgs/Twist(类似于plumbing_pub_sub/Person)得到内部参数
- rosmsg info geometry_msgs/Twist
geometry_msgs/Vector3 linear(线速度)
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular(角速度)
float64 x
float64 y
float64 z
- linear(线速度) 下的xyz分别对应在x、y和z方向上的速度(单位是 m/s),数据类型是浮点double
- angular(角速度)下的xyz分别对应x轴上的翻滚、y轴上俯仰和z轴上偏航的速度(单位是rad/s)
弧度: 单位弧度定义为圆弧长度等于半径时的圆心角。即图中的radian
周长为2pir,转1个半径是1弧度,转1圈是相当于6.28个半径,就是6.28个弧度,1秒转1圈是6.28rad/s。
以10Hz的方式进行订阅:rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist
4. 控制乌龟运动
4.1 C++实现:test01_pub_twist
运行
步骤:
- roscore
- rosrun turtlesim turtlesim_node
- cd demo02_ws
- source ./devel/setup.bash
- rosrun plumbing_test test01_pub_twist
#include"ros/ros.h"
#include"geometry_msgs/Twist.h"
/*
需求:发布话题消息
话题: /turtle1/cmd_vel
消息: geometry_msgs/Twist
1.包含头文件
2.初始化ROS节点
3.创建节点句柄
4.创建发布对象
5.发布逻辑实现
6.spinOnce() 循环发布
*/
int main(int argc, char *argv[])
{
// 解决乱码问题
setlocale(LC_ALL,"");
// 2.初始化节点
ros::init(argc,argv,"my_control");
// 3.创建节点句柄
ros::NodeHandle nh;
// 4.创建发布对象
ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);// 话题名称/tur...
// 5.发布逻辑实现 10Hz 1秒10次
// 5.1 设置发布频率
ros::Rate rate(10);
// 5.2 组织被发布的消息
geometry_msgs::Twist twist;
twist.linear.x = 1.0;//数据类型是浮点double
twist.linear.y = 0.0;
twist.linear.z = 0.0;
twist.angular.z = 1.0;//只有偏航角
twist.angular.x = 0.0;
twist.angular.y = 0.0;
// 5.3 循环发布
while(ros::ok())
{
pub.publish(twist);
// 休眠
rate.sleep();
// 6.spinOnce() 循环发布
ros::spinOnce();
}
return 0;
}
4.2 Python实现: test01_pub_twist_p.py
运行
步骤
- 添加可执行权限
chmod +x *.py
ll - 编译——catkin部分修改
- 执行
roscore
rosrun turtlesim turtlesim_node
rosrun plumbing_test test01_pub_twist_p.py
#! /usr/bin/eny python
"""
发布方:发布速度消息
话题: /turtle1/cmd_vel
消息: geometry_msgs/Twist
1. 导包
2. 初始化ROS节点
3. 创建发布者对象
4. 组织数据,发布数据
"""
import rospy
from geometry_msgs.msg import Twist
if __name__ == "__main__":
# 2. 初始化ROS节点
rospy.init_node("my_control_p")
# 3. 创建发布者对象
pub = rospy.Publisher("/turtle/cmd_vel",Twist,queue_size = 10)
# 4. 组织数据,发布数据
# 4.1 设置发布频率
rate = rospy.Rate(10)
# 4.2 创建速度消息
twist = Twist()
twist.linear.x = 0.5
twist.linear.y = 0.0
twist.linear.z = 0.0
twist.angular.x = 0.0
twist.angular.y = 0.0
twist.angular.z = 1.0
# 4.3 循环发布
while not rospy.is_shutdown():
pub.publish(twist)
rate.sleep()
话题订阅
1. 获取话题 /turtle1/pose
rostopic list
/rosout
/rosout_agg
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
2. 获取消息类型
rostopic info /turtle1/pose
Type: turtlesim/Pose
Publishers: /turtle1 (http://rosnoetic-VirtualBox:46159/)
Subscribers: None
3. 获取消息格式
rosmsg info turtlesim/Pose
float32 x(坐标)
float32 y
float32 theta(朝向)
float32 linear_velocity(线速度)
float32 angular_velocity(角速度)
rostopic echo /turtle1/pose:打印信息
4. 代码实现
4.1 C++实现:test02_sub_pose
运行
- 窗口1:vscode终端
source ./devel/setup.bash
roslaunch plumbing_test start_turtle.launch - 窗口2:ctrl+alt+t
cd demo02_ws
source ./devel/setup.bash
rosrun plumbing_test test02_sub_pose
就可以根据键盘控制乌龟运动的同时,实时打印出乌龟的运动信息。
#include"ros/ros.h"
#include"turtlesim/Pose.h"
/*
需求:订阅乌龟的位姿信息
1. 包含头文件
2. 初始化ROS节点
3. 创建节点句柄
4. 创建订阅对象
5. 处理订阅到的数据(回调函数)
6. spin()回头
*/
void doPose(const turtlesim::Pose::ConstPtr &pose)
{
ROS_INFO("乌龟位姿信息:坐标(%.2f,%.2f),朝向(%.2f),线速度:%.2f,角速度:%.2f",
pose->x,pose->y,pose->theta,pose->linear_velocity,pose->angular_velocity);
}
int main(int argc, char *argv[])
{
// 中文乱码
setlocale(LC_ALL,"");
// 2. 初始化ROS节点
ros::init(argc,argv,"sub_pose");
// 3. 创建节点句柄
ros::NodeHandle nh;
// 4. 创建订阅对象
ros::Subscriber sub = nh.subscribe("/turtle1/pose",100,doPose); //doPose是回调函数
// 5. 处理订阅到的数据(回调函数)
// 6. spin()回头
ros::spin();
return 0;
}
4.2 Python实现:test02_sub_pose_p.py
运行
- 添加可执行权限
chmod +x *.py
ll - 编译——catkin部分修改
- 执行
窗口1:vscode终端
source ./devel/setup.bash
roslaunch plumbing_test start_turtle.launch
窗口2:ctrl+alt+t
cd demo02_ws
source ./devel/setup.bash
rosrun plumbing_test test02_sub_pose_p.py
#! /usr/bin/env python
"""
需求:订阅并输出乌龟的位资信息
1. 导包
2. 初始化ROS节点
3. 创建订阅对象
4. 使用回调函数处理订阅到的信息
5. spin()
"""
import rospy
from turtlesim.msg import Pose
def doPose(pose):
rospy.loginfo("p->乌龟位姿信息:坐标(%.2f,%.2f),朝向(%.2f),线速度:%.2f,角速度:%.2f",
pose.x,pose.y,pose.theta,pose.linear_velocity,pose.angular_velocity)
if __name__ == "__main__":
# 2. 初始化ROS节点
rospy.init_node("sub_pose_p")
# 3. 创建订阅对象
sub = rospy.Subscriber("/turtle1/pose",Pose,doPose,queue_size=100)# 消息类型是Pose
# 4. 使用回调函数处理订阅到的信息
# 5. spin()
rospy.spin()
服务调用
1. 获取话题/spawn(产卵)
rosservice list
/clear
/key/get_loggers
/key/set_logger_level
/kill
/reset
/rosout/get_loggers
/rosout/set_logger_level
/spawn
/turtle1/get_loggers
/turtle1/set_logger_level
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
2. 获取消息类型
rosservice info /spawn:获取turtlesim/Spawn
Node: /turtle1
URI: rosrpc://rosnoetic-VirtualBox:60831
Type: turtlesim/Spawn
Args: x y theta name
3.获取消息格式
rossrv info turtlesim/Spawn
float32 x (上半部分是请求)
float32 y
float32 theta
string name
string name(下半部分是响应)
theta是弧度制,范围是3.14rad——(-3.14)rad,逆时针为正,顺时针为负
4. 代码实现
4.1 C++实现 test03_server_client.cpp
- 窗口1:vscode终端
source ./devel/setup.bash
roslaunch plumbing_test start_turtle.launch - 窗口2:ctrl+alt+t
cd demo02_ws
source ./devel/setup.bash
rosrun plumbing_test test03_service_client
运行
#include"ros/ros.h"
#include"turtlesim/Spawn.h"
/*
需求:向服务器发送请求,生成一个新的乌龟
话题:/spawn
消息:turtlesim/Spawn
1.包含头文件
2.初始化ROS节点
3.创建节点句柄
4.创建客户端对象
5.组织数据并发送
6.处理响应
*/
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
// 2.初始化ROS节点
ros::init(argc,argv,"service_call");
// 3.创建节点句柄
ros::NodeHandle nh;
// 4.创建客户端对象
ros::ServiceClient client = nh.serviceClient<turtlesim::Spawn>("/spawn"); // /spawn是话题名称
// 5.组织数据并发送
// 5.1 组织请求数据
turtlesim::Spawn spawn;
spawn.request.x = 1.0;
spawn.request.y = 4.0;
spawn.request.theta = 4.0;
spawn.request.name = "turtle2";
// 5.2 发送请求
//判断服务器状态
// ros::service::waitForService("/spawn");
client.waitForExistence();
bool flag = client.call(spawn);//flag 接受响应状态,响应结果也会被设置进spawn对象
// 6.处理响应
if(flag) // 响应成功
{
ROS_INFO("乌龟生成成功,新乌龟叫:%s",spawn.response.name.c_str());
}
else
{
ROS_INFO("请求失败!!!");
}
return 0;
}
4.2 Python实现 test03_server_client_p.py
运行
- 添加可执行权限
chmod +x *.py
ll - 编译——catkin部分修改
- 执行
窗口1:vscode终端
source ./devel/setup.bash
roslaunch plumbing_test start_turtle.launch
窗口2:ctrl+alt+t
cd demo02_ws
source ./devel/setup.bash
rosrun plumbing_test test03_service_client_p.py
#! /usr/bin/env python
"""
需求:向服务器发送请求生成一个乌龟
话题:/spawn
消息类型:turtlesim/Spawn
1. 导包
2. 初始化ROS节点
3. 创建服务的客户端对象
4. 组织数据并发送请求
5. 处理响应结果
"""
import rospy
from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse
if __name__ == "__main__":
# 2. 初始化ROS节点
rospy.init_node("service_call")
# 3. 创建服务的客户端对象
client = rospy.ServiceProxy("/spawn",Spawn) # /spawn是话题名称
# 4. 组织数据并发送请求
# 4.1 组织数据
request = SpawnRequest()
request.x = 4.5
request.y = 2.0
request.theta = -3 # 向右转3个rad
request.name = "turtle3"
# 4.2 判断服务器状态并发送
client.wait_for_service() # 服务端开启则执行,否则挂起
# 防止抛出异常
try:
response = client.call(request)
# 5. 处理响应结果
rospy.loginfo("生成乌龟的名字叫:%s",response.name)
except Exception as e:
rospy.logerr("请求处理异常")
参数设置
1. 获取参数名
获取参数列表rosparam list
/rosdistro
/roslaunch/uris/host_rosnoetic_virtualbox__43129
/rosversion
/run_id
/turtlesim/background_b
/turtlesim/background_g
/turtlesim/background_r
获取参数值rosparam get /turtlesim/background_r
2. 代码实现
2.1 C++实现 test04_param
运行
rescore
cd demo02_ws
source ./devel/setup.bash
rosrun plumbing_test test04_param
rosrun turtlesim turtlesim_node(最后启动)
#include"ros/ros.h"
/*
需求:修改参数服务器中turtlesim背景色相关参数
1.初始化ROS节点
2.不一定需要创建节点句柄(和后续API有关)
3.修改参数
*/
int main(int argc, char *argv[])
{
// 1.初始化ROS节点
ros::init(argc,argv,"change_bgcolor");
// 2.不一定需要创建节点句柄(和后续API有关)
// ros::NodeHandle nh("turtlesim");//设置命名空间
// nh.setParam("background_r",255);
// nh.setParam("background_g",255);
// nh.setParam("background_b",255);
ros::NodeHandle nh;
nh.setParam("/turtlesim/background_r",0);
nh.setParam("/turtlesim/background_g",50);
nh.setParam("/turtlesim/background_b",100);
// 3.修改参数
// 方式1:如果调用ros::param 不需要创建节点句柄
// ros::param::set("/turtlesim/background_r",0);
// ros::param::set("/turtlesim/background_g",0);
// ros::param::set("/turtlesim/background_b",0);
// 方式2:使用nodehandle
return 0;
}
2.2 Python实现 test04_param_p.py
运行
- 添加可执行权限
chmod +x *.py
ll - 编译——catkin部分修改
- 执行
rescore
cd demo02_ws
source ./devel/setup.bash
rosrun plumbing_test test04_param_p.py
rosrun turtlesim turtlesim_node(最后启动)
#! /usr/bin/env python
"""
需求:修改乌龟GUI的背景色
1.初始化ros节点
2.设置参数
"""
import rospy
if __name__ == "__main__":
rospy.init_node("change_bgcolor")
# 修改背景色
rospy.set_param("/turtlesim/background_r",100)
rospy.set_param("/turtlesim/background_g",50)
rospy.set_param("/turtlesim/background_b",200)