机器人学习-关于经典路径规划(一)

这篇具有很好参考价值的文章主要介绍了机器人学习-关于经典路径规划(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.内容简介

  • 识别不同类型的路径规划算法
  • 理解一组算法的内部工作原理
  • 评估算法对特定应用的适用性
  • 实现搜索算法

2.路径规划示例

术语

完整性——如果一个算法能够在起点和目标之间找到一条路径,那么这个算法就是完整的。

最优性——如果一个算法能够找到最佳的解决方案,那么它就是最优的。

bug算法

下面的问题演示一个有解决方案,但bug算法无法找到它的例子:

机器人学习-关于经典路径规划(一)

机器人会无休止地穿越在障碍物的外墙周边,但bug算法的一些变体可以弥补这个错误,大部分路径规划算法依赖于本文将介绍的其他原则。在研究新的算法时,我们将在分析算法对任务的适用性时重新考虑完整性和最优性的概念。

3.路径规划方法
路径规划方法

在本文中,将学习三种不同的路径规划方法。第一种称为离散(或组合)路径规划,是三种方法中最直接的。另外两种方法,称为基于样本的路径规划和概率路径规划,建立在离散规划的基础上,以开发更广泛适用的路径规划解决方案。

离散规划
离散规划是将机器人的工作空间显式离散化为一个连通图,并应用graph-search(图搜索)算法来计算最佳路径。这个过程非常精确(实际上,可以通过改变离散空间的精细程度来显式地调整精度),而且非常彻底,因为它离散了整个工作空间。因此,离散规划的计算成本可能非常高——对于大型路径规划问题来说,这可能令人望而却步。
下图显示了应用于二维工作空间的离散路径规划的一种可能实现。

机器人学习-关于经典路径规划(一)

离散路径规划在其精确性上是优雅的,但最适合于低维问题。对于高维问题,基于样本的路径规划是一种更合适的方法。
基于样本的规划

基于样本的路径规划探测工作空间以增量地构造一个图。与离散工作空间的每个部分不同,基于样本的规划采用许多样本并使用它们来构建工作空间的离散表示。生成的图不如使用离散规划创建的图精确,但由于使用的样本数量相对较少,因此构造起来要快得多。
使用基于样本的规划生成的路径可能不是最佳路径,但在某些应用中——快速生成可行路径比等待数小时甚至数天生成最优路径要好。

下图显示了使用基于样本的规划创建的二维工作空间的图形表示。

机器人学习-关于经典路径规划(一)

概率路径规划
在本模块中学习的最后一种路径规划是概率路径规划。前两种方法一般地考虑路径规划问题——不了解谁或什么可能在执行动作——概率路径规划考虑了机器人运动的不确定性。
虽然这在某些环境中可能不会提供显著的好处,但在高度受限的环境或具有敏感或高风险区域的环境中尤其有用。
下图显示了应用于包含危险的环境(右上方的湖泊)的概率路径规划:

机器人学习-关于经典路径规划(一)

Multi-Lesson地图
在本文中,学习几种离散路径规划算法及基于样本和概率规划,然后应用到路径规划实验中,并使用C++编写搜索算法。

4.连续性表示
为了考虑机器人的几何形状并简化路径规划的任务,工作空间中的障碍物可以膨胀以创建一个称为配置空间(或C空间)的新空间。障碍物的边缘随着机器人的半径大小膨胀,机器人本体可以被视为一个点,使算法更容易搜索路径。C空间是所有机器人姿态的集合,可以分解为C_Free和C_Obs。

5.Minkowski求和
Minkowski求和

Minkowski之和是一种数学性质,可用于计算给定障碍物和机器人几何的配置空间。
Minkowski之和计算方法的直觉可以通过想象用一个形状像机器人的画笔绘制一个障碍物的外部来理解,机器人的原点是画笔的尖端。涂漆面积为C_obs。下图显示了这一点。

机器人学习-关于经典路径规划(一)为了创建配置空间,对工作空间中的每一个障碍物都用这种方法计算Minkowski之和。下图显示了由三个不同大小的机器人从一个工作空间创建的三个配置空间。如您所见,如果机器人只是一个点,那么工作空间中的障碍物只会膨胀少量来创建C空间。随着机器人体积的增大,障碍物也会膨胀得越来越大。

机器人学习-关于经典路径规划(一)对于凸多边形,计算卷积是很简单的,可以在线性时间内完成-然而对于非凸多边形(即存在间隙或空洞的多边形),计算要昂贵得多。
如果有兴趣更详细地了解Minkowski之和,可参见以下资源:

  • A blog post on Minkowski sums and differences,

  • An interesting read on how collisions are detected in video games.

小测验:Minkowski求和

如下图所示:

机器人学习-关于经典路径规划(一)

以下哪个图像代表上面所示的机器人(紫色)和障碍物(白色)的配置空间? 答案:B

机器人学习-关于经典路径规划(一)

机器人学习-关于经典路径规划(一)

6.Minkowski求和的C++实现
现在已经学习了Minkowski求和,请尝试在C++中编写代码!
图示如下: 

机器人学习-关于经典路径规划(一)

在这个例子中,可以看到两个三角形——一个蓝色的,一个红色的。假设机器人用一个蓝色三角形表示,障碍物用一个红色三角形表示。任务是用C++计算机器人A和障碍物B的配置空间C。

  • 机器人:蓝色三角形,用A表示
  • 障碍物:红色三角形,用B表示

 下面是在C++中编写Minkowski和的步骤:

机器人学习-关于经典路径规划(一)   机器人学习-关于经典路径规划(一)

机器人学习-关于经典路径规划(一)

机器人学习-关于经典路径规划(一)

Non-shifted(未转换)图例
以上用C++编写了Minkowski求和代码,并生成了配置空间。注意到红色的障碍物并没有充分膨胀,蓝色的机器人仍然可以撞到障碍物。这是因为配置空间仍然需要转移到障碍物上。
首先将机器人转换为障碍物,计算配置空间后,再转化为机器人和障碍物。
转换后图例

机器人学习-关于经典路径规划(一)

上图是转换后最终的图像,其中蓝色的机器人和绿色的配置空间都发生了转化。可以看到黄色填充,它代表转换后的配置空间围绕在红色障碍物周围。蓝色的机器人不会再撞到红色的障碍物,因为它膨胀得很好。

完整代码如下:(详见-https://github.com/udacity/RoboND-MinkowskiSum)

#include <iostream>
#include <vector>
#include <algorithm>
#include "../lib/matplotlibcpp.h"
#include <math.h>

using namespace std;
namespace plt = matplotlibcpp;

// Print 2D vectors coordinate values
void print2DVector(vector<vector<double> > vec)
{
    for (int i = 0; i < vec.size(); ++i) {
        cout << "(";
        for (int j = 0; j < vec[0].size(); ++j) {
            if (vec[i][j] >= 0)
                cout << vec[i][j] << "  ";
            else
                cout << "\b" << vec[i][j] << "  ";
        }
        cout << "\b\b)" << endl;
    }
}

// Check for duplicate coordinates inside a 2D vector and delete them
vector<vector<double> > delete_duplicate(vector<vector<double> > C)
{
    // Sort the C vector
    sort(C.begin(), C.end());
    // Initialize a non duplicated vector
    vector<vector<double> > Cn;
    for (int i = 0; i < C.size() - 1; i++) {
        // Check if it's a duplicate coordinate
        if (C[i] != C[i + 1]) {
            Cn.push_back(C[i]);
        }
    }
    Cn.push_back(C[C.size() - 1]);
    return Cn;
}

// Compute the minkowski sum of two vectors
vector<vector<double> > minkowski_sum(vector<vector<double> > A, vector<vector<double> > B)
{
    vector<vector<double> > C;
    for (int i = 0; i < A.size(); i++) {
        for (int j = 0; j < B.size(); j++) {
            // Compute the current sum
            vector<double> Ci = { A[i][0] + B[j][0], A[i][1] + B[j][1] };
            // Push it to the C vector
            C.push_back(Ci);
        }
    }
    C = delete_duplicate(C);
    return C;
}

// Compute the centroid of a polygon
vector<double> compute_centroid(vector<vector<double> > vec)
{
    vector<double> centroid(2);
    double centroid_x=0, centroid_y=0;
    for (int i = 0; i < vec.size(); i++) {
        centroid_x += vec[i][0];
        centroid_y += vec[i][1];
    }
    centroid[0] = centroid_x / vec.size();
    centroid[1] = centroid_y / vec.size();
    return centroid;
}

// Compute the angle of each point with respect to the centroid and append in a new column
// Resulting vector[xi,yi,anglei]
vector<vector<double> > compute_angle(vector<vector<double> > vec)
{
    vector<double> centroid = compute_centroid(vec);
    double prec = 0.0001;
    for (int i = 0; i < vec.size(); i++) {
        double dy = vec[i][1] - centroid[1];
        double dx = vec[i][0] - centroid[0];
        // If the point is the centroid then delete it from the vector
        if (abs(dx) < prec && abs(dy) < prec) {
            vec.erase(vec.begin() + i);
        }
        else {
            // compute the centroid-point angle
            double theta = (atan2(dy, dx) * 180) / M_PI;
            // append it to the vector in a 3rd column
            vec[i].push_back(theta);
        }
    }
    return vec;
}

// Sort the vector in increasing angle (clockwise) for plotting
vector<vector<double> > sort_vector(vector<vector<double> > vec)
{
    vector<vector<double> > sorted_vec = compute_angle(vec);
    // Change the 0 angle to 90 degrees
    for (int i = 0; i < sorted_vec.size(); i++) {
        if (sorted_vec[i][2] == 0)
            sorted_vec[i][2] = 90.0;
    }
    // Sort with respect to the 3rd column(angles)
    sort(sorted_vec.begin(),
        sorted_vec.end(),
        [](const vector<double>& a, const vector<double>& b) {
            return a[2] < b[2];
        });
    return sorted_vec;
}

// Process the shapes and plot them
void plot(vector<vector<double> > vec, string color)
{
    // Sort the vector coordinates in clockwise
    vector<vector<double> > sorted_vec;
    sorted_vec = sort_vector(vec);
    // Add the first element to the end of the vector
    sorted_vec.push_back(sorted_vec[0]);
    // Loop through vector original size
    for (int i = 0; i < sorted_vec.size() - 1; i++) {
        // Connect coordinate point and plot the lines (x1,x2)(y1,y2)
        plt::plot({ sorted_vec[i][0], sorted_vec[i + 1][0] }, { sorted_vec[i][1], sorted_vec[i + 1][1] }, color);
    }
}

// Translate the configuration space toward the obstacle
vector<vector<double> > shift_space(vector<vector<double> > B, vector<vector<double> > C)
{
    // Compute the obstacle and space centroids
    vector<double> centroid_obstacle = compute_centroid(B);
    vector<double> centroid_space = compute_centroid(C);
    // Compute the translations deltas
    double dx = centroid_space[0] - centroid_obstacle[0];
    double dy = centroid_space[1] - centroid_obstacle[1];
    // Translate the space
    for (int i = 0; i < C.size(); i++) {
        C[i][0] = C[i][0] - dx;
        C[i][1] = C[i][1] - dy;
    }
    return C;
}

// Draw A, B and C shapes
void draw_shapes(vector<vector<double> > A, vector<vector<double> > B, vector<vector<double> > C)
{
    //Graph Format
    plt::title("Minkowski Sum");
    plt::xlim(-5, 5);
    plt::ylim(-5, 5);
    plt::grid(true);

    // Draw triangle A
    plot(A, "b-");

    // Draw triangle B
    plot(B, "r-");

    // Draw configuration space C
    // Trasnlate the C space
    vector<vector<double> > shifted_C = shift_space(B, C);
    plot(shifted_C, "y-");
    // Plot the original C shape
    plot(C, "g-");
    
    //Save the image and close the plot
    plt::save("../images/Minkowski_Sum.png");
    plt::clf();
}

int main()
{
    // Define the coordinates of triangle A and B in 2D vectors
    vector<vector<double> > A(3, vector<double>(2));
    // Robot A
    A = {
        { 0, -1 }, { 0, 1 }, { 1, 0 },
    };
    vector<vector<double> > B(3, vector<double>(2));
    // Obstacle B
    B = {
        { 0, 0 }, { 1, 1 }, { 1, -1 },
    };
    
    // Translating Robot toward the obstacle
    A=shift_space(B,A);
    
    // Compute the Minkowski Sum of triangle A and B
    vector<vector<double> > C;
    C = minkowski_sum(A, B);

    // Print the resulting vector
    print2DVector(C);

    // Draw all the shapes
    draw_shapes(A, B, C);
    
    return 0;
}

简而言之,必须遵循以下步骤来生成任意多边形:

  1. 计算每个多边形的质心
  2. 计算每个点质心相对于x轴的角度
  3. 将点按角度升序排序(顺时针)
  4. 在每个连续的点之间画一条线

7.三维配置空间

机器人的配置空间取决于它的旋转,允许机器人旋转增加了一个自由度——因此,它也使配置空间复杂化了。配置空间的维数等于机器人拥有的自由度的个数。虽然二维配置空间能够表示机器人的x和y平移,但需要第三维来表示机器人的旋转。让我们看看一个机器人和它对应的两种不同旋转的配置空间。第一种是0°,第二种是18°。

机器人学习-关于经典路径规划(一)

三维配置空间可以通过将二维配置空间堆叠成层来生成——如下图所示:

机器人学习-关于经典路径规划(一)

如果要计算机器人的无限小旋转的配置空间,并将它们堆叠在一起-我们会得到如下图所示的图形: 机器人学习-关于经典路径规划(一)

上图显示了一个三角形机器人的配置空间,它可以在二维空间中平移,也可以绕z轴旋转。虽然这个图像看起来很复杂,但有一些技巧可以用来生成3D配置空间并在它们周围移动。以下视频来自Freie Universität Berlin,是一个美妙的三维配置空间的可视化。该视频将显示不同类型的运动,并描述某些机器人运动如何映射到3D配置空间:Configuration Space Visualization 。文章来源地址https://www.toymoban.com/news/detail-459873.html

到了这里,关于机器人学习-关于经典路径规划(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 机器人轨迹生成:轨迹规划与路径规划

    机器人轨迹生成涉及到轨迹规划和路径规划两个关键概念,它们是机器人运动控制中的重要组成部分。下面对轨迹规划和路径规划进行深入比较。 轨迹规划(Trajectory Planning): 定义:轨迹规划是指在机器人运动中确定机器人末端或关节的期望轨迹。它是在特定的工作空间中

    2024年02月12日
    浏览(55)
  • ECBS多机器人路径规划

    多智能体路径规划 (Multi-Agent Path Finding, MAPF) 研究多智能体的路径规划算法,为多机系统规划无冲突的最优路径。 ECBS 算法由 CBS(Conflict-Based Search) 算法改进而来, 对 CBS算法的介绍可以参考笔者的这篇文章CBS多机器人路径规划(Conflict-Based Search)。CBS 算法给出 MAPF 问题的 全局最优

    2024年02月05日
    浏览(65)
  • 多机器人路径规划(MAPF)综述

    Multi-Agent Pathfinding: Definitions, Variants, and Benchmarks 这篇综述详细介绍了多机器人路径规划问题(Multi-Agent Path Finding, MAPF)统一的描述形式和研究 MAPF 问题需要参考的术语定义,并介绍了评估 MAPF 算法的标准数据集. 文中介绍了一个关于 MAPF 非常重要的网站 : http://mapf.info, 里面实时更

    2024年02月06日
    浏览(91)
  • 【路径规划】基于遗传算法求解机器人栅格地图路径规划问题matlab代码

     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进, 代码获取、论文复现及科研仿真合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab完整代码及仿真定制内容点击👇 智能优化算法       神经网络预测       雷达通信    

    2024年01月24日
    浏览(67)
  • 【路径规划matlab代码】基于遗传算法求解机器人栅格地图路径规划问题

     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进, 代码获取、论文复现及科研仿真合作可私信。 🍎个人主页:Matlab科研工作室 🍊个人信条:格物致知。 更多Matlab完整代码及仿真定制内容点击👇 智能优化算法       神经网络预测       雷达通信    

    2024年03月08日
    浏览(73)
  • SLAM+路径规划:巡检机器人算法设计

    标题:Research on SLAM and Path Planning Method of Inspection Robot in Complex Scenarios 作者:Xiaohui Wang,Xi Ma,Zhaowei Li 编译:东岸因为 编辑:郑欣欣@一点人工一点智能 入群邀请:7个专业方向交流群+1个资料需求群 原文:SLAM+路径规划:巡检机器人算法设计 工厂安全检查对于保持生产环境

    2024年02月03日
    浏览(49)
  • 基于粒子群算法的机器人动态路径规划

    基于粒子群算法的机器人动态路径规划 粒子群算法(Particle Swarm Optimization,PSO)是一种基于群体智能的优化算法,常用于解决优化问题。在机器人动态路径规划中,粒子群算法可以被应用于寻找最优路径,以使机器人在动态环境中能够高效地规划路径并避免障碍物。 本文将

    2024年02月07日
    浏览(53)
  • 改进灰狼算法实现机器人栅格地图路径规划

    改进灰狼算法实现机器人栅格地图路径规划 在机器人路径规划领域中,灰狼算法是一种具有全局搜索能力的优化算法。为了进一步提高其性能,可以结合和声算法对其进行改进。本文将介绍如何使用改进的灰狼算法实现机器人在栅格地图上的路径规划,并提供相应的MATLAB源代

    2024年02月06日
    浏览(59)
  • 基于灰狼算法的机器人栅格地图路径规划

    基于灰狼算法的机器人栅格地图路径规划 路径规划是机器人领域中一项重要的任务,它涉及在给定的环境中找到机器人从起始点到目标点的最优路径。灰狼算法是一种基于自然界中灰狼群体行为的优化算法,可以用于解决路径规划问题。在本文中,我们将介绍如何使用灰狼算

    2024年02月06日
    浏览(70)
  • 一套简单的机器人短途路径规划算法

    适用场景 效果 机器人在收到目标点后, global_planner先生成一条直达该点的路径 机器人转向目标点 机器人移动至目标点 机器人旋转到目标位姿 具体可以参考上篇文章, 修改了ROS自带navigation包中的carrot_planner, 使之具有以下特点 global_plan这个vector中包含的路径点的数量增加, 适配

    2024年02月19日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包