参考: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;
};
参考: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)=x1∂fi1+x2∂fi2+...+xn∂fin
示例:
如下图为一条离散路径,共7个路点,优化目标为在路径不碰到障碍物的情况下最优化路径。
为简单起见,这里的优化目标设置为路径的长度代价。
设路径表达式为
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的连线的方向,如下图所示。
从直观上讲,将p2坐标改为两垂线的焦点p2’会使得路径更短,因为有
p1p2 + p2p3 > p1p2’ + p2’p3。那么将p2点向p2’点方向移动一小个步长,也会使得路径长度更短。
那么对出了首尾两端的路径点都进行这样的操作,则新的路径点如下图:
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′))<ε
是否成立,成立则结束迭代,找到局部最优路径;否则将继续新一轮梯度下降迭代。