AI - Steering behaviorsII(碰撞避免,跟随)

Steering Behaviors系统中的碰撞避免,路径跟随,队长跟随

Collision Avoid

在物体前进的方向,延伸一定长度的向量进行检测。相当于物体对前方一定可使范围进行检测障碍物的碰撞
在这里插入图片描述
延伸的向量与碰撞物圆心的距离小于碰撞物的半径,则判断前进方向有阻挡物
在这里插入图片描述
我们会对所有障碍物进行碰撞检测,但是只取最近的一个做处理
在这里插入图片描述

可以延伸多条不同长度的同方向向量进行检测,以免过于靠近物体而使检测向量超过了碰撞物
在这里插入图片描述
前方视野向量检测到有障碍物的话,就会进行躲避,有障碍物圆心减去检测向量得到躲避力的方向
在这里插入图片描述
注意这里是和flee的最主要区别。avoid力相当于提前检测前方行进方向是否有障碍物,然后提前开始避开了。而flee力则是用当前自身自身的位置判断是否flee目标点,并以自身位置进行反向逃离计算
这里一个关键点是ahead的向量,如果ahead向量是个固定长度的,会有个问题就是,物体无法停在障碍物的前方。因为可能此生的检测向量一直在障碍物的范围内。如下图
在这里插入图片描述
因此ahead向量的长度要通过当前速度与最大速度的比例来设置,如果当前速度接近0,则ahead的长度也接近于0

Vec2 MoveNode::collisionAvoid(float maxSpeed) {Vec2 avoidForce = Vec2::ZERO;float dynamicLen = _velocity.getLength() / maxSpeed;//Vec2 ahead = this->getPosition() + _velocity.getNormalized() * _aheadLen;Vec2 ahead = this->getPosition() + _velocity.getNormalized() * dynamicLen;Vec2 obstaclePos = findNearestObstacle(maxSpeed);if (obstaclePos != Vec2(-1, -1)) {avoidForce = ahead - obstaclePos;avoidForce.normalize();avoidForce *= _avoidForce;}return avoidForce;
}
//找到最具威胁的阻碍物,ahead为检测向量,与所有障碍物的圆心进行距离判定
Vec2 MoveNode::findNearestObstacle(float maxSpeed) {Vec2 pos = this->getPosition();/*Vec2 ahead = pos + _velocity.getNormalized() * _aheadLen;Vec2 ahead2 = pos + _velocity.getNormalized() * _aheadLen / 2;*/float dynamicLen = _velocity.getLength() / maxSpeed;Vec2 ahead = pos + _velocity.getNormalized() * dynamicLen;Vec2 ahead2 = pos + _velocity.getNormalized() * dynamicLen / 2;Vec2 v = Vec2(-1, -1);for (auto obstacle : _obstacles) {Vec2 center = obstacle.first;float radius = obstacle.second;bool isCollision = ahead.getDistance(center) < radius || ahead2.getDistance(center) < radius;if(isCollision && (v == Vec2(-1,-1) || pos.getDistance(center) < pos.getDistance(v))) v = center;}return v;
}

效果
在这里插入图片描述

Path Following

比较简单的实现是,将路径划分多个路径点,对每个路径点进行seek
在这里插入图片描述
因为物体是带有类似惯性的,所有对每个路径点seek时,需要判定到达路径点一定范围内就算到达当前路径点,然后前往下一路径点,否则会在初始点无限循环
在这里插入图片描述
注意路径点的到达半径如果太短的话,物体由于速度过快可能会在路径点周围绕一圈,才走进了到达的范围内,才前往下一路径点
在这里插入图片描述

在这里插入图片描述

//_pathDir表示了路径点索引的方向,我们这里是抵达起始点或终点后进行反向
Vec2 MoveNode::pathFollowing() {Vec2 steering = Vec2::ZERO;if (_pathNodes.empty()) return steering;auto pathNode = _pathNodes[_pathNodeIdx];Vec2 pos = pathNode.first;float arriveRadius = pathNode.second;if (this->getPosition().getDistance(pos) <= arriveRadius) {_pathNodeIdx += _pathDir;if (_pathNodeIdx >= _pathNodes.size() || _pathNodeIdx < 0) {_pathDir *= -1;_pathNodeIdx += _pathDir;}}return seek(_pathNodes[_pathNodeIdx].first);
}

在这里插入图片描述

Leader Following

跟随一个队长的路径
队长跟随类似追捕目标,只不过追捕目标是预测目标点前进几帧后的方向进行seek,但是跟随是队长前进方向的反向一定距离进行跟随
在这里插入图片描述
如上图,求出队长速度的反向,在一定长度的位置behind,队员对behind的位置进行arrive

//_leaderBehindDist:跟随在队长背后的距离
Vec2 MoveNode::leaderFollowing() {Vec2 steering = Vec2::ZERO;if (_leader == nullptr) return steering;Vec2 tv = _leader->getVelocity() * -1;tv.normalize();tv *= _leaderBehindDist;Vec2 followPos = _leader->getPosition() + tv;steering += seek(followPos);return steering;
}

在这里插入图片描述
我们看到队员跟随在队长背后,但是此时队员都挤成了一团,因此对队员加上集群模拟的separation力
在这里插入图片描述
另一个问题是,跟随队长的队员,是不允许挡在队长前进的前方的。此时,我们给队长一个前方的视线检测向量和一个检测半径,如果队员在这个视线检测范围内的话,就要对队长进行避让evade
在这里插入图片描述

//pos是队员的坐标位置,_leaderAhead是队长视线的检测的长度,与队长速度方向求的检测向量,_leaderAheadRadius是检测的范围半径。该函数判定队员位置是否在队长前进的方向上
bool MoveNode::isInAheadArea(Vec2 pos) {Vec2 srcPos = this->getPosition();Vec2 aheadPos = _velocity.getNormalized()* _leaderAhead + srcPos;return srcPos.getDistance(pos) < _leaderAheadRadius || aheadPos.getDistance(pos) < _leaderAheadRadius;
}

evade的逻辑于pursuit类似,预测队长几帧后的前进位置,对该位置进行flee

Vec2 MoveNode::leaderFollowing() {Vec2 steering = Vec2::ZERO;if (_leader == nullptr) return steering;Vec2 tv = _leader->getVelocity() * -1;tv.normalize();tv *= _leaderBehindDist;Vec2 followPos = _leader->getPosition() + tv;//如果在队长视野前方,则预测队长行进路线进行逃离evadeif (_leader->isInAheadArea(this->getPosition())) {Vec2 leadPos = _leader->getPosition();float t = this->getPosition().getDistance(leadPos) / _dtSpeed;Vec2 fleePos = leadPos + _leader->getVelocity() * t;steering += flee(fleePos);}steering += seek(followPos);return steering;
}

在这里插入图片描述
下面是队长跟随路径移动,队员跟随队长移动的结合例子
在这里插入图片描述

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

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

相关文章

计算机体系结构----流水线技术(三)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。绝大部分资料来自----计算机系统结构教程(第二版)张晨曦等 计算机体系结构----流水线技术&#xff08;三&#xff09; 3.1 流水线的基本概念3.1.1 什么是流水线3.1.2 流水线的分类1. 部件级流水线、处理机级流…

您的计算机已被.Elbie勒索病毒感染?恢复您的数据的方法在这里!

引言&#xff1a; 在数字世界里&#xff0c;.Elbie勒索病毒如同一位隐匿的黑帮成员&#xff0c;以其狡猾而毁灭性的手段频频露面。我们将深入探讨.Elbie的狡诈行径&#xff0c;教你如何在被其加密的数据中找回丢失的珍贵文件&#xff0c;并揭示如何巧妙规避这场数字陷阱。数据…

C语言之结构体详解

C语言之结构体详解 文章目录 C语言之结构体详解1. 结构体类型的声明2. 结构体变量的创建和初始化3. 结构体的特殊声明4. 结构体的自引用结构体的自引用匿名结构体的自引用 5. 结构体内存对齐5.1 练习一5.2 练习三 6. 为什么存在内存对⻬? 1. 结构体类型的声明 struct tag {me…

MySQL电商管理系统练习题及答案

一 、表结构 用户表(user)&#xff1a;id(主键)、username、password、email、phone、age商品表(product)&#xff1a;id(主键)、name、price、stock、description订单表(order)&#xff1a;id(主键)、user_id(外键&#xff0c;关联用户表)、total_price、status、create_time…

05_属性描述符

05_属性描述符 文章目录 05_属性描述符一、属性描述符是什么&#xff1f;二、属性描述符①&#xff1a;查看属性描述②&#xff1a;设置属性描述符③&#xff1a;案例01.代码实现02.代码实现&#xff08;优化&#xff09; 一、属性描述符是什么&#xff1f; 属性描述符的结构 在…

类和对象——(3)再识对象

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 你说那里有你的梦想&#xff0c;…

MySQL官网推荐书籍

MySQL官网推荐书籍 图片有防盗链csdn转存失败。有图版传送门MySQL官网推荐书籍 高效的MySQL性能&#xff1a;Daniel Nichter的最佳实践和技术 Daniel Nichter 向您展示了如何应用直接影响 MySQL 性能的最佳实践和技术。您将学习如何通过分析查询执行、为常见 SQL 子句和表联接…

KMP基础架构

前言 Kotlin可以用来开发全栈, 我们所熟悉的各个端几乎都支持(除了鸿蒙) 而我们要开发好KMP项目需要一个好的基础架构,这样不仅代码更清晰,而且能共享更多的代码 正文 我们可以先将KMP分为前端和服务端 它们两端也能共享一些代码,比如接口声明,bean类,基础工具类等 前端和…

Go语言 值传递

官方说法&#xff0c;Go中只有值传递&#xff0c;没有引用传递 而Go语言中的一些让你觉得它是引用传递的原因&#xff0c;是因为Go语言有值类型和引用类型&#xff0c;但是它们都是值传递。 值类型 有int、float、bool、string、array、sturct等 引用类型有slice&#xff0c…

Logstash使用指南

介绍 Logstash是一个开源数据收集引擎&#xff0c;具有实时管道功能。它可以动态地将来自不同数据源的数据统一起来&#xff0c;并将数据标准化到你所选择的目的地。尽管Logstash的早期目标是搜集日志&#xff0c;现在它的功能已完全不只于此。任何事件类型都可以加入分析&…

docker (镜像分层、阿里云镜像推送/拉去)-day02

一、镜像概念 Docker 镜像是 Docker 容器的基础&#xff0c;它提供了一种可重复使用的、跨平台的部署方式&#xff0c;使得应用程序的部署和运行变得简单和高效。 把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),打包好…

C语言练习记录(蓝桥杯练习)(小蓝数点)

目录 小蓝数点 第一题程序的输出结果是&#xff1f;: 第二题下面代码的执行结果是什么&#xff1f;: 第三题下面代码的执行结果是什么&#xff1f;: 第四题关于关系操作符说法错误的是&#xff1f;: 第五题对于下面代码段&#xff0c;y的值为&#xff1f; 第六题sum 21 …

informer辅助笔记:exp/exp_informer.py

0 导入库 from data.data_loader import Dataset_ETT_hour, Dataset_ETT_minute, Dataset_Custom, Dataset_Pred from exp.exp_basic import Exp_Basic from models.model import Informer, InformerStackfrom utils.tools import EarlyStopping, adjust_learning_rate from u…

huggingface - pipeline - translate 记录

文章目录 #!/usr/bin/env python # -*- encoding: utf-8 -*-import os ,sys from transformers import pipelinemodel_checkpoint "Helsinki-NLP/opus-mt-zh-en" translator pipeline("translation", modelmodel_checkpoint)def translate_arr(arr): r…

Java 数据结构篇-用链表、数组实现栈

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 栈的说明 2.0 用链表来实现栈 2.1 实现栈 - 入栈方法&#xff08;push&#xff09; 2.2 实现栈 - 出栈&#xff08;pop&#xff09; 2.3 实现栈 - 查看栈顶元素…

mybatis 实现批量更新的三种方式

注&#xff1a;Mybatis实现批量更新有三种方式&#xff0c;分别是使用foreach标签、使用SQL的case when语句和使用动态SQL的choose语句。具体实现方法如下&#xff1a; 1&#xff1a;使用foreach标签 <update id"batchUpdate" parameterType"java.util.Lis…

C 标准库 <errno.h>与 <float.h>

C 标准库 <errno.h> C 标准库的 errno.h 头文件定义了整数变量 errno&#xff0c;它是通过系统调用设置的&#xff0c;在错误事件中的某些库函数表明了什么发生了错误。该宏扩展为类型为 int 的可更改的左值&#xff0c;因此它可以被一个程序读取和修改。 在程序启动时…

国产linux单用户模式破解无密码登陆 (麒麟系统用户登录密码遗忘解决办法)

笔者手里有一批国产linu系统&#xff0c;目前开始用在日常的工作生产环境中&#xff0c;我这个老程序猿勉为其难的充当运维的或网管的角色。 国产linux系统常见的为麒麟Linux&#xff0c;统信UOS等&#xff0c;基本都是基于debian再开发的linux。 问题描述&#xff1a; 因为…

基于AT89C51单片机的倒数计时器设计

1&#xff0e;设计任务 利用AT89C51单片机为核心控制元件,设计一个简易的数字电压表&#xff0c;设计的系统实用性强、操作简单&#xff0c;实现了智能化、数字化。 本设计采用单片机为主控芯片&#xff0c;结合周边电路组成LED彩灯的闪烁控制系统器&#xff0c;用来控制红色…

用于缓存一些固定名称的小组件

项目中&#xff0c;用于缓存姓名、地名、单位名称等一些较固定名称的id-name小组件。用于减少一些表的关连操作和冗余字段。优化代码结构。扩展也方便&#xff0c;写不同的枚举就行了。 具体用法&#xff1a; {NameCacheUser.USER.getName(userId);NameCacheUser.ACCOUNT.getN…