ORCA-3D避障算法解析

二维ORCA原理参考:
https://zhuanlan.zhihu.com/p/669426124

ORCA原理图解

1. 找到避障速度增量 u

碰撞处理分为三种情况:
(1)没有发生碰撞,且相对速度落在小圆里
(2)没有发生碰撞,且相对速度落在圆锥里
(3)发生碰撞,马上做出反应
请添加图片描述
timeStep 决定了仿真每一步的时间更新间隔,是系统的时间推进基础。较小的 timeStep 可以提高仿真的精度,但会增加计算量。

timeHorizon 决定了智能体在进行避障计算时预测的时间范围。较大的 timeHorizon 值使得智能体可以更早预测潜在碰撞,但会减少它的速度选择自由度。

timeStep 是碰撞时需要计算的调整u所需的时间
timeHorizon 是未发生碰撞时,需要计算的u所化的时间,他是一种提前预测

2. 添加速度障碍平面

表示一个平面需要法向量和平面上的点
请添加图片描述

1和2对应代码如下

	// 它使用ORCA(Optimal Reciprocal Collision Avoidance)方法来计算智能体之间的避碰行为
	void Agent::computeNewVelocity()
	{
		orcaPlanes_.clear();				  // 清空ORCA平面列表
		const float invTimeHorizon = 1.0f / timeHorizon_; // 计算时间视野的倒数

		/* 创建智能体的ORCA平面 */
		for (size_t i = 0; i < agentNeighbors_.size(); ++i)
		{								       // 遍历每个邻居智能体
			const Agent *const other = agentNeighbors_[i].second;	       // 获取邻居智能体指针
			//这里的position_是在rvo->updateState添加的当前agent的位置
			// 改这块就好了===============================
			const Vector3 relativePosition = other->position_ - position_; // 计算相对位置
			const Vector3 relativeVelocity = velocity_ - other->velocity_; // 计算相对速度
			// const Vector3 relativePosition = relative_position_; // 计算相对位置
			// const Vector3 relativeVelocity = relative_velocity_; // 计算相对速度

			const float distSq = absSq(relativePosition);		       // 计算相对位置的平方距离
			const float combinedRadius = radius_ + other->radius_;	       // 计算合并半径
			const float combinedRadiusSq = sqr(combinedRadius);	       // 计算合并半径的平方

			Plane plane; // 定义一个平面对象
			Vector3 u;   // 定义速度调整向量

			if (distSq > combinedRadiusSq)
			{										// 如果没有发生碰撞
				// w表示给定时间视野TimeHorizon内,两个智能题之间的相对速度偏移量
				const Vector3 w = relativeVelocity - invTimeHorizon * relativePosition; // 计算从截断中心到相对速度的向量
				const float wLengthSq = absSq(w);					// 计算w向量的平方长度

				const float dotProduct = w * relativePosition; // 计算w向量和相对位置的点积
				
				// 1. 如果投影在截断圆上
				// dotProduct表示相差的速度和相差的位置的点乘,要是点乘小于0,表示在靠近
				if (dotProduct < 0.0f && sqr(dotProduct) > combinedRadiusSq * wLengthSq)
				{						    
					const float wLength = std::sqrt(wLengthSq); // 计算w向量的长度
					const Vector3 unitW = w / wLength;	    // 计算w向量的单位向量

					plane.normal = unitW;					 // 设置平面的法向量
					u = (combinedRadius * invTimeHorizon - wLength) * unitW; // 计算速度调整向量
				}
				// 2. 如果投影在圆锥上
				else
				{																  
					const float a = distSq;													  // 设置系数a
					const float b = relativePosition * relativeVelocity;									  // 设置系数b
					const float c = absSq(relativeVelocity) - absSq(cross(relativePosition, relativeVelocity)) / (distSq - combinedRadiusSq); // 设置系数c
					// t表示圆锥中心线到斜线的距离 对于 半径的倍数
					const float t = (b + std::sqrt(sqr(b) - a * c)) / a;									  // 计算t值
					const Vector3 w = relativeVelocity - t * relativePosition;								  // 计算w向量
					const float wLength = abs(w);												  // 计算w向量的长度
					const Vector3 unitW = w / wLength;											  // 计算w向量的单位向量

					plane.normal = unitW;			    // 设置平面的法向量
					u = (combinedRadius * t - wLength) * unitW; // 计算速度调整向量
				}
			}
			// 3. 如果发生碰撞
			else
			{									     
				const float invTimeStep = 1.0f / sim_->timeStep_;		     // 计算时间步长的倒数
				const Vector3 w = relativeVelocity - invTimeStep * relativePosition; // 计算w向量
				const float wLength = abs(w);					     // 计算w向量的长度
				const Vector3 unitW = w / wLength;				     // 计算w向量的单位向量

				plane.normal = unitW;				      // 设置平面的法向量
				u = (combinedRadius * invTimeStep - wLength) * unitW; // 计算速度调整向量
			}
			
			// 有多少个neighbor,就有多少个orca平面
			plane.point = velocity_ + 0.5f * u; // 计算平面上的点
			orcaPlanes_.push_back(plane);	    // 将平面添加到ORCA平面列表中
		}

		const size_t planeFail = linearProgram3(orcaPlanes_, maxSpeed_, prefVelocity_, false, newVelocity_); // 计算新的速度,如果失败返回失败的平面索引

		if (planeFail < orcaPlanes_.size())
		{									 // 如果存在失败的平面
			linearProgram4(orcaPlanes_, planeFail, maxSpeed_, newVelocity_); // 调用备用算法处理失败的平面
		}
	}

3. 线性规划求解出最优速度

linearProgram几个函数实现了一套线性规划(Linear Programming, LP)求解方法,目的是在有多个平面约束(即避障条件)的情况下找到最优的速度向量,以确保多个智能体不会发生碰撞。

linearProgram1():寻找线与圆形区域的交点
linearProgram2():解决单个平面约束的最优速度
linearProgram3():求解所有平面的初步速度
linearProgram4():处理多个平面之间的约束冲突

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值