跟随
效果介绍¶
界面上有两只小乌龟:
- 小乌龟A
- 小乌龟B
- 小乌龟B跟随着小乌龟A走
- 小乌龟A通过键盘控制移动
分析¶
- 界面上需要显示两只小乌龟
- 小乌龟A通过键盘运动
- 小乌龟B通过代码控制来跟随小乌龟A运动
坐标系构建¶
- 小乌龟A的坐标系
- 小乌龟B的坐标系
可以通过订阅广播获得两只小乌龟的位置信息.
TF开发流程¶
坐标系构建¶
- 将显示界面定义为世界坐标系
- 将小乌龟A定义为自身坐标系
- 将小乌龟B定义为自身坐标系
广播发送自身位置¶
小乌龟A¶
from turtlesim.msg import Pose
from tf.broadcaster import TransformBroadcaster
from tf.transformations import quaternion_from_euler
def pose_callback(msg):
if not isinstance(msg, Pose):
return
x = msg.x
y = msg.y
# 小乌龟Z轴转动的角度, roll: x pitch: y yaw:z
theta = msg.theta
# 实时发布位置信息到TF工具
# 位置
translation = (x, y, 0)
# 姿态 tf工具是用四元素来描述姿态信息 将 rpy欧拉角描述方式转换为 四元素描述方式
rotation = quaternion_from_euler(0, 0, theta)
broadcaster.sendTransform(translation, rotation, rospy.Time().now(), "turtle_a", "world")
小乌龟B¶
实现和小乌龟A类似
收听者获取坐标关系¶
以小乌龟B为参考系
以小乌龟A为参考系
# 获取相对位置信息的listener
listener = TransformListener()
rate = rospy.Rate(10)
while not rospy.is_shutdown():
# //实时查看turtle_a 在 turtle_b的坐标系中的位置
#
# // target_frame: 坐标系,参考坐标系
# // source_frame: 求解的坐标系
# // 想知道 source_frame在 target_frame的位置信息
# // time: 0获得最近我和你的相对位置
try:
transform = listener.lookupTransform("turtle_a", "turtle_b", rospy.Time())
except:
rate.sleep()
continue
# 获取位置
x, y, z = transform[0]
# # 获取姿态 (四元素) -> rpy
quat = transform[1]
roll, pitch, yaw = euler_from_quaternion(quat)
运动规划¶
以小乌龟B为参考系
以小乌龟A为参考系
distance = sqrt(pow(x, 2) + pow(y, 2))
angular = atan2(y, x)
twist = Twist()
twist.linear.x = 0.6 * distance
twist.angular.z = 6 * angular
publisher.publish(twist)
总结优化¶
实现的内容¶
小乌龟A节点¶
- 订阅小乌龟A的位姿
- 广播小乌龟A和界面的坐标关系
小乌龟B节点¶
- 产生小乌龟B
- 订阅小乌龟B的位姿
- 广播小乌龟B和界面的坐标关系
- 接收小乌龟A和B的坐标关系
- 控制小乌龟B实现追随功能
优化策略¶
小乌龟节点¶
- 杀死小乌龟
- 产生小乌龟
- 订阅小乌龟的位姿
- 广播小乌龟和界面的坐标关系
追随功能节点¶
- 接收小乌龟A和B的坐标关系
- 控制小乌龟实现追随功能
launch文件¶
- 配置两个小乌龟节点,参数不同
- 配置追随功能节点,参数配置