pure pursuit纯跟踪

Pure Pursuit是一种几何追踪方法,速度越小,performance越好;

\delta:汽车前轮转角

L:前后轮轴距(车长)

R:转弯半径

将车辆模型简化为自行车模型(这里默认左轮和右轮的旋转是一致的)!!!

bicycle model:

tan\delta =\frac{L}{R }

pure pursuit建立于自行车模型和阿克曼小车模型的基础上,goal point为距离后轴中心最近的点.

1、pure pursuit的公式推导:

\alpha:目标点方向和当前航向角方向夹角;

l_{d}:前视距离;

e_{ld}:横向误差;

\frac{l_{d}}{sin2\alpha }=\frac{R}{sin(\frac{\Pi }{2}-\alpha )}

\frac{l_{_d}}{2sin\alpha cos\alpha }=\frac{R}{cos\alpha }

R = \frac{2l_{_d}}{sin\alpha }   

sin\alpha =\frac{e_{ld}}{l_{d}}

联立R = \frac{2l_{_d}}{sin\alpha }tan\delta =\frac{L}{R }可得:

\delta(t) = tan^{-1}(\frac{2L}{l_{d}^2}e_{ld}(t))

以上就是pure pursuit的相关公式,purepursuit是基于横向误差(cross track error)放大\frac{2L}{l_{d}^2}倍的比例控制器。

2、pure pursuit的实现步骤:

(1)确定车辆自身位置

(2)找到距离当前位置最近的点

(3)寻找目标点G,以车辆后轴为中心,Ld为半径画一个圆弧找到规划路径的交点

(4)转换到车身坐标系下

(5)用pure pursuit计算公式计算到达目标点所需的转向角

3、影响因素

由purepursuit公式可知,影响最大的就是l_{_{d}}l_{_{d}}会影响(steering angle )\delta、进而影响车辆对轨迹的追踪效果;

l_{_d}pure pursuit performance 越好稳定性越差准确性越高
l_{_d}pure pursuit performance 越差稳定性越好准确性越低

 4、改进

l_{_d} 并没有和vehicle的velociety相关,并且(steering angle)\delta并不能无限大无限小;

改进:对l_{_d}和速度关联起来(pure_pursuit的特性是:长的平滑轨迹上越小的前视距离准确度越好),对\delta设定范围;

\delta (t)=tan^{-1}(\frac{2Lsin(\alpha(t))}{l_{d}})

 \delta(t)=tan^{-1}(\frac{2Lsin(\alpha )}{kv_{x}})

l_{_d} = KV_{_x}l_{_d}与V关联起来,V正比于l_{_d}

K越小稳定性越差
K越大Acc越小

5、pure_pursuit的挑战

(1)如何选择一个合适的前视距离?

答:l_{_d} = KV_{_x}

(2)不要刻意的将pure_pursuit针对于某一特定的场景进行调整、因为会出现过拟合现象;

(3)当车辆还没有到预瞄点的时候就切换到下一个目标点,故无法对曲线达到100%的追踪,对于直线的效果很好;

#!/usr/bin/env python

import os
import csv
import math

from geometry_msgs.msg import Quaternion, PoseStamped, TwistStamped, Twist

from styx_msgs.msg import Lane, Waypoint

from gazebo_msgs.msg import ModelStates

import tf
import rospy

HORIZON = 6.0

class PurePersuit:
	def __init__(self):
		rospy.init_node('pure_persuit', log_level=rospy.DEBUG)

		rospy.Subscriber('/smart/rear_pose', PoseStamped, self.pose_cb, queue_size = 1)
		rospy.Subscriber('/smart/velocity', TwistStamped, self.vel_cb, queue_size = 1)
		rospy.Subscriber('/final_waypoints', Lane, self.lane_cb, queue_size = 1)

		self.twist_pub = rospy.Publisher('/smart/cmd_vel', Twist, queue_size = 1)

		self.currentPose = None
		self.currentVelocity = None
		self.currentWaypoints = None

		self.loop()

	def loop(self):
		rate = rospy.Rate(20)
		rospy.logwarn("pure persuit starts")
		while not rospy.is_shutdown():
			if self.currentPose and self.currentVelocity and self.currentWaypoints:
				twistCommand = self.calculateTwistCommand()
				self.twist_pub.publish(twistCommand)
			rate.sleep()

	def pose_cb(self,data):
		self.currentPose = data

	def vel_cb(self,data):
		self.currentVelocity = data

	def lane_cb(self,data):
		self.currentWaypoints = data

	def calculateTwistCommand(self):
		lad = 0.0 #look ahead distance accumulator
		targetIndex = len(self.currentWaypoints.waypoints) - 1
		for i in range(len(self.currentWaypoints.waypoints)):
			if((i+1) < len(self.currentWaypoints.waypoints)):
				this_x = self.currentWaypoints.waypoints[i].pose.pose.position.x
				this_y = self.currentWaypoints.waypoints[i].pose.pose.position.y
				next_x = self.currentWaypoints.waypoints[i+1].pose.pose.position.x
				next_y = self.currentWaypoints.waypoints[i+1].pose.pose.position.y
				lad = lad + math.hypot(next_x - this_x, next_y - this_y)
				if(lad > HORIZON):
					targetIndex = i+1
					break


		targetWaypoint = self.currentWaypoints.waypoints[targetIndex]

		targetSpeed = self.currentWaypoints.waypoints[0].twist.twist.linear.x

		targetX = targetWaypoint.pose.pose.position.x
		targetY = targetWaypoint.pose.pose.position.y		
		currentX = self.currentPose.pose.position.x
		currentY = self.currentPose.pose.position.y
		#get vehicle yaw angle
		quanternion = (self.currentPose.pose.orientation.x, self.currentPose.pose.orientation.y, self.currentPose.pose.orientation.z, self.currentPose.pose.orientation.w)
		euler = tf.transformations.euler_from_quaternion(quanternion)
		yaw = euler[2]
		#get angle difference
		alpha = math.atan2(targetY - currentY, targetX - currentX) - yaw
		l = math.sqrt(math.pow(currentX - targetX, 2) + math.pow(currentY - targetY, 2))
		if(l > 0.5):
			theta = math.atan(2 * 1.868 * math.sin(alpha) / l)
			# #get twist command
			twistCmd = Twist()
			twistCmd.linear.x = targetSpeed
			twistCmd.angular.z = theta 
		else:
			twistCmd = Twist()
			twistCmd.linear.x = 0
			twistCmd.angular.z = 0

		return twistCmd


if __name__ == '__main__':
    try:
        PurePersuit()
    except rospy.ROSInterruptException:
        rospy.logerr('Could not start motion control node.')

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【资源说明】 基于Matlab实现跟踪(Pure Pursuit)算法源码+项目说明.zip 基于Matlab实现跟踪(Pure Pursuit)算法 在参考资料1的基础上修正部分错误,优化代码,演示跟踪算法。 ![图片](./imgs/1.png) ## 跟踪算法本质 参考人类驾驶员的行为,以车的后轴为基点,通过控制前轮的偏角delta,使车辆沿一条经过预瞄点的**圆弧**行驶,跟踪效果将由ld决定,如何设计ld也是算法的改进方向之一。 预瞄点的引入使得控制更加平顺,普通PID控制跟踪的是离车辆最近的轨迹点,而跟踪跟踪的是预瞄点。 跟踪本质是一个**P控制器**,对车辆进行**横向控制**,代码示例中的横向误差如图所示: ![横向误差](./imgs/2.png) 可见横向误差不收敛于0,即横向控制存在静态误差,加入积分控制后,横向误差如图所示: ![横向误差](./imgs/3.png) (加入积分控制,静态误差减小,超调量增大,为减小超调量,可引入微分控制) 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值