一个简单的路径规划

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近在做差速小车pathplanning相关工作,记录一下相关的知识点


一、问题描述

任意两条直线的道路交汇于B点,假定小车的转弯半径为R,为小车规划一条路径,从A行驶到C在这里插入图片描述
在这里插入图片描述

二、求解步骤

1.求半径为R的圆与两条直线相切时的圆心和切点

代码如下(示例):

A = [1,1]
B = [10,10]
C = [19,1]
radius = 1.5 #m

def line_2D(pos_start,pos_end):
    k = (pos_end[1]-pos_start[1])/(pos_end[0]-pos_start[0])
    b = pos_end[1] - k*pos_end[0]
    return k,b
    
def find_circle(A,B,C,radius):
    k1,b1 = line_2D(A,B)
    k2,b2 = line_2D(B,C)
    if (A[1]-k2*A[0]-b2)<0:
        bb2 = b2 - radius/math.cos(math.atan(k2))
    else:
        bb2 = b2 + radius/math.cos(math.atan(k2))
    if (C[1]-k1*C[0]-b1)<0:
        bb1 = b1 - radius/math.cos(math.atan(k1))
    else:
        bb1 = b1 + radius/math.cos(math.atan(k1))
    x0 = (bb2 - bb1)/(k1 - k2)
    y0 = k1*x0+bb1
    circle_center = (x0,y0)
    x1 = (x0+k1*(y0-b1))/(1+k1**2)
    y1 = k1*x1+b1
    tangency1 =(x1,y1)
    x2 = (x0+k2*(y0-b2))/(1+k2**2)
    y2 = k2*x2+b2
    tangency2 =(x2,y2)
    return tangency1,tangency2,circle_center

2.判断C点在AB直线的左边还是右边,如果在左边就在到达切点1时选择逆时针方向旋转

def isleft(a,b,c):
    ux,uy = c[0] - a[0],c[1] - a[1]
    vx,vy = b[0] - a[0],b[1] - a[1]
    return ux*vy-uy*vx>0

3.路径path由x,y,yaw组成

class PrePath:
    def __init__(self):
        self.x = []
        self.y = []
        self.yaw = []

def getLinePath(pos_1,pos_2,v,dt):
    path = PrePath()
    k,b = line_2D(pos_1,pos_2)
    x_ = pos_1[0]
    y_ = pos_1[1]
    if pos_2[0] - pos_1[0]>0:
        while(x_ + v*dt*math.cos(math.atan(k)) <= pos_2[0]):
            path.x.append(x_)
            path.y.append(k*x_+b)
            x_ += v*dt*math.cos(math.atan(k))
            path.yaw.append(math.atan(k))
    else:
        while(x_ - v*dt*math.cos(math.atan(k)) >= pos_2[0]):
            path.x.append(x_)
            y_ = k*x_+b
            path.y.append(y_)
            x_ += v*dt*math.cos(math.atan(k))
            path.yaw.append(math.atan(k)+math.pi)
    return path

def zero_to_2pi(theta):
    while(theta<0):
        theta+=2*math.pi
    while(theta>2*math.pi):
        theta-=2*math.pi
    return theta


def getCirclePath(tangcy1,tangcy2,circle_center,radius,trun_dir,V,dt):
    path = PrePath()
    theta1 = math.atan((tangcy1[1]-circle_center[1])/(tangcy1[0]-circle_center[0]))
    if (tangcy1[0]-circle_center[0])<0:
        theta1+=math.pi
    theta1 = zero_to_2pi(theta1)
    theta2 = math.atan((tangcy2[1]-circle_center[1])/(tangcy2[0]-circle_center[0]))
    if (tangcy2[0]-circle_center[0])<0:
        theta2+=math.pi
    theta2 = zero_to_2pi(theta2)
    dtheta = V*dt/radius 
    if trun_dir:
        opera = -1 #顺时针减
        omega = zero_to_2pi(theta1-theta2)
    else:
        opera = 1 #逆时针加
        omega = zero_to_2pi(theta2-theta1)
    num = math.ceil(omega*radius/(V*dt))
    for i in range(num):
        x,y = cacu_circle(circle_center,radius,theta1+i*opera*dtheta)
        path.x.append(x)
        path.y.append(y)
        path.yaw.append(theta1 + opera*(i*dtheta + math.pi/2))
    return path

4.组成完整的path

V = 1.0  #m/s
dt = 0.1 #s

qiedian1,qiedian2,circle_center = find_circle(A, B, C, R)
trun_dir = isleft(A,B,C)
path1 = getLinePath(A,qiedian1,V,dt)
path2 = getCirclePath(qiedian1,qiedian2,circle_center,R,trun_dir,V,dt)
path3 = getLinePath(qiedian2,C,V,dt)
path = PrePath()
path.x = path1.x+path2.x+path3.x
path.y = path1.y+path2.y+path3.y
path.yaw = path1.yaw+path2.yaw+path3.yaw

plt.plot(path.x, path.y, "-r")

总结

先求出圆与两条直线的两个切点将路径分为3段,选择外侧圆弧与两条直线拼接得到最终路径

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值