运动规划算法实现-基于OMPL库_henry.zhu51的博客-程序员秘密

技术标签: 规划算法  OMPL  规划  

概述

本文主要介绍如何使用ompl库实现自己的随机采样规划算法。由于OMPL库已经封装了功能完善的采样算法、最临近节点搜索算法等。基于这些算法接口,可以很容易地实现各种改进型的随机搜索树算法。

限制要求

基于OMPL库实现新的运动规划算法非常简单,只有两个要求:

  1. 新的算法的类需公有继承ompl::base::Planner
  2. 从继承的ompl::base::Planner类中,实现solve()函数

可选特性

除了上述严格要求之外,为了便于集成,还有一些可集成的函数和应遵循的做法。它们不作要求,但为了简单和一致强烈建议包含下述特性

配置规划器属性

更新ompl::base::Planner的成员变量ompl::base::PlannerSpecs,该结构体表示规划器是否包含相关特性。如果在新的规划器中更新这些属性,对于用户来讲,可以更好的使用该规划器。

重载setup()函数

为了执行任何一次性的方法,可以重载函数setup()

注意:setup()方法要确保只能调用一次,且不能每次使用solve()前调用它。

更新问题定义

当在solve()函数中找到一个可行路径,使用ompl::base::ProblemDefinition中的addSolutionPath成员函数,将有效路径添加到相应的实例化对象中。其中ompl::base::ProblemDefinition也是ompl::base::Planner的子类。

返回规划状态

在执行完solve()函数后,需通过ompl::base::PlannerStatus返回丰富的状态值。

配置停止条件

应该将ompl::base::PlannerTerminationCondition参数递给solve()函数,且当给定条件评定为真时,solve()函数应该尽可能快的返回。

反复规划

重复调用solve()函数,不应从头开始新的规划过程,而应从先前中断的地方继续进行搜索。

clear()函数

提供ompl::base::Planner::clear()函数的实现,这个函数应该释放所有由规划器申请的内存空间并将规划器恢复到可以再次调用ompl::base::Planner::solve()函数的状态,这样就无需将先前调用的信息传递给solve()函数。如果有必要的话,clear()函数可以设置ompl::base::Planner::setup_参数为false,以通知solve函数,setup()函数需要再次调用。

规划数据格式

提供一个ompl::bas::Planner::getPlannerData()的实例,其可以将内部的数据结构转化为ompl::base::PlannerData的图形化实现。因为它允许用户检查数据结构,所以该数据格式对调试特别有用。

新规划器的模板

#include <ompl/base/Planner.h>
 
// often useful headers:
#include <ompl/util/RandomNumbers.h>
#include <ompl/tools/config/SelfConfig.h>
 
namespace ompl
{
    
    class myNewPlanner : public base::Planner
    {
    
    public:
 
        myNewPlanner(const base::SpaceInformationPtr &si) : base::Planner(si, "the planner's name")
        {
    
            // 规划器的规格 (ompl::base::PlannerSpecs)
            specs_.approximateSolutions = ...;
            specs_.recognizedGoal = ...;
            ...
        }
 
        virtual ~myNewPlanner(void)
        {
    
            // 释放所有分配的内存空间
        }
 
        virtual base::PlannerStatus solve(const base::PlannerTerminationCondition &ptc)
        {
    
            // 确保规划器配置正确;ompl::base::Planner::checkValidity确保至少一个输入状态和一个ompl::base::Goal对象
            checkValidity();
 
            // 从ompl::base::ProblemDefinition实例化成员(pdef_)中,获取一个目标句柄
            base::Goal *goal = pdef_->getGoal().get();
 
            // 通过PlannerInputStates(pis_)协助,获取输入状态
            while (const base::State *st = pis_.nextStart())
            {
    
                // st将包含一个开始状态。通常这个状态将会被克隆并插入到规划器的数据结构中
            }
 
            // 如果需要,采样状态从目标区域获得
            const base::State *st = pis_.nextGoal(ptc);
            // 或者如果可行的话,采样一个新的目标状态
            const base::State *st = pis_.nextGoal();
 
            // 定期检查ptc()函数是否返回真,如果返回真,终止规划
            while (ptc() == false)
            {
    
                // 规划从这儿开始
 
                // 根据需要,调用SpaceInformation的子程序,例如
                // 1、si_->allocStateSampler() 函数用于采样;
                // 2、si_->checkMotion(state1, state2) 函数用于状态检测
 
 				// 使用一个目标点去评估一个采样状态是否满足目标要求
                // use the Goal pointer to evaluate whether a sampled state satisfies the goal requirements
 
                // 使用log宏用于信息传递,例如logInfo("Planner found a solution!");
            }
 
            // When a solution path is computed, save it here
            // 当计算出一个可行路径的解,将它保存这儿
            pdef_->addSolutionPath(...);
 
            // Return a value from the PlannerStatus enumeration.
            // See ompl::base::PlannerStatus for the possible return values
            // 从PlannerStatus枚举中,返回一个值
            // 参照ompl::base::PlannerStatus获取可行的返回值
            return base::PlannerStatus::EXACT_SOLUTION;
        }
 
        virtual void clear(void)
        {
    
            Planner::clear();
            // clear the data structures here
        }
 
        // optional, if additional setup/configuration is needed, the setup() method can be implemented
        virtual void setup(void)
        {
    
            Planner::setup();
 
            // perhaps attempt some auto-configuration
            SelfConfig sc(si_, getName());
            sc.configure...
        }
 
        virtual void getPlannerData(base::PlannerData &data) const
        {
    
            // fill data with the states and edges that were created
            // in the exploration data structure
            // perhaps also fill control::PlannerData
        }
 
    };
}

参考

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zghforever/article/details/107673706

智能推荐

实现简单动态自动匹配输入的内容_动态输入匹配怎么做_AC_XXZ的博客-程序员秘密

用这两个控件分别实现这两个:package com.example.autocomplete;import android.app.Activity;import android.os.Bundle;import android.util.Log;import andr

Makefile.am文件详解_u012903992的博客-程序员秘密

原文:https://blog.csdn.net/u013485792/article/details/51355668Makefile.am是一种比Makefile更高层次的编译规则,可以和configure.in文件一起通过调用automake命令,生成Makefile.in文件,再调用./configure的时候,就将Makefile.in文件自动生成Makefile文件了。所以Makefile.am文件是比Makefile文件更高的抽象。下面我根据自己的工作中的一些应用,来讨论Makefil

C# 实现软件授权码的功能_private system.windows.forms.textbox textbox2_任玉腾的博客-程序员秘密

对于一个商业软件来说,授权码这个功能必不可少。我这里采用CPU序列号加硬盘标识来判断是否授权。完整代码如下:using Microsoft.Win32;using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;us...

51nod-1119 机器人走方格 V2_z岁月无声的博客-程序员秘密

 1119 机器人走方格 V2 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。Input第1行,2个数M,N,中间用空格隔开。(2 &amp;lt;= m,n &amp;lt;= 100000...

LIS (最长上升字序列) nlgn 解法_wodasini的博客-程序员秘密

LIS, 一道比较经典的动态规划题目。对于长为n的序列 F[n] = max{F[k] + 1,F[n] | if arr[k] 时间复杂度 O(N^2) 线性空间。最近看到网上的一种 nlgn的解法,深受启发:思路是这样的:        令一个数组 pos[x] 来表示上升序列中第i个数字最小是多少。         从 arr[i] ~arr[n] 遍

Linux 编写configure.ac和Makefile.am示例_qq_38781075的博客-程序员秘密

我们知道configure.ac可以生成configure文件,而Makefile.am可以生成Makefile,之所以这么做就是为了适应不同的环境需求我已经写好了一个示例,目录结构如下我想在src的文件夹编译一个静态库,叫libfoo.a,基于c.c、d.c、c.h、d.h生成我想用a.c编译一个程序叫做test,并引用了上面的 libfoo.ac文件代码(不是很重要)configure.acMakefile.am (外层)src/Makefile.am前提假设大家...

随便推点

三星android 8.0的变化,三星关于Android 8.0更新时间表出炉:Note 8本月更新_地理狗的博客-程序员秘密

上月,相信三星S8系列的用户已经先后收到Android 8.0的更新推送。那么,三星Note8的Android 8.0什么时候能跟上呢?其实,三星Note8的Android 8.0已经在计划中了。据外媒消息显示,三星土耳其方面已经在其官网公布了三星计划更新Android 8.0正式版的机型的具体推送时间,其中就包括三星Note8、S7、S7+等机型可获得升级。从三星土耳其官方网站上可以看到,最先吃...

STM32 USB 学习_stm32 usb拔出_yhl_sophia的博客-程序员秘密

USB硬件接口1、Type —— Type A(普通PC端)、Type B(USB设备的接口)、Type C(属于USB3.0)2、Mini —— Mini A、Mini B(数码相机、移动硬盘等移动设备)3、 Micro —— Micro A、MicroB(手机等移动设备),属于USB2.0USB模式1、USB HOST模式2、USB OTG U...

洛谷P1455 搭配购买_denge2160的博客-程序员秘密

1 //并查集+01背包 2 //用并查集把几件物品合为一件 3 #include&lt;bits/stdc++.h&gt; 4 using namespace std; 5 const int maxn=10005; 6 const int maxv=10005; 7 int n,m,v_tot,tot,v[maxn],w[maxn],dp[maxv];...

视频基本知识_Destihang的博客-程序员秘密

一个序列的第一个图像叫做IDR图像(立即刷新图像)。只要显示屏幕分辨率>=1280*720即可分为HD等级。SPS(序列参数集)/PPS(图像参数集):包含了初始化H.264解码器所需要的信息参数,包括编码用profile,level,图像宽和高,deblock滤波器H.264把图像分为一帧(frame)或两场(filed);帧又分为片(slice),片由宏块(MB)组成,宏块是编码处

动态显示图片 Js + html_lzid2008的博客-程序员秘密

theShowImg.htm -->无标题文档   //showImgsJs.js// JavaScript Documentvar htmlShow = "" var imgName ="";  var numBegin,numEnd; var colNum = 7;  //一行显示的图片数量 var theCount = 12;//总共有多少图片  //文件夹里图片的名称