ORCA-3D避障算法解析

news2024/11/18 12:18:08

二维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():处理多个平面之间的约束冲突

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2132989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++---string类常见接口

介绍 string类详情>>>https://cplusplus.com/reference/string/string/?kwstring 1. string是表示字符串的字符串类&#xff08;感觉就像一个动态的字符数组&#xff09; 2. 该类的接口与常规容器的接口基本相同&#xff0c;再添加了一些专门用来操作string的常规操作…

9月19日与MongoDB相约2024云栖大会

2024云栖大会来了&#xff01; 9月19日至9月21日 在杭州云栖小镇召开 汇集全球最新云计算和AI硬科技 MongoDB互动展区 2号馆2-8展区 MongoDB技术演讲 9月20日 分论坛&#xff1a;D2-5 2024云栖大会将设置 人工智能、计算、前沿应用三大主题馆&#xff0c; 围绕云计算与AI&#…

面试官:说说停止线程池的执行流程?

对于我们使用的线程池 ThreadPoolExecutor 来说&#xff0c;停止线程池的方法有以下两个&#xff1a; shutdown()&#xff1a;优雅的关闭线程池&#xff0c;即不再接受新任务&#xff0c;但会等待已提交任务&#xff08;包括正在执行的任务和在队列中等待的任务&#xff09;执行…

【C++高阶】解锁C++的深层魅力——探索特殊类的奥秘

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C 类型转换 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀C特殊类 &#x1f4d2;1. 不能被拷贝…

外贸网站建设该怎么做

外贸网站已成为企业拓展国际市场、促进贸易合作的重要工具。然而&#xff0c;要想在竞争激烈的国际贸易舞台上脱颖而出&#xff0c;就需要一套科学有效的外贸网站建设方案。本文将为您介绍成功打造外贸网站的关键步骤&#xff0c;助您在数字化时代实现更广阔的国际商机。 第一步…

嗨! 大叔,什么时候退休?

先祝各位中秋快乐&#xff01;&#xff01;&#xff01;接下我们吃瓜。娱乐至上&#xff01; 纯属娱乐&#xff0c;没验证是否正确&#xff01; 2024年9月13日第十四届全国人民代表大会常务委员会第十一次会议通过关于实施渐进式延迟法定退休年龄的决定,我将规则给ChatGPT&am…

如何绕过Cloudflare的403 禁止错误?

Cloudflare 的 403 错误与常规 HTTP 403 错误代码并无二致&#xff0c;都表示禁止访问。这通常意味着你没有权限访问该文档。然而&#xff0c;在使用 Cloudflare 的情况下&#xff0c;当你尝试网页抓取时&#xff0c;可能会遇到这种情况&#xff0c;因为它可能表明你的 IP 地址…

【练习10】链表相加

链接&#xff1a;链表相加(二)_牛客题霸_牛客网 (nowcoder.com) 分析&#xff1a; 算法原理是逆序高精度算法 逆序的原因是为了实现从低位&#xff08;个位&#xff09;开始相加。 public class Solution {//逆序链表public ListNode reverse(ListNode head){ListNode newHead …

尤雨溪推荐的拖拽插件,支持Vue2/Vue3 VueDraggablePlus

大家好,我是「前端实验室」爱分享的了不起~ 今天在网上看到尤雨溪推荐的这款拖拽组件,试了一下非常不错,这里推荐给大家。 说到拖拽工具库,非大名鼎鼎的的 Sortablejs 莫属。它是前端领域比较知名的,且功能强大的工具。但我们直接使用Sortablejs的情况很少,一般都是使用…

java项目之基于Spring Boot智能无人仓库管理源码(springboot+vue)

项目简介 智能无人仓库管理实现了以下功能&#xff1a; 基于Spring Boot智能无人仓库管理的主要使用者分为&#xff1a; 管理员的功能有&#xff1a;员工信息的查询管理&#xff0c;可以删除员工信息、修改员工信息、新增员工信息 &#x1f495;&#x1f495;作者&#xff1a…

容器镜像同步工具image-migrator

1 概述 image-migrator是一个用于容器镜像同步的可执行二进制命令行工具&#xff08;不依赖于docker命令&#xff09;&#xff0c;能够自动将基于Docker Registry v2镜像仓库&#xff08;registry、云厂商容器镜像服务、docker hub、Quay、Harbor &#xff09;中的镜像迁移到基…

MADE A PIE 之动态树形图

MADE A PIE api地址 他那个api里的代码可以直接拿过来用&#xff0c;只是他没有写怎么使用 使用时我发现如果节点太多会导致节点名称重叠&#xff0c;所以我在他这个基础之上加了一个放大缩小和随意拖动&#xff08;dragstart&#xff0c;dragend&#xff0c;flTop&#xff0…

收银员权限-收银系统源码

收银系统对于门店来说是收银员每天日常高频使用的软件工具&#xff0c;但很多门店老板不想给收银员开放很多权限&#xff0c;如商品改价、订单打折、会员充值、订单退款等都需要门店给其开通权限或者有权限码才能操作。 1. 收银员交接班 收银系统要支持交接班&#xff0c;收银…

OJ题——迷宫问题

&#x1f36c;个人主页&#xff1a;Yanni.— &#x1f308;数据结构&#xff1a;Data Structure.​​​​​​ &#x1f382;C语言笔记&#xff1a;C Language Notes &#x1f3c0;OJ题分享&#xff1a; Topic Sharing 前言&#xff1a; 在笔试或者竞赛的过程中&#xff0c;经…

剖析 MySQL 数据库连接池(C++版)

目录 ☀️0. 前言 &#x1f324;️1. 数据库连接池概述 ⛅1.1 服务器与数据库交互 ⛅1.2 MySQL 数据库网络模型 ⛅1.3 MySQL 连接驱动安装 ⛅1.4 同步&#xff08;synchronous&#xff09;连接池与异步&#xff08;asynchronous&#xff09;连接池 ⛅1.5 同步连接池和异…

Spring 循环依赖原理及解决方案

一、什么是循环依赖 循环依赖指的是一个实例或多个实例存在相互依赖的关系&#xff08;类之间循环嵌套引用&#xff09;。 举例&#xff1a; Component public class AService {// A中注入了BAutowiredprivate BService bService; }Component public class BService {// B中也…

通信工程学习:什么是PC永久连接、SPC软永久连接

一、PC永久连接 PC&#xff08;Permanent Connection&#xff09;永久连接是一种由网管系统通过网管协议建立的长期稳定的连接方式。在ASON&#xff08;自动交换光网络&#xff09;中&#xff0c;PC永久连接沿袭了传统光网络的连接建立形式&#xff0c;其特点主要包括&#xff…

【Canvas与密铺】正六边形、正方形和正三角形的密铺

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>正六边形正方形和正三角形的密铺1920x1080</title><style t…

SpringSecurity原理解析(四):SpringSecurity初始化过程

1、对 SpringSecurity初始化时的几个疑问 通过对前边一个请求流转的分析&#xff0c;我们知道一个请求要想到达服务端Servlet需要经过n多个 拦截器处理&#xff0c;请求处理流程如下所示&#xff1a; 对于一个请求到来后会通过FilterChainProxy来匹配一个对应的过滤器链来处理该…