路径规划算法

目录

    • 碰撞检测算法:
      • 非cost_map:
        • 针对二维平面中的多边形障碍物;
      • cost_map:
        • 检测直线是否与障碍物(cost>0)的节点碰撞
    • 轨迹优化
      • 梯度下降法
        • 梯度的定义:
        • 梯度下降法流程:
        • 离散路点使用梯度下降

碰撞检测算法:

非cost_map:

针对二维平面中的多边形障碍物;

参考:https://blog.csdn.net/Azahaxia/article/details/115644042
线段与矩形:

python:

import numpy as np
class Rectangle:
    def __init__(self, n):
        #ox,oy 矩形左下角顶点  w 、h 宽和高
        self.ox = n[0]
        self.oy = n[1]
        self.w = n[2]
        self.h = n[3]
        
class Tool:
    def __init__(self,delta):
        #delta用于障碍物膨胀
        self.delta = delta

    def is_collide_with_rec(self,start, end, obs_rectangle):
        obs_vertex = self.get_obs_vertex(obs_rectangle)
        #v1, v2, v3, v4 矩形四个顶点
        for (v1, v2, v3, v4) in obs_vertex:
            #print(v1, v2, v3, v4)
            if self.is_intersect_rec(start, end, v1, v2):
                return True
            if self.is_intersect_rec(start, end, v2, v3):
                return True
            if self.is_intersect_rec(start, end, v3, v4):
                return True
            if self.is_intersect_rec(start, end, v4, v1):
                return True
        return False

    def get_obs_vertex(self,obs_rectangle):
        delta = self.delta
        obs_list = []
        vertex_list = [[obs_rectangle.ox - delta, obs_rectangle.oy - delta],
                        [obs_rectangle.ox + obs_rectangle.w + delta, obs_rectangle.oy - delta],
                        [obs_rectangle.ox + obs_rectangle.w + delta, obs_rectangle.oy + obs_rectangle.h + delta],
                        [obs_rectangle.ox - delta, obs_rectangle.oy + obs_rectangle.h + delta]]
        obs_list.append(vertex_list)
        #print(obs_list)
        return obs_list

    def is_intersect_rec(self, start, end, a, b):
        l1 = [a[0]-start[0],a[1]-start[1]]
        l2 = [b[0]-start[0],b[1]-start[1]]
        l3 = [end[0]-start[0],end[1]-start[1]]
        m1=np.cross(l3,l1); n1=np.cross(l3,l2)
        #print(m1,n1)
        if m1==0 and (a[0]-start[0])*(a[0]-end[0])<=0 and (a[1]-start[1])*(a[1]-end[1])<=0 :
                return True
        if n1==0 and (b[0]-start[0])*(b[0]-end[0])<=0 and (b[1]-start[1])*(b[1]-end[1])<=0 :
                return True
        
        l4= [start[0]-a[0],start[1]-a[1]]
        l5= [end[0]-a[0],end[1]-a[1]]
        l6= [b[0]-a[0],b[1]-a[1]]
        m2=np.cross(l6,l4); n2=np.cross(l6,l5)
        #print(m2,n2)
        if m2==0 and (start[0]-a[0])*(start[0]-b[0])<=0 and (start[1]-a[1])*(start[1]-b[1])<=0:
                return True
        if n2==0 and (end[0]-a[0])*(end[0]-b[0])<=0 and (end[1]-a[1])*(end[1]-b[1])<=0:
                return True
        if (m1*n1)<0 and (m2*n2)<0:
            return True
        return False

if __name__ == '__main__':
    rec=Rectangle([1,1,1,1])
    tool=Tool(0)
    start=[0,0];end=[1,1]
    res = tool.is_collide_with_rec(start,end,rec)
    print(res)

C++:

#include 
#include 
#include 
#include 
#include 
using namespace std;
//class Rectangle
//{
//
//};
class Solution1
{
public:
	// is_collide_with_rectangle 用于检测线段(两点连线)是否与矩形障碍物发生碰撞
	bool is_collide_with_rectangle(vector<int> &start, vector<int>& end, vector<int>& rec) {
		vector<vector<int>> rec_vertex = get_vertex_of_rec(rec);
		vector<int> v1 = rec_vertex[0];
		vector<int> v2 = rec_vertex[1];
		vector<int> v3 = rec_vertex[2];
		vector<int> v4 = rec_vertex[3];
		if (is_collide_with_vertex(start, end, v1, v2)){
			cout << "11111 " << endl;
			return true;
		}			
		if (is_collide_with_vertex(start, end, v2, v3)){
			cout << "2222 " << endl;
			return true;
		}	
		if (is_collide_with_vertex(start, end, v3, v4)){
			cout << "333 " << endl;
			return true;
		}	
		if (is_collide_with_vertex(start, end, v4, v1)){
			cout << "444 " << endl;
			return true;
		}		
		return false;
	}

	// get_vertex_of_rec 用于获取rec的四个顶点
	vector<vector<int>> get_vertex_of_rec(vector<int> rec) {
		vector<vector<int>> vertex_list(4,vector<int>(2));
		//cout << rec[0] << " " << rec[1] << " " << rec[2]<< " " << rec[3]<< endl;
		/*vertex_list[0][0] = rec[0];			 vertex_list[0][1] = rec[1];
		vertex_list[1][0] = rec[0] + rec[2]; vertex_list[1][1] = rec[1];
		vertex_list[2][0] = rec[0] + rec[2]; vertex_list[1][1] = rec[1] + rec[3];
		vertex_list[3][0] = rec[0];			 vertex_list[3][1] = rec[1] + rec[3];*/
		vertex_list[0] = { rec[0] ,rec[1] };
		vertex_list[1] = { rec[0] + rec[2] ,rec[1] };
		vertex_list[2] = { rec[0] + rec[2] ,rec[1] + rec[3] };
		vertex_list[3] = { rec[0] ,rec[1] + rec[3] };
		//cout << vertex_list[0][0] << " " << vertex_list[0][1] << endl;
		//cout << vertex_list[1][0] << " " << vertex_list[1][1] << endl;
		//cout << vertex_list[2][0] << " " << vertex_list[2][1] << endl;
		//cout << vertex_list[3][0] << " " << vertex_list[3][1] << endl;
		return vertex_list;
	}

	bool is_collide_with_vertex(vector<int> &start, vector<int> &end, vector<int> &vertex1, vector<int>& vertex2) {
		vector<int> l1(2), l2(2), l3(2), l4(2), l5(2), l6(2);
		/*l1[0] = vertex1[0] - start[0]; l1[1] = vertex1[1] - start[1];
		l2[0] = vertex2[0] - start[0]; l1[1] = vertex2[1] - start[1];
		l3[0] = end[0] - start[0];	   l3[1] = end[1] - start[1];*/

		l1 = { vertex1[0] - start[0] ,vertex1[1] - start[1] };
		l2 = { vertex2[0] - start[0] ,vertex2[1] - start[1] };
		l3 = { end[0] - start[0] ,l3[1] = end[1] - start[1] };
		int m1 = cross(l3, l1); int n1 = cross(l3, l2);
		//cout << "m1 " << m1 << " " << n1 << endl;
		//printf("%d,%d//%d,%d//%d,%d \n", start[0], start[1], end[0], end[1], vertex2[0], vertex2[1]);
		if ((m1 == 0) && ((vertex1[0] - start[0]) * (vertex1[0] - end[0]) <= 0) && ((vertex1[1] - start[1]) * (vertex1[1] - end[1]) <= 0))
		{	
			
			return true;
		}
		if ((n1 == 0) && ((vertex2[0] - start[0]) * (vertex2[0] - end[0]) <= 0) && ((vertex2[1] - start[1]) * (vertex2[1] - end[1]) <= 0))
		{
			return true;
		}
		
	/*	l4[0] = start[0] - vertex1[0]; l4[1] = start[1] - vertex1[1];
		l5[0] = end[0] - vertex1[0]; l5[1] = end[1] - vertex1[1];
		l6[0] = vertex2[0] - vertex1[0]; l6[1] = vertex2[1] - vertex1[1];*/
		l4 = { start[0] - vertex1[0] ,start[1] - vertex1[1] };
		l5 = { end[0] - vertex1[0] ,end[1] - vertex1[1] };
		l6 = { vertex2[0] - vertex1[0] ,vertex2[1] - vertex1[1] };

		int m2 = cross(l6, l4); int n2 = cross(l6, l5);
		cout << "m2 " << m2 << " " << n2 << endl;
		if ((m2 == 0) && ((start[0] - vertex1[0]) * (start[0] - vertex2[0]) <= 0) && ((start[1] - vertex1[1]) * (start[1] - vertex2[1]) <= 0))
		{
			//printf("%d,%d//%d,%d//%d,%d \n", start[0], start[1], vertex1[0], vertex1[1], vertex2[0], vertex2[1]);
			return true;
		}
		if ((n2 == 0) && ((end[0] - vertex1[0]) * (end[0]- vertex2[0]) <= 0) && ((end[1] - vertex1[1]) * (end[1]- vertex2[1]) <= 0))
		{
			return true;
		}

		if ((m1 * n1 < 0) && (m2 * n2 < 0))
		{
			//cout << "!! " << endl;
			return true;
		}
		return false;
	}
	int cross(vector<int> &v1, vector<int> &v2) {
		return (v1[0] * v2[1] - v1[1] * v2[0]);
	}
};

int main() {
	//rec为矩形障碍物,rec{x,y,w,h} xy为第一个顶点坐标,wh为宽和高
	vector<int> rec{ 1,1,1,1 };
	vector<int> start{ 1,1 };
	vector<int> end{ 0,1 };
	vector<vector<int>> vertex_list(4, vector<int>(2,0));
	Solution1 sol;
	bool result=sol.is_collide_with_rectangle(start,end,rec);
	cout << "result" << result <<endl;
	return 0;
};

cost_map:

检测直线是否与障碍物(cost>0)的节点碰撞

参考:https://blog.csdn.net/u014028063/article/details/80917486?spm=1001.2014.3001.5506

#include
#include

using namespace std;

//5*4的cost_map,为0时可通行,为1时是障碍物节点;
vector<vector<int>> cost(5, vector<int>(4, 0));


/*
* description: 检测直线是否与障碍物发生碰撞;
* param: start_x,start_y,end_x,end_y 直线起点终点的坐标;
* return: true 发生碰撞,false 不发生碰撞;
*/
bool is_line_collision(float start_x, float start_y, float end_x, float end_y) {
	//计算与横轴交点
	float intersection_x, intersection_y;
	float k = (end_y - start_y) / (end_x - start_x);
	cout << k << endl;

	if (k <= 1 && k >= -1) {
		int sign;//移动判断点的方向
		if ((end_x - start_x) >= 0) {
			sign = 1;
		}
		else {
			sign = -1;
		}
		for (int i = 0; i < (end_x - start_x)*sign; i++)
		{
			if (i == 0) {
				intersection_x = start_x + 0.5 * sign;
			}
			else
			{
				intersection_x = intersection_x + 1 * sign;
			}
			intersection_y = k * (intersection_x - start_x) + start_y;
			//cout << intersection_x << "//" << intersection_y << endl;
			int x1 = floor(intersection_x);
			int x2 = x1 + 1;
			int y0 = floor(intersection_y);
			int y1,y2;
			if ((intersection_y - y0) < 0.5) {
				y1 = y0;
				if (cost[x1][y1] == 1 || cost[x2][y1] == 1)
					return true;
			}
			else if ((intersection_y - y0) == 0.5) {
				//四点共享
				y1 = y0; y2 = y0 + 1;
				if(cost[x1][y1] == 1 || cost[x2][y1] == 1|| cost[x2][y1] == 1 || cost[x2][y2] == 1)
					return true;
			}
			else {
				y1 = y0 + 1;
				if (cost[x1][y1] == 1 || cost[x2][y1] == 1)
					return true;
			}
			cout << x1 << "//" << y1 << endl;
			cout << x2 << "//" << y1 << endl;
			
		}
	}
		
	else {
		int sign;
		if ((end_y - start_y) >= 0) {
			sign = 1;
		}
		else {
			sign = -1;
		}
		for (int i = 0; i < (end_y - start_y)*sign; i++)
		{
			if (i == 0) {
				intersection_y = start_y + 0.5 * sign;
			}
			else
			{
				intersection_y = intersection_y + 1 * sign;
			}
			intersection_x = (intersection_y - start_y)/k + start_x;
			//cout << intersection_x << "//" << intersection_y << endl;

			int y1 = floor(intersection_y);
			int y2 = y1 + 1;
			int x0 = floor(intersection_x);
			int x1,x2;
			if ((intersection_x - x0) < 0.5) {
				x1 = x0;
				if (cost[x1][y1] == 1 || cost[x1][y2] == 1)
					return true;
			}
			else if ((intersection_x - x0) == 0.5) {
				x1 = x0; x2 = x0 + 1;
				if (cost[x1][y1] == 1 || cost[x1][y2] == 1|| cost[x2][y1] == 1 || cost[x2][y2] == 1)
					return true;
			}
			else {
				x1 = x0 + 1;
				if (cost[x1][y1] == 1 || cost[x1][y2] == 1)
					return true;
			}
		}
	}
	return false;
}

void main() {
	//设置cost_map的障碍物节点;
	cost[2][1] = 1; cost[2][3] = 1;
	cout<<is_line_collision(2, 2, 2, 0)<<endl;	
}

轨迹优化

梯度下降法

梯度的定义:

如一元函数: y = f ( x ) y=f(x) y=f(x)
梯度就是函数的导数,即
∇ f ( x ) = f ′ ( x ) \nabla f(x) = f'(x) f(x)=f(x)
若为多元函数,则梯度为函数的偏微分,即
∇ f ( x 1 , x 2 , . . x n ) = ∂ f x 1 i 1 + ∂ f x 2 i 2 + . . . + ∂ f x n i n \nabla f(x_1,x_2,.. x_n) =\frac{\partial f}{x_1} i_1 + \frac{\partial f}{x_2} i_2 +...+ \frac{\partial f}{x_n} i_n f(x1,x2,..xn)=x1fi1+x2fi2+...+xnfin

梯度下降法流程:

  1. 设定参数 η (步长),ε (误差),设定自变量(x1,x2,… xn)的取值(a1,a2,…an);
  2. 求出各自变量(x1,x2,… xn)在取值(a1,a2,…an)时的偏导数,
    f ′ ( x m ) = ∂ f ∂ x m a m f'(x_m) =\frac{\partial f}{\partial x_m}a_m f(xm)=xmfam
    利用偏导数求出下一次迭代的新的变量取值(a1’,a2’,…an’)
    a m ′ = a m − η f ′ ( x m ) = a m − η ∂ f ∂ x m a m a_m' = a_m -\eta f'(x_m) = a_m -\eta \frac{\partial f}{\partial x_m}a_m am=amηf(xm)=amηxmfam
  3. 判断
    Δ a m = a m − a m ′ < ϵ \Delta am =a_m - a_m' < \epsilon Δam=amam<ϵ
    若成立,则退出迭代,求解出(a1’,a2’,…an’)为目标自变量取值;
    若不成立,则令(a1,a2,…an)=(a1’,a2’,…an’),并回到第2步,继续迭代。

离散路点使用梯度下降

示例:
如下图为一条离散路径,共7个路点,优化目标为在路径不碰到障碍物的情况下最优化路径。
路径规划算法_第1张图片

为简单起见,这里的优化目标设置为路径的长度代价。
设路径表达式为
l ( p 1 , p 2 , . . . p n ) l(p_1,p_2,...p_n) l(p1,p2,...pn),其中p1,p2,…pn为图上的路点,有pm=(xm,ym)
路径代价函数
c o s t = f ( l ( p 1 , p 2 , . . . p n ) ) cost =f(l(p_1,p_2,...p_n)) cost=f(l(p1,p2,...pn))
f函数是对路径求长度的函数,那么优化目标就是让路径长度最短。
对于离散路径不是一个连续函数,是无法求梯度/导数,那就使用伪梯度。
对p2点求梯度方向,即为p2 垂直于p1 p3的连线的方向,如下图所示。
路径规划算法_第2张图片

从直观上讲,将p2坐标改为两垂线的焦点p2’会使得路径更短,因为有
p1p2 + p2p3 > p1p2’ + p2’p3。那么将p2点向p2’点方向移动一小个步长,也会使得路径长度更短。
那么对出了首尾两端的路径点都进行这样的操作,则新的路径点如下图:
路径规划算法_第3张图片
p2、p4、p5都进行了梯度下降,如红点所示,p3、p6则因为已经在最优位置了,不需要操作,新的路径如红线所示。在使用伪梯度下降时,需要确保路径不会于障碍物发生碰撞。
并对新的路径点求new cost,判断
c o s t = f ( l ( p 1 , p 2 , . . . p n ) ) − c o s t = f ( l ( p 1 ′ , p 2 ′ , . . . p n ′ ) ) < ε cost =f(l(p_1,p_2,...p_n)) - cost =f(l(p_1',p_2',...p_n')) < ε cost=f(l(p1,p2,...pn))cost=f(l(p1,p2,...pn))<ε
是否成立,成立则结束迭代,找到局部最优路径;否则将继续新一轮梯度下降迭代。

你可能感兴趣的:(轨迹规划,算法,python)