首页 > 编程语言 >路径规划算法

路径规划算法

时间:2024-08-30 20:51:53浏览次数:7  
标签:样条 int 规划 路径 插值 算法 代价 节点

Field D*

Filed D*算法是D_star Lite算法的一种改进版本,该算法针对基于栅格的路径规划算法通常以栅格端点或中心点作为路径的节点,限制了路径方向变化只能为π/4的倍数,会导致机器人不必要的运动转向,影响执行效率。而Dave Ferguson提出的Filed D*算法,通过对栅格进行线性插值使路径点不局限于端点,规划方向的变化不再受限于π/4的倍数,生成较为平滑的路径

原文:

https://blog.csdn.net/lqzdreamer/article/details/85158542

Filed D*算法的关键是在给定相邻节点路径代价的前提下,提出一种计算每个网格节点路径代价的新方法。在基于网格的路径规划中,一个节点的代价为(从节点到目标的路径代价):

其中,nbrs(s)是s的所有相邻节点的集合;c(s, s’)是遍历s和s’之间的边的代价,g(s’)是节点s’的路径代价。而在此之前都是假设从节点s到相邻节点的唯一可能的移动只能是直线轨迹(只能是从一格移动到另一格)。

而Filed D*考虑放宽这个假设,允许从节点s到其网格单元边界上的任何一点的直线轨迹(如下图所示)。如果知道每一个点 s b s_b sb​在边界的值,那么仅仅可以通过最小化 c ( s , s b ) + g ( s b ) c(s, s_b)+ g(s_b) c(s,sb​)+g(sb​)计算节点s的最优值, c ( s , s b ) c(s, s_b) c(s,sb​)通过s和sb之间的距离乘以到达s所在单元的代价。但是,这样的点有无数个,因此不可能为每个点计算 g ( s b ) g(s_b) g(sb​)。

但是,用线性插值法对每个边界点提供g(sb)的近似是可能的。首先将上图中的节点视为连续代价的样本点,由节点s开始的一条优化路径必须通过连接两个连续相邻的边缘,例如
​。因此,设置通过这些边的路径的最小代价为s的路径代价,而这些边被认为是一次一条。为了通过计算节点s的路径,需要使用节点 ​的路径代价以及图5(a)中所示中间网格的转移代价c和底部网格的转移代价b。

假设位于 s 1​和 s 2​之间边界上的任意点sy的路径代价是 g ( s 1 ) 和 g ( s 2 ) 的线性组合(如图6):

其中,其中y是 s 1 ​到 s y的距离(假设单位单元格)。这个假设并不完美, s y 的路径代价可能不是 g ( s 1 ) 和 g ( s 2 )的线性组合,甚至也不是这些路径代价的函数。然而,这种线性近似在实际应用中效果良好,可以构造节点s路径代价的封闭形式解。根据这个近似,s在 s 1、 s 2 ​、网格代价c和b下的路径代价可以计算为

这个公式可以通过上图7中的(a)图理解。公式中的第1项为s→ s x 的代价,第2项为 s x → s y 的代价,第3、4项为y处的代价。其中, x ∈ [ 0 , 1 ] , y ∈ [ 0 , 1 ] 。当x=y=1时,路径为底部的路径,但是代价却是中间网格的代价。

C++代码:

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <limits>

using namespace std;

const double INFINITY_COST = numeric_limits<double>::infinity();

struct Node {
    int x, y;
    double g, rhs;
};

struct CompareCost {
    bool operator()(const Node& a, const Node& b) {
        return (a.g + a.rhs) > (b.g + b.rhs);
    }
};

vector<vector<double>> map; // 代表地图的二维数组
vector<vector<Node>> nodes;
priority_queue<Node, vector<Node>, CompareCost> openList;

void init(int rows, int cols) {
    map.resize(rows, vector<double>(cols, 1));
    nodes.resize(rows, vector<Node>(cols, {0, 0, INFINITY_COST, INFINITY_COST}));
}

double heuristic(int x1, int y1, int x2, int y2) {
    return abs(x2 - x1) + abs(y2 - y1);
}

void updateVertex(Node& u, int goalX, int goalY) {
    if (u.x != goalX || u.y != goalY) {
        u.rhs = INFINITY_COST;
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                if (i == 0 && j == 0) continue;
                if (u.x + i >= 0 && u.x + i < map.size() && u.y + j >= 0 && u.y + j < map[0].size()) {
                    Node v = nodes[u.x + i][u.y + j];
                    u.rhs = min(u.rhs, v.g + heuristic(u.x, u.y, v.x, v.y));
                }
            }
        }
    }
    if (find(openList.begin(), openList.end(), u) != openList.end()) {
        openList.pop();
    }
    u.g = u.rhs;
    openList.push(u);
}

void fieldDStar(int startX, int startY, int goalX, int goalY) {
    Node goal = {goalX, goalY, 0, 0};
    nodes[goalX][goalY] = goal;
    openList.push(goal);

    while (!openList.empty()) {
        Node u = openList.top();
        openList.pop();

        if (u.x == startX && u.y == startY) {
            cout << "Start reached!" << endl;
            break;
        }

        // 更新节点代价
        updateVertex(u, startX, startY);
    }
}

int main() {
    init(5, 5); // 初始化地图和节点数组

    fieldDStar(0, 0, 4, 4); // 从(0,0)到(4,4)的路径规划

    return 0;
}

Morphin局部避障规划

三次样条路径规划

三次样条路径规划是一种有效的路径规划方法,广泛应用于机器人轨迹规划自动驾驶运动规划等领域。

三次样条路径规划基于三次样条插值方法,通过一系列的控制点生成一条连续平滑的轨迹。这种方法的核心在于使用三次多项式来逼近给定的数据点,从而得到一条光滑曲线。三次样条插值方法的关键在于解决一组方程,这些方程确保了曲线在所有数据点处的连续性,并且在这些点之间达到一定的光滑度。

在三次样条路径规划中,每个分段使用三次多项式来表示,这些多项式在连接点处满足一定的条件,如速度和加速度的连续性。通过这种方式,可以生成一条既通过所有给定数据点又保持平滑的曲线。这种方法特别适用于需要生成平滑轨迹的应用场景,如机器人运动规划、自动驾驶等。

三次样条插值的基本原理:

  1. 数据点集合:三次样条插值通常基于一组已知的数据点,例如起始点和目标点,以及可能的中间参考点。

  2. 插值函数:通过这些数据点,三次样条插值会生成一个连续的三次多项式函数,这个函数在每两个相邻数据点之间是三次可微的。

  3. 平滑性:三次样条插值保证生成的曲线在数据点处平滑连接,并且一阶导数和二阶导数连续。

  4. 边界条件:通常需要为插值函数的边界指定条件,例如固定端点的值或者固定端点的一阶导数值,以确保生成的曲线在边界处有合适的行为。

  5. 参数化曲线:通过三次样条插值生成的曲线可以进行参数化,使得机器人可以沿着这条曲线移动,并且可以在需要时对参数进行调整以改变路径的形状。

 C++代码:这个示例代码使用了 Eigen 库来进行矩阵运算,Eigen 是一个用于线性代数运算的 C++ 模板库,提供了方便的矩阵和向量操作。

#include <iostream>
#include <Eigen/Dense>
#include <vector>

using namespace Eigen;
using namespace std;

// 三次样条插值计算函数
MatrixXd cubicSplineInterpolation(const vector<double>& x, const vector<double>& y) {
    int n = x.size();

    // 构建系数矩阵和右侧向量
    MatrixXd A = MatrixXd::Zero(n, n);
    VectorXd b(n);
    VectorXd h = VectorXd::Zero(n - 1);

    for (int i = 0; i < n - 1; i++) {
        h(i) = x[i + 1] - x[i];
    }

    for (int i = 1; i < n - 1; i++) {
        A(i, i - 1) = h(i - 1);
        A(i, i) = 2 * (h(i - 1) + h(i));
        A(i, i + 1) = h(i);
        b(i) = 3 * ((y[i + 1] - y[i]) / h(i) - (y[i] - y[i - 1]) / h(i - 1));
    }

    // 设置边界条件
    A(0, 0) = 1;
    A(n - 1, n - 1) = 1;

    // 解线性方程组
    VectorXd c = A.colPivHouseholderQr().solve(b);
    
    // 计算系数矩阵
    MatrixXd coefMatrix(n - 1, 4);
    for (int i = 0; i < n - 1; i++) {
        double a = y[i];
        double b = (y[i + 1] - y[i]) / h(i) - h(i) * (2 * c(i) + c(i + 1)) / 3;
        double d = (c(i + 1) - c(i)) / (3 * h(i));
        coefMatrix.row(i) << a, b, c(i), d;
    }

    return coefMatrix;
}

int main() {
    vector<double> x = {0, 1, 2, 3, 4};  // 数据点 x 坐标
    vector<double> y = {0, 1, 0.5, 1.5, 1};  // 数据点 y 坐标

    MatrixXd coefMatrix = cubicSplineInterpolation(x, y);

    cout << "Coefficients for each segment:" << endl;
    cout << coefMatrix << endl;

    return 0;
}

请确保已经安装了 Eigen 库,并将其正确包含在项目中。这段代码演示了如何通过三次样条插值计算系数矩阵,以实现平滑的曲线插值。

标签:样条,int,规划,路径,插值,算法,代价,节点
From: https://blog.csdn.net/m0_60857098/article/details/141687189

相关文章

  • TPAMI 2024 | 离散且平衡的谱聚类算法:一种可扩展的方法
    DiscreteandBalancedSpectralClusteringWithScalability离散且平衡的谱聚类算法:一种可扩展的方法RongWang,HuiminChen,YihangLu,QianrongZhang,FeipingNie,andXuelongLi摘要谱聚类(SC)因其卓越的聚类性能而成为深入研究的主要课题。尽管取得了成功......
  • 【有源码】基于Python的猫眼电影数据分析可视化与电影推荐系统K-means算法电影票房数
    注意:该项目只展示部分功能,如需了解,文末咨询即可。本文目录1.开发环境2系统设计2.1设计背景2.2设计内容3系统展示3.1功能展示视频3.2系统页面4更多推荐5部分功能代码1.开发环境开发语言:Python采用技术:K-means算法数据库:MySQL开发环境:PyCharm2系统......
  • 代码随想录算法训练营,8月30日 | 203.移除链表元素, 707.设计链表, 206.反转链表
    链表理论基础1.单链表:数据域和指针域(指向下一个结点的位置)组成,头结点,结尾为空指针;双链表:多了一个指向前一个结点的指针;循环链表:结尾指向头结点。2.链表在内存中的存储不是顺序的,跟数组不同,要找一个数据只能通过前一个数据来找,所有这就导致链表的查询比数组麻烦,但是插入删除数据......
  • 数据结构与算法 第四天(串、数组、广义表)
    串(String)任意字符组成的有限序列串的类型定义串的顺序存储结构模式匹配算法确定主串所含字串第一次出现的位置。BF算法穷举法,从每个字符开始依次匹配KMP算法链式存储数组基本操作特殊矩阵存储对称矩阵三角矩阵对角矩阵稀疏矩阵超过95%元素为零......
  • 算法专项—新手村
    一:python输入输出1、python中使用print函数输出语句;默认print输出会打印回车;在python中双引号和单引号的作用是相同的!print("gsupl")print("gsupl","yyds",sep='****')#用****分割print("gsupl"+"yyds")#使用+进行拼接print("guspl"*10)#输出10次......
  • 算法专项—码蹄集
    根据对码蹄集新手村的刷题经验;此片文章对python基本的语法进行简单的总结!一:python输入输出1、python中使用print函数输出语句;默认print输出会打印回车;在python中双引号和单引号的作用是相同的!print("gsupl")print("gsupl","yyds",sep='****')#用****分割print("gsupl"......
  • 「代码随想录算法训练营」第四十九天 | 图论 part7
    目录最小生成树的解题prim算法举例说明(来自代码随想录)题目:53.寻宝Kruskal算法举例说明(来自代码随想录)题目:53.寻宝最小生成树的解题最小生成树类型的题目主要用于解决所有节点的最小连通子图的问题,即:以最小的成本(边的权值)将图中所有节点链接到一起。最小生成树可以使用prim算......
  • 算法设计与分析:实验二 分治法——最近点对问题
    实验内容:对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离。分别对N=100000—10......
  • sha-256算法,生成固定长度的字符串
    SHA-256(安全哈希算法256位)是一种广泛使用的加密哈希函数,它会将输入的任意大小的数据转换为固定长度的256位(32字节)哈希值。SHA-256是SHA-2系列算法的一部分,由美国国家安全局(NSA)设计,并由美国国家标准与技术研究院(NIST)发布。SHA-256的主要特点包括:固定长度输出:无论输入数据的......
  • Java中的并发控制算法:如何实现高效的锁机制与无锁编程
    Java中的并发控制算法:如何实现高效的锁机制与无锁编程大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在多线程环境中,如何保证数据的正确性和一致性是个重要的问题。为了解决这个问题,Java提供了多种并发控制算法,主要包括锁机制和无锁编程。本文将介......