Python - OpenDrive Map - 使用菲涅耳积分的螺旋/ Clothoid / Euler螺旋/ Curu螺旋插值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python - OpenDrive Map - 使用菲涅耳积分的螺旋/ Clothoid / Euler螺旋/ Curu螺旋插值相关的知识,希望对你有一定的参考价值。

地图格式OpenDrive提供(以及其他)道路的几何形状。道路的每个区段可以具有不同的几何形状(例如,线,弧,螺旋,多项式)。道路几何形状“螺旋”的提供信息如下:

 - s - relative position of the road segment in respect to the beginning of the road (not used in here)
 - x - the "x" position of the starting point of the road segment
 - y - the "y" position of the starting point of the road segment
 - hdg - the heading of the starting point of the road segment
 - length - the length of the road segment
 - curvStart - the curvature at the start of the road segment
 - curvEnd - the curvature at the end of the road segment

我的目标是在给定“分辨率”参数的情况下沿着螺旋插入点(例如,分辨率= 1,沿着螺旋每个仪表插入一个点)。螺旋几何形状使得它引入曲率的恒定变化(1 /半径),从而创建从线到弧的平滑且稳定的过渡,使得车辆上的横向加速力小于从...的过渡。直接线到弧(线曲率= 0,弧曲率=常数)。

螺旋总是有一个曲率为0的终点(它连接到道路的线段),另一个作为常数(例如0.05,它连接到弧线)。根据连接顺序,curvStart可以等于0或常数,而curvEnd也可以等于0或常数。它们不能同时等于0或恒定。

下面的代码是一个函数,它将前面讨论的参数(由格式给出)和分辨率作为参数。

目前,我遇到以下问题:

  • 插入相距1米的等距点(见图1)
  • 获得点的正确标题(检查图2)
  • 找到最后2个案例的解决方案

根据我对如何完成任务的研究,我找到了一些有用的资源,但没有一个帮助我获得最终的解决方案:

SciPy: What are the arguments in scipy.special.fresnel(x[, out1, out2])?
答案

我不确定您当前的代码是否正确。我写了一个简短的脚本来使用类似的参数插入欧拉螺旋,它给出了不同的结果:



import numpy as np
from math import cos, sin, pi, radians
from scipy.special import fresnel
import matplotlib.pyplot as plt
%matplotlib inline

def spiralInterpolation(resolution, s, x, y, hdg, length, curvStart, curvEnd):
    points = np.zeros((int(length/resolution), 1))
    points = [i*resolution for i in range(len(points))]
    xx = np.zeros_like(points)
    yy = np.zeros_like(points)
    hh = np.zeros_like(points)
    if curvStart == 0 and curvEnd > 0:
        print("Case 1: curvStart == 0 and curvEnd > 0")
        radius = np.abs(1/curvEnd)
        A_sq = radius*length
        ss, cc = fresnel(np.square(points)/(2*A_sq*np.sqrt(np.pi/2)))
        xx = points*cc
        yy = points*ss
        hh = np.square(points)*2*radius*length
        xx, yy, hh = rotate(xx, yy, hh, hdg)
        xx, yy = translate(xx, yy, x, y)
        xx = np.insert(xx, 0, x, axis=0)
        yy = np.insert(yy, 0, y, axis=0)
        hh = np.insert(hh, 0, hdg, axis=0)

    elif curvStart == 0 and curvEnd < 0:
        print("Case 2: curvStart == 0 and curvEnd < 0")
        radius = np.abs(1/curvEnd)
        A_sq = radius*length
        ss, cc = fresnel(np.square(points)/(2*A_sq*np.sqrt(np.pi/2)))
        xx = points*cc
        yy = points*ss*-1
        hh = np.square(points)*2*radius*length
        xx, yy, hh = rotate(xx, yy, hh, hdg)
        xx, yy = translate(xx, yy, x, y)
        xx = np.insert(xx, 0, x, axis=0)
        yy = np.insert(yy, 0, y, axis=0)
        hh = np.insert(hh, 0, hdg, axis=0)

    elif curvEnd == 0 and curvStart > 0:
        print("Case 3: curvEnd == 0 and curvStart > 0")

    elif curvEnd == 0 and curvStart < 0:
        print("Case 4: curvEnd == 0 and curvStart < 0")

    else:
        print("The curvature parameters differ from the 4 predefined cases. Change curvStart and/or curvEnd")

    n_stations = int(length/resolution) + 1
    stations = np.zeros((n_stations, 3))
    for i in range(len(xx)):
        stations[i][0] = xx[i]
        stations[i][1] = yy[i]
        stations[i][2] = hh[i]

    return stations

    def rotate(x, y, h, angle):
        # This function rotates the x and y vectors around zero
        xx = np.zeros_like(x)
        yy = np.zeros_like(y)
        hh = np.zeros_like(h)
        for i in range(len(x)):
            xx[i] = x[i]*cos(angle) - y[i]*sin(angle)
            yy[i] = x[i]*sin(angle) + y[i]*cos(angle)
            hh[i] = h[i] + angle
        return xx, yy, hh

    def translate(x, y, x_delta, y_delta):
        # This function translates the x and y vectors with the delta values
        xx = np.zeros_like(x)
        yy = np.zeros_like(y)
        for i in range(len(x)):
            xx[i] = x[i] + x_delta
            yy[i] = y[i] + y_delta 
        return xx, yy

    stations = spiralInterpolation(1, 77, 50, 100, radians(56), 40, 0, 1/20)

    x = []
    y = []
    h = []

    for station in stations:
        x.append(station[0])
        y.append(station[1])
        h.append(station[2])

    plt.figure(figsize=(20,13))
    plt.plot(x, y, '.')
    plt.grid(True)
    plt.axis('equal')
    plt.show()

    def get_heading_components(x, y, h, length=1):
        xa = np.zeros_like(x)
        ya = np.zeros_like(y)
        for i in range(len(x)):
            xa[i] = length*cos(h[i])
            ya[i] = length*sin(h[i])
        return xa, ya

    xa, ya = get_heading_components(x, y, h)
    plt.figure(figsize=(20,13))
    plt.quiver(x, y, xa, ya, width=0.005)
    plt.grid(True)
    plt.axis('equal')
    plt.show()

有了这个,我得到了

import numpy as np from math import cos, sin, pi, radians, sqrt from scipy.special import fresnel import matplotlib.pyplot as plt def spiral_interp_centre(distance, x, y, hdg, length, curvEnd): '''Interpolate for a spiral centred on the origin''' # s doesn't seem to be needed... theta = hdg # Angle of the start of the curve Ltot = length # Length of curve Rend = 1 / curvEnd # Radius of curvature at end of spiral # Rescale, compute and unscale a = 1 / sqrt(2 * Ltot * Rend) # Scale factor distance_scaled = distance * a # Distance along normalised spiral deltay_scaled, deltax_scaled = fresnel(distance_scaled) deltax = deltax_scaled / a deltay = deltay_scaled / a # deltax and deltay give coordinates for theta=0 deltax_rot = deltax * cos(theta) - deltay * sin(theta) deltay_rot = deltax * sin(theta) + deltay * cos(theta) # Spiral is relative to the starting coordinates xcoord = x + deltax_rot ycoord = y + deltay_rot return xcoord, ycoord fig = plt.figure() ax = fig.add_subplot(1, 1, 1) # This version xs = [] ys = [] for n in range(-100, 100+1): x, y = spiral_interp_centre(n, 50, 100, radians(56), 40, 1/20.) xs.append(x) ys.append(y) ax.plot(xs, ys) # Your version from yourspiral import spiralInterpolation stations = spiralInterpolation(1, 77, 50, 100, radians(56), 40, 0, 1/20.) ax.plot(stations[:,0], stations[:,1]) ax.legend(['My spiral', 'Your spiral']) fig.savefig('spiral.png') plt.show()

哪个是正确的?

同样在曲率在结尾处为零且在开始时非零的情况下,Plot from above code代表什么?它是曲线起点或终点的角度吗?你的函数也接受了一个未使用的参数hdg。它应该是相关的吗?

如果您的示例代码显示了螺旋段之前和之后的线段图,那么将更容易看出哪个是正确的并且知道每个参数的含义。

以上是关于Python - OpenDrive Map - 使用菲涅耳积分的螺旋/ Clothoid / Euler螺旋/ Curu螺旋插值的主要内容,如果未能解决你的问题,请参考以下文章

Apollo使用方法;map_gen工具使用

Java解析OpenDrive,OpenDrive格式解析

万字详解OpenDRIVE文件

OpenDrive学习笔记

OpenDrive学习笔记

OpenX系列标准:OpenDRIVE标准简述