【openframework】实时路径规划(RTRRTstar算法)

news2024/11/29 9:43:02

4bc5dece0931c533cc79379d4075c346.jpeg

程序框架

视频演示

实时RRT-star算法介绍

实时RRT-star算法是一种基于采样的运动规划算法,它可以在有限的时间内找到一条渐进最优的路径。实时RRT-star算法是在RRT-star算法的基础上进行了改进,主要有两个方面:

- 实时更新起始点。实时RRT-star算法不是从固定的起始点开始搜索,而是每次迭代都将当前的位置作为起始点,这样可以适应动态的环境和目标。

- 实时调整采样区域。实时RRT-star算法不是在整个搜索空间中随机采样,而是根据当前的路径长度和目标位置,计算一个椭圆形的采样区域,只在该区域内进行采样,这样可以提高采样的效率和质量。

实时RRT-star算法的流程如下:

1. 初始化:将当前位置作为起始点,将目标位置作为终点,将起始点加入搜索树中,设置最大迭代次数和时间限制。

2. 迭代:重复以下步骤,直到达到最大迭代次数或时间限制。

    - 采样:根据当前的路径长度和目标位置,计算一个椭圆形的采样区域,从该区域内随机选择一个点作为采样点。

    - 扩展:在搜索树中找到离采样点最近的节点作为基准节点,从基准节点出发以一定步长朝着采样点进行延伸,延伸线的终点所在的位置被当做有效节点加入搜索树中。

    - 重布线:在搜索树中找到有效节点附近的一定范围内的所有节点,对每个节点检查是否可以通过有效节点改善其路径长度,如果可以,则将有效节点作为其父节点,并更新其路径长度。

    - 检查:检查是否存在从起始点到终点的可行路径,如果存在,则更新当前的路径长度和采样区域。

3. 输出:输出当前找到的最优路径或者提示无法找到可行路径。

实时RRT-star算法的优点是:

- 可以在有限的时间内找到一条渐进最优的路径,适用于时间敏感的任务。

- 可以实时更新起始点和采样区域,适应动态的环境和目标。

- 可以利用先验知识指导采样过程,提高采样的效率和质量。

实时RRT-star算法的缺点是:

- 需要计算椭圆形的采样区域,增加了计算量和复杂度。

- 需要存储搜索树中的所有节点和路径长度,增加了空间开销。

- 不能保证找到全局最优的路径,只能保证渐进最优。

实时RRT-star算法是一种有前途的运动规划算法,它结合了RRT-star算法和informed RRT-star算法的优点,同时进行了一些创新性的改进。实时RRT-star算法在多种场景下都有很好的表现,例如无人驾驶、机器人导航、游戏角色控制等。实时RRT-star算法还有很多可以改进和扩展的地方,例如采样区域的形状、采样点的分布、重布线的策略等,值得进一步的研究和探索。

ofApp主程序:

#include "ofApp.h"


//--------------------------------------------------------------
void ofApp::setup() {
#ifdef randomSeed
  ofSeedRandom(randomSeed);//如果定义了 randomSeed,则使用它来设置随机数种子,以便在每次运行时获得可重复的随机结果。
#endif // randomSeed
#ifdef CLK
  auto start = std::chrono::steady_clock::now();
#endif // DEBUG
  ofSetVerticalSync(true);//启用垂直同步,以匹配显示器的刷新率。
  ofSetFrameRate(30);//设置帧率为30帧/秒。
  ofSetWindowTitle("Dynamic-obstacles");//设置窗口标题为 "Dynamic-obstacles"。
  ofBackground(200,200,200,200);//设置窗口背景颜色为浅灰色。
  myfont.loadFont("Roboto-Regular.ttf", 10);//加载字体文件 "Roboto-Regular.ttf" 并设置字体大小为10
  //map = new Enviroment();
  //car.setup();
  //接下来的几段代码是创建迷宫墙壁的示例
  ofVec2f w;
  w.set(ofGetWidth() / 2, 0);
  wall = new maze(w);//通过创建 maze 类的对象并将其添加到 obst 向量中,来创建障碍物。
  obstacles *ob = wall;
  obst.push_back(ob);


  w.set(ofGetWidth() / 2, 0.6*ofGetHeight());
  wall = new maze(w);
  ob = wall;
  obst.push_back(ob);


  w.set(ofGetWidth() / 4, 0.4*ofGetHeight());
  wall = new maze(w, 60, 0.2*ofGetHeight());
  ob = wall;
  obst.push_back(ob);


  w.set(0.75*ofGetWidth(), 0.4*ofGetHeight());
  wall = new maze(w, 60, 0.2*ofGetHeight());
  ob = wall;
  obst.push_back(ob);
  //使用一个循环创建了一些障碍物对象,并将它们添加到 obst 向量中
  for (unsigned int i = 0; i < numberOfobst; i++)
  {
    //obstacles *ob = new obstacles(); //固定障碍物
    OBST = new movingObst();//移动障碍物
    obstacles *ob = OBST;//移动障碍物
    obst.push_back(ob);
  }
  //创建了一个 movingObst 对象,并将其添加到 obst 向量中
  OBST = new movingObst();//移动的对象
  ob = OBST;
  obst.push_back(ob);


  cout << "Obst size: " << obst.size() << endl; //输出 obst 的大小


#ifdef randomSeed //根据是否定义了 randomSeed 输出随机种子的值
  std::cout << "RandomSeed:" << randomSeed << endl;
#endif


#ifdef CLK
  auto end = std::chrono::steady_clock::now();
  std::cout << std::endl << "Setup:" << std::chrono::duration<double, std::milli>(end - start).count() << " ms" << std::endl;
#endif // DEBUG
}


//一些更新操作--------------------------------------------------------------
void ofApp::update(){
  if (!updateFlag) return;//如果 updateFlag 为假,则函数直接返回
#ifdef CLK
  auto start = std::chrono::steady_clock::now();
#endif // DEBUG


#ifdef automatic //如果定义了 automatic,则遍历 obst 向量中的每个障碍物对象,并调用其 move() 函数,将 obst 向量作为参数传递。
  for (auto i : obst) {
    i->move(obst);
    //cout << "location: " << i->loc() << "Radius: " << i->rad() << endl;
    //cout << i.getX() << "  " << i.getY() << endl;
  }
#endif // automatic
  //如果 map 不为空指针,则调用 map 对象的 update() 函数,并将 car 和 obst 作为参数传递。
  if (map!= NULL) map->update(car,obst);
#ifdef CLK
  auto end = std::chrono::steady_clock::now();
  /*std::cout << std::endl << "Update:" << std::chrono::duration<double, std::milli>(end - start).count() << " ms" << std::endl;*/
  updateTime = std::chrono::duration<double, std::milli>(end - start).count();//计算更新时间并存储在 updateTime 变量中
#endif // DEBUG
}


//绘制操作--------------------------------------------------------------
void ofApp::draw(){
#ifdef CLK
  auto start = std::chrono::steady_clock::now();
#endif // DEBUG
  //遍历 obst 向量中的每个障碍物对象,并调用其 render() 函数进行绘制
  for (auto i : obst) {
    i->render();
  }
  if (map != NULL) map->render();//如果 map 不为空指针,则调用 map 对象的 render() 函数进行绘制。
  if (car!= NULL) car->render();//如果 car 不为空指针,则调用 car 对象的 render() 函数进行绘制。
  //创建一个用于存储帧率字符串的字符数组 fpsStr,并将帧率信息存储在其中。然后使用 myfont 对象绘制该字符串在窗口的指定位置。
  char fpsStr[255]; // an array of chars
  ofSetColor({ 255,0,0 });
  sprintf(fpsStr, "Frame rate: %d", int(ofGetFrameRate()));
  myfont.drawString(fpsStr, ofGetWindowWidth() - 100, ofGetWindowHeight() - 25);
  //如果 map 不为空指针,则创建一个用于存储节点数字符串的字符数组 numNode,并将节点数信息存储在其中。然后 字符串在窗口的指定位置使用 myfont 对象绘制该。
  if (map != NULL) {
    char numNode[255];
    sprintf(numNode, "Number of nodes: %d", int(map->numofnode()));
    myfont.drawString(numNode, ofGetWindowWidth() - 140, ofGetWindowHeight() - 10);
  }


#ifdef CLK //如果定义了 CLK,则计算绘制时间并存储在 drawTime 变量中,然后绘制更新时间和绘制时间的字符串。
  auto end = std::chrono::steady_clock::now();
  /*std::cout << std::endl << "Draw:" << std::chrono::duration<double, std::milli>(end - start).count() << " ms" << std::endl;*/
  drawTime = std::chrono::duration<double, std::milli>(end - start).count();


  char time[255];
  sprintf(time, "Update rate: %f", updateTime);
  myfont.drawString(time, ofGetWindowWidth() - 140, ofGetWindowHeight() - 755);
  sprintf(time, "Draw rate: %f", drawTime);
  myfont.drawString(time, ofGetWindowWidth() - 140, ofGetWindowHeight() - 740);


#endif // DEBUG
}


//根据按键的值执行相应的操作--------------------------------------------------------------
void ofApp::keyPressed(int key){
  if (key == 'p')
  {//如果按下的键是 'p',则切换 updateFlag 变量的值
    updateFlag = !updateFlag;
  }
  else if(key=='g')
  {//如果按下的键是 'g',则切换 map 对象的 grid 变量的值。
    map->grid = !map->grid;
  }
  else if (key == 'x') 
  { //如果按下的键是 'x',则截取屏幕的图像并保存为 "screenshot.png"。
    ofImage img;
    img.grabScreen(0, 0, ofGetWidth(), ofGetHeight());
    img.save("screenshot.png");
  }
#ifdef manual //如果定义了 manual,则调用 OBST 对象的 move() 函数,并将按下的键作为参数传递。
  OBST->move(key);
#endif // manual


}


//鼠标按下的位置和按钮执行相应的操作--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
  ofVec2f loc;//创建一个 ofVec2f 对象 loc,
  loc.set(x, y);//并将鼠标按下的位置设置为其坐标。
  if (button == 0) {
    if (car != NULL) {
      //如果按下的按钮是鼠标左键(按钮值为0),并且 car 不为空指针,
      //则调用 map 对象的 targetSet() 函数,将 loc 作为参数传递。
      map->targetSet(loc);//设定目标位置
    }
  }
  else if (button == 2) {
    //如果按下的按钮是鼠标右键(按钮值为2),则创建一个 Robot 对象和一个 Enviroment 对象,并将 loc 作为参数传递给它们。
    car = new Robot(loc);
    map = new Enviroment(car->getLocation());//重建环境
  }
  else
  {


  }
}

The End

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

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

相关文章

那些漏洞挖掘高手都是怎么挖漏洞的?

前言 说到安全就不能不说漏洞&#xff0c;而说到漏洞就不可避免地会说到三座大山&#xff1a; 漏洞分析 漏洞利用 漏洞挖掘 从个人的感觉上来看&#xff0c;这三者尽管通常水乳交融、相互依赖&#xff0c;但难度是不尽相同的。本文就这三者分别谈谈自己的经验和想法。 漏洞分析…

Mac图片批处理工具

PhotoMill X是一款强大的图像处理软件&#xff0c;它可以帮助用户快速地对照片进行编辑、调整和转换。它支持在单个或批量模式下处理大量的图像文件&#xff0c;并具有直观的用户界面和易于使用的工具。 PhotoMill X具有广泛的编辑功能&#xff0c;包括裁剪、缩放、旋转、调整明…

记录基于Vue.js的Tree组件_Liquor Tree

酒树 (Liquor Tree) A Vue tree component that allows you to present hierarchically organized data in a nice and logical manner. Vue 树组件&#xff0c;可让您以美观和逻辑的方式呈现层次结构的数据。 supports mobile, and has a variety of response events. Flex…

软考A计划-电子商务设计师-模拟试题卷三

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

springboot+websocket客服聊天

续&#xff1a;spring boot 完整后端接口案例_cc&的博客-CSDN博客 后台代码 1.在pom.xml中添加spring-boot-starter-websocket <!--WebSocket--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter…

浅谈数明深力科隔离驱动器SLMi8235BD 车载充电器(OBC)方案

数明深力科SLMi823x系列SLMi8235BD隔离驱动技术优势&#xff1a;具有高性能、高性价比、高可靠性的产品特性&#xff0c;应用覆盖UPS、充电桩、服务器电源、通信电源、新能源汽车动力总成系统的车载 OBC 领域。通过CQC认证的。 车载充电器&#xff08;OBC&#xff09;是电动汽…

在线电子书创建:MkDocs + Github + ReadTheDocs

MkDocs是一个静态站点生成器&#xff0c;可用于构建项目文档。文档文件使用Markdown语法编写&#xff0c;本文记录如何使用MkDocs生成项目文档&#xff0c;并部署到Read the Docs上。 目录 安装mkdocs搭建文档项目创建项目启动项目编写文档Markdown语法站内链接图片 文档结构 配…

聚观早报 | 苹果收购AR头显初创公司Mira;抖音将尝试自营电商

今日要闻&#xff1a;苹果收购AR头显初创公司Mira&#xff1b;抖音将尝试自营电商&#xff1b;特斯拉股价实现九连涨&#xff1b;《黑镜》主创曾试用ChatGPT写剧本&#xff1b;携程集团发布2023Q1财报 苹果收购AR头显初创公司Mira 6 月 7 日消息&#xff0c;据 The Verge 报道…

2023免费电脑录视频软件Camtasia

Camtasia 2023是专业又好用的录屏软件&#xff0c;既可以用来录视频、ppt、直播课程等&#xff0c;也能够处理视频&#xff0c;添加各种效果&#xff0c;制作出更加满意的视频作品。Camtasia凭借愈发强大的功能收获了一大批忠实用户和如潮好评&#xff0c;已成为屏幕录制的必备…

6.16 @ 广州丨相约泛娱乐出海论坛,探寻市场突围的核心要义

1979 年&#xff0c;“出国办企业”第一次被有关部门提出&#xff0c;开启了中国企业对外投资的积极探索与尝试。经过 40 多年的耕耘&#xff0c;不少出海品牌已经站稳了脚跟&#xff0c;品牌影响力与日俱增&#xff0c;甚至在部分核心细分赛道上&#xff0c;中国企业凸显出了明…

TiDB 7.1 LTS 发版:为关键业务提供业务稳定性和多租户场景支持

近日&#xff0c;企业级开源分布式数据库厂商 PingCAP 正式发布 TiDB 7.1 版本&#xff0c;这也是 2023 年度发布的首个 LTS&#xff08;Long Term Support&#xff09; 版本&#xff0c;汇集了来自 20 个真实场景带来的功能增强&#xff0c;累计优化和修复 140 功能&#xff0…

easyui5

1.1准备工作. 今天我们的主要任务是完成分页功能&#xff1b; 导入数据表 t_book&#xff0c;数据文件在课件&#xff1b; 介绍拼音字段&#xff0c;拼音工具类&#xff0c;拼音jar包&#xff1b; 模糊查询还要实现拼音模糊查询&#xff0c;如&#xff1a;百度输入拼音也可以…

飞凌嵌入式AM62x系列核心板配置新增,单核/双核/四核随心选

新时代&#xff0c;工业、电力、交通、医疗等众多行业纷纷从信息化向着智能化转型&#xff0c;这就对主控的综合性能提出了全新的要求。在这样的背景下 TI AM62x Sitara™处理器应运而生&#xff0c;为AIoT时代带来了新的突破可能。作为TI官方合作伙伴&#xff0c;飞凌嵌入式于…

RabbitMQ - 发布确认高级

RabbitMQ - 发布确认高级 发布确认 springboot 版本回退消息备份交换机 在生产环境中由于一些不明原因&#xff0c;导致 RabbitMQ 重启&#xff0c;在 RabbitMQ 重启期间生产者消息投递失败&#xff0c; 导致消息丢失&#xff0c;需要手动处理和恢复。于是&#xff0c;我们开始…

Steemit 会颠覆 Quora/知乎 甚至 Facebook 吗?

Steemit是基于区块链技术的社交媒体平台&#xff0c;其独特的激励机制吸引了众多用户。然而&#xff0c;是否能够真正颠覆Quora、知乎甚至Facebook这些已经成为社交巨头的平台&#xff0c;仍然存在着许多未知因素。本文将探讨Steemit的优势和挑战&#xff0c;以及其在社交领域中…

数据分析第15课pandas和matplotlib实战

01实战:911 导入: 读取数据: 转换类型:

java html导出添加空行和空格

情景&#xff1a; 要求导出签批单&#xff1a; 格式如下&#xff0c; 要获取“主办处室负责人”和“相关处室会签”环节的处理意见、处理人员和处理日期进行替换&#xff0c;导出word文档。 处理&#xff1a; 主要是如何拼接内容&#xff1f; 方法一&#xff1a; 导出word&…

爬虫如何发送 HTTP 请求

爬虫可以使用 Python 中的 requests 库来发送 HTTP 请求。requests 库提供了简单易用的 API&#xff0c;可以方便地发送 GET、POST 等请求&#xff0c;并且支持设置请求头、请求参数、代理等功能。 以下是一个使用 requests 库发送 GET 请求的示例代码&#xff1a; import re…

国产触控笔哪个牌子好?第三方电容笔推荐

对于那些把iPad当做学习工具的人来说&#xff0c;这已经成为了他们生活中不可缺少的一部分。但没有人买得起苹果原装电容笔&#xff0c;因为苹果电容笔的售价太贵了。因此&#xff0c;最好还是用一支普通的电容笔。我是个一个苹果粉&#xff0c;同时也是个数字发烧友&#xff0…

十年之约 记账表格(会员专享)

* * * 原创&#xff1a;刘教链 * * * 6号&#xff0c;教链发起了十年之约加密投资实证计划。 很多读者、会员纷纷同行。 有朋友问及教链所用记账表格。可根据文章中的介绍自制。为方便会员&#xff0c;教链已将该表格上传至刘教链的加密投资星球&#xff0c;供下载。 另外&…