ROS基础 坐标管理系统与广播监听

机器人中的坐标变换

因为机器人各部位的坐标不同,在控制运行中考虑各部位坐标的计算会让程序变得繁琐复杂,所以ROS提供了TF功能包用于处理机器人各部位的坐标关系

TF功能包

  • 不同时间内,机器人部位坐标相对于全局坐标的关系
  • 机器人部位进行操作时相对机器人中心坐标系的的坐标关系
  • 机器人中心坐标系相对全局坐标系的关系

TF坐标变换的实现

  • 广播TF变换
  • 监听TF变换

有了TF功能包,得到传感器的位置信息,就可以处理机器人本体的位置信息,减少了繁琐的计算合操作

实现操作

$ sudo apt-get install ros-melodic-turtle-tf
$ roslaunch turtle_tf turtle_tf_demo.launch				#启动脚本,可启动多个节点
$ rosrun turtlesim turtle_teleop_key					#启动新终端
$ rosrun tf view_frames									#记录位置关系的工具,生成pdf

一只海龟追逐键盘控制的海龟
ROS基础 坐标管理系统与广播监听_第1张图片
有world坐标系(全局坐标系),turtle1和turtle2坐标系
ROS基础 坐标管理系统与广播监听_第2张图片
显示坐标变换

$ rosrun tf tf_echo turtle1 turtle2

用于描述两只海龟的位置变换
描述量有平移(x,y,z)
旋转,四元数,弧度,角度
ROS基础 坐标管理系统与广播监听_第3张图片
通过三维可视化平台

$ rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.rviz

Fixed Frame改为world,基准设为全局坐标系
Add添加TF
即可通过三维可视化看到turtle1和turtle2的运动
过程就是turtle2跟随turtle1运动,达到重合
ROS基础 坐标管理系统与广播监听_第4张图片

坐标系广播和监听编程实现

创建TF功能包

$ cd ~/catkin_ws/src
$ catkin_create_pkg learning_tf roscpp rospy tf turtlesim

在tf功能包的src中创建turtle_tf_broadcaster.cpp

实现TF广播器步骤

  • 定义TF广播器(TransformBroadcaster)
  • 创建坐标变换值
  • 发布坐标变换(sendTransform)
//该例程产生tf数据,并计算、发布turtle2的速度指令
#include 
#include 
#include 
std::string turtle_name;

void poseCallback(const turtlesim::PoseConstPtr& msg){
	// 创建tf的广播器
	static tf::TransformBroadcaster br;
	// 初始化tf数据
	tf::Transform transform;
	transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );	//平移量
	tf::Quaternion q;
	q.setRPY(0, 0, msg->theta);									//旋转量
	transform.setRotation(q);
	// 广播world与海龟坐标系之间的tf数据
	br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}

int main(int argc, char** argv){
    // 初始化ROS节点
	ros::init(argc, argv, "my_tf_broadcaster");
	// 输入参数作为海龟的名字
	if (argc != 2){
		ROS_ERROR("need turtle name as argument"); 
		return -1;
	}
	turtle_name = argv[1];
	// 创建句柄,订阅海龟的位姿话题
	ros::NodeHandle node;
	ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
    // 循环等待回调函数
	ros::spin();
	return 0;
};

在tf功能包的src中创建turtle_tf_listener.cpp

实现TF监听器步骤

  • 定义TF监听器(TransformListener)
  • 查找坐标变换(waitForTransform,lookupTransform)
//该例程监听tf数据,并计算、发布turtle2的速度指令
#include 
#include 
#include 
#include 

int main(int argc, char** argv){
	// 初始化ROS节点
	ros::init(argc, argv, "my_tf_listener");
    // 创建节点句柄
	ros::NodeHandle node;
	// 请求产生turtle2
	ros::service::waitForService("/spawn");
	ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
	turtlesim::Spawn srv;
	add_turtle.call(srv);
	// 创建发布turtle2速度控制指令的发布者
	ros::Publisher turtle_vel = node.advertise<geometry_msgs::Twist>("/turtle2/cmd_vel", 10);
	// 创建tf的监听器
	tf::TransformListener listener;
	ros::Rate rate(10.0);
	while (node.ok()){
		// 获取turtle1与turtle2坐标系之间的tf数据
		tf::StampedTransform transform;
		try{
			listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));		//等待变换
			listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);					//查询变换
		}
		catch (tf::TransformException &ex){
			ROS_ERROR("%s",ex.what());
			ros::Duration(1.0).sleep();
			continue;
		}
		// 根据turtle1与turtle2坐标系之间的位置关系,发布turtle2的速度控制指令
		geometry_msgs::Twist vel_msg;
		vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(), transform.getOrigin().x());					//线速度
		vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) + pow(transform.getOrigin().y(), 2));	//角速度
		turtle_vel.publish(vel_msg);
		rate.sleep();
	}
	return 0;
};

配置CMakeLists.txt中的编译规则,build栏

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)		#编译可执行文件
target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)			#链接库
target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})

编译运行

$ cd ~/catkin_ws
$ catkin_make
$ source devel/setup.bash
$ roscore
$ rosrun turtlesim turtlesim_node
#对运行对象命名,坐标系为turtle1
$ rosrun learning_tf turtle_tf_broadcaster __name:=turtle1_tf_broadcaster /turtle1	
#两个对象重新命名避免冲突,使之可以同时运行
$ rosrun learning_tf turtle_tf_broadcaster __name:=turtle2_tf_broadcaster /turtle2
$ rosrun learning_tf turtle_tf_listener
$ rosrun turtlesim turtle_teleop_key

实现机制就是运行的两个广播器不断广播两个海龟的位置,而监听器收到海龟位置关系后对其做出调整,也就是turtle2跟随turtle1。运行效果相同

你可能感兴趣的:(ROS,可视化,机器学习)