SLAM从入门到精通(dwa算法)

news2025/3/15 13:02:12

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        要说搜路算法,这个大家都比较好理解。毕竟从一个地点走到另外一个地点,这个都是直觉上可以感受到的事情。但是这条道路上机器人应该怎么走,以什么样的速度、什么样的角速度走,这里面有很大的学问。一方面,机器人本身的机械特性决定了它的速度、角速度这些参数都有一定范围约束的;另外一方面,不同的速度、角速度走出来的轨迹可能是不一样的,特别是拐弯的时候。这个时候,什么样的轨迹最适合我们机器人,就需要设计出一套标准来甄别了。比如,是越快越好,还是越安全越好,还是说离目标越近越好。

        对于客户来说,速度、角速度肯定是越快越好。但是机械的特性决定了很多时候它快不了,比如转弯的时候,甚至是连续转弯的时候,速度快了反而不安全。正因为有了这些需求,所以才会有了dwa算法设计出来帮助我们来解决这些问题。

1、了解机器人的参数

        每一款机器人都有自己独特的参数,比如最小速度、最大速度;最小角速度、最大加速度;最小线加速度、最大线加速度等等。这些数据都需要做很好的了解。不仅如此,我们还需要知道机器人的最小转弯半径。如果可以原地旋转,这固然很好。但是大多数机器人不一定可以做到这一点。而且根据v=w*r,一旦转弯半径定了,v和w只要一个确定了,另外一个也就确定了。

2、知晓机器人的运动学模型

        之前我们说过差速轮的运动学模型,假设速度分别为v和w,那么后面小车的轨迹应该是这样的,

x += v * cos(theta) * dt
y += v * cos(theta) * dt
theta += w * dt

        当然这里描述的只是差速轮的运动学模型,其他机器人的运动学模型也可以通过类似的方法进行计算。

3、速度采样、加速度采样

        以速度为例,机器人本身有一个最小速度,还有一个最大速度。此外,它还有一个最小加速度、最大加速度。所以某个时刻速度v,依据加速度的范围可以得到一个数值[v_min, v_max],但是这个范围不能超过[vmin,v_max]机器人本身要求的范围。所以最终机器人的速度应该是在[max(v_min, vmin), min(v_max, vmax)]这个范围之内。加速度也是一个道理。

4、轨迹评价标准

        本身dwa提供了三个评价标准,分别是目标、速度以及和障碍物的最小距离。当然,这三个标准是不一定的,我们完全可以自己来设计。

5、测试代码

        dwa算测的测试代码是用python实现的,参考一本ros书上的内容,在此表示感谢。此python代码用python3执行,依赖于库matplotlib。代码内容如下,

import numpy as np
import matplotlib.pyplot as plt
import math

class Info():
    def __init__(self):
        self.v_min = -0.5
        self.v_max = 3.0
        self.w_max = 50.0 * math.pi / 180.0
        self.w_min = -50.0 * math.pi / 180.0
        self.vacc_max = 0.5
        self.wacc_max = 30.0 * math.pi / 180.0
        self.v_reso = 0.01
        self.w_reso = 0.1 * math.pi / 180.0
        self.radius = 1.0
        self.dt = 0.1
        self.predict_time = 4.0
        self.goal_factor = 1.0
        self.vel_factor = 1.0
        self.traj_factor = 1.0
    
def motion_model(x,u,dt):
    x[0] += u[0] * dt * math.cos(x[2])
    x[1] += u[0] * dt * math.sin(x[2])
    x[2] += u[1] * dt
    x[3] = u[0]
    x[4] = u[1]
    return x

def vw_generate(x,info):
    Vinfo = [info.v_min, info.v_max,
            info.w_min, info.w_max]
    
    Vmove = [x[3] - info.vacc_max * info.dt,
              x[3] + info.vacc_max * info.dt,
              x[4] - info.wacc_max * info.dt,
              x[4] + info.wacc_max * info.dt]

    vw = [max(Vinfo[0], Vmove[0]), min(Vinfo[1], Vmove[1]),
          max(Vinfo[2], Vmove[2]), min(Vinfo[3], Vmove[3])]
    return vw


def traj_calculate(x,u,info):
    ctraj = np.array(x)
    xnew = np.array(x)
    time = 0
    
    while time <= info.predict_time:
        x_new = motion_model(xnew,u,info.dt)
        ctraj = np.vstack((ctraj, xnew))
        time += info.dt
    return ctraj


def dwa_core(x,u,goal,info, obstacles):
    vw = vw_generate(x,info)
    best_ctraj = np.array(x)
    min_score = 10000.0
    
    for v in np.arange(vw[0], vw[1], info.v_reso):
        for w in np.arange(vw[2], vw[3], info.w_reso):
            ctraj = traj_calculate(x, [v,w], info)
            
            goal_score = info.goal_factor * goal_evaluate(ctraj, goal)
            vel_score = info.vel_factor * velocity_evaluate(ctraj, info)
            traj_score = info.traj_factor * traj_evaluate(ctraj, obstacles,info)
            ctraj_score = goal_score + vel_score + traj_score
            
            if min_score >= ctraj_score:
                min_score = ctraj_score
                u = np.array([v,w])
                best_ctraj = ctraj

    return u,best_ctraj


def goal_evaluate(traj, goal):
    goal_score = math.sqrt((traj[-1,0]-goal[0])**2 + (traj[-1,1]-goal[1])**2)
    return goal_score
    
def velocity_evaluate(traj, info):
    vel_score = info.v_max - traj[-1,3]
    return vel_score

def traj_evaluate(traj, obstacles, info):
    min_dis = float("Inf")
    for i in range(len(traj)):
        for ii in range(len(obstacles)):
            current_dist = math.sqrt((traj[i,0] - obstacles[ii,0])**2 + (traj[i,1] - obstacles[ii,1])**2)
            if current_dist <= info.radius:
                return float("Inf")
            
            if min_dis >= current_dist:
                min_dis = current_dist

    return 1/min_dis


def obstacles_generate():
    obstacles = np.array([[0,10],
                    [2,10],
                    [4,10],
                    [6,10],
                    [3,5],
                    [4,5],
                    [5,5],
                    [6,5],
                    [7,5],
                    [8,5],
                    [10,7],
                    [10,9],
                    [10,11],
                    [10,13]])
    return obstacles

def local_traj_display(x,goal,current_traj, obstacles):
    plt.cla()
    plt.plot(goal[0], goal[1], 'or', markersize=10)
    plt.plot([0,14],[0,0],'-k',linewidth=7)
    plt.plot([0,14],[14,14],'-k',linewidth=7)
    plt.plot([0,0],[0,14],'-k',linewidth=7)
    plt.plot([14,14],[0,14],'-k',linewidth=7)
    plt.plot([0,6],[10,10],'-y',linewidth=10)
    plt.plot([3,8],[5,5],'-y',linewidth=10)
    plt.plot([10,10],[7,13],'-y',linewidth=10)
    plt.plot(obstacles[:,0], obstacles[:,1],'*b',linewidth=8)
    plt.plot(x[0], x[1], 'ob', markersize=10)
    plt.arrow(x[0], x[1], math.cos(x[2]), math.sin(x[2]), width=0.02, fc='red')
    plt.plot(current_traj[:,0], current_traj[:,1], '-g', linewidth=2)
    plt.grid(True)
    plt.pause(0.001)
    
def main():
    x = np.array([2,2,45*math.pi/180,0,0])
    u = np.array([0,0])
    goal = np.array([8,8])
    info = Info()
    obstacles = obstacles_generate()
    global_traj = np.array(x)
    plt.figure('DWA Algorithm')
    
    for i in range(2000):
        u,current_traj = dwa_core(x,u,goal,info,obstacles)
        x = motion_model(x,u,info.dt)
        global_traj = np.vstack((global_traj, x))
        local_traj_display(x, goal, current_traj,obstacles)
        if math.sqrt((x[0]-goal[0])**2 + (x[1]-goal[1])**2 <= info.radius):
            print("Goal Arrived")
            break
    plt.plot(global_traj[:,0], global_traj[:,1], '-r')
    plt.show()    
        
if __name__ == "__main__":
    main()

6、执行效果

        代码本身是一个仿真过程,大家可以下载下来在ubuntu环境下测试验证一下。最终实现的效果如下所示,

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

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

相关文章

行情分析——加密货币市场大盘走势(10.17)

大饼昨日在受到假消息美国证券交易委员会&#xff08;SEC&#xff09;通过大饼ETF后迅速上涨&#xff0c;一度上涨到30000&#xff0c;而很快回落到28000附近。从MACD日线来看&#xff0c;现在完全进入多头趋势&#xff0c;同时大饼再次进入蓝色上涨趋势线&#xff0c;目前按照…

李宏毅机器学习笔记-半监督学习

半监督学习&#xff0c;一般应用于少量带标签的数据&#xff08;数量R&#xff09;和大量未带标签数据的场景&#xff08;数量U&#xff09;&#xff0c;一般来说&#xff0c;U>>R。 半监督学习一般可以分为2种情况&#xff0c;一种是transductive learning&#xff0c;…

使用秋云 ucharts echarts 高性能跨全端图表组件 流程

1. 2. // 引入 import qiunDataCharts from ../../uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue // 注册 components:{qiunDataCharts },// 页面中使用 <qiun-data-charts type"line" :opts"opts" :chartData"…

04 MIT线性代数-矩阵的LU分解 Factorization into A=LU

目的: 从矩阵的角度理解高斯消元法, 完成LU分解得到ALU 1.矩阵乘积的逆矩阵 Inverse of a product 2.矩阵乘积的转置 Transpose of a product 3.转置矩阵的逆矩阵 Inverse of a transpose 4.矩阵的LU分解 U为上三角阵(Upper triangular matrix), L为下三角阵(Lower triangular…

pycharm远程连接miniconda完整过程,以及遇到的问题解决

问题1&#xff1a;no-zero exit code(126) env: ‘/home/user2/miniconda3/envs/ihan/bin/python3’: Too many levels of symbolic links Python interpreter process exited with a non-zero exit code 126 因为选择的新建导致太多软连接&#xff0c;先在服务器上建好虚拟环…

【微信小程序】数字化会议OA系统之首页搭建(附源码)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《微信小程序开发实战》。&#x1f3af;&#x1f3a…

eNSP笔记①

关闭范文信息&#xff1a;undo terminal monitor VRP三种试图 "<>"表示用户视图&#xff0c;系统默认的状态。主要用于查询设备基础信息或者状态等&#xff0c;也可以执行保存(save)。 “[]” 表示系统视图&#xff0c;在用户视图下输入system-view进入状态…

Kafka序列化反序列化解析、kafka schema

Kafka序列化反序列化解析、kafka schema。 kafka有自己的rpc协议,即nio bytebuf中的数据格式,详见之前的kafka相关介绍的文章。这里我们来看一下大家常用,有时又疑惑的序列化反序列化,对应rpc协议中的records,kafka叫Serdes,实际上也是字面上的意思serialize and deseri…

Qt扫盲-QDataStream 序列化和反序列化理论

QDataStream 序列化和反序列化理论 一、概述二、QDataStream 概述三、版本控制四、读取和写入原始二进制数据五、读写Qt集合类六、读写其他Qt类七、使用读事务八、Qt支持的序列化类型 一、概述 序列化&#xff1a; 指的是将一个内存对象转化成一串字节数据&#xff08;存储在一…

FSDP(Fully Sharded Data Parallel)

完全分片数据并行 (FSDP) &#xff0c;它将AI 模型的参数分片到数据并行工作器上&#xff0c;并且可以选择将部分训练计算卸载到 CPU。顾名思义&#xff0c;FSDP 是一种数据并行训练算法。尽管参数被分片到不同的GPU&#xff0c;但每个微批次数据的计算仍然是每个 GPU Worker 本…

C++ - 一些特殊类的设计

前言 我们在日常写项目的过程当中&#xff0c;肯定会遇到各种各样的需求&#xff0c;那么也就要求我们要写各种各样的类。本篇博客当中&#xff0c;就一些常用的特殊类进行介绍和实现。 不能被拷贝的类 关于实例化类拷贝&#xff08;对象的拷贝&#xff09;一般就是两个场景&…

6.DApp-用Web3实现前端与智能合约的交互

题记 用Web3实现前端与智能合约的交互&#xff0c;以下是操作流程和代码。 准备ganache环境 文章地址&#xff1a;4.DApp-MetaMask怎么连接本地Ganache-CSDN博客 准备智能合约 文章地址&#xff1a; 2.DApp-编写和运行solidity智能合约-CSDN博客 编写index.html文件 <!…

简单测试一下 展锐的 UDX710 性能

最近在接触 联通5G CPE VN007 &#xff0c;发现使用的是 展锐的Unisoc UDX710 CPU&#xff0c;正好简单的测试一下这颗CPU CPU信息 UDX710 是一颗 双核 ARM Cortex-A55 处理器&#xff0c;主频高达 1.35GHz processor : 0 BogoMIPS : 52.00 Features : fp…

ARM资源记录《AI嵌入式系统:算法优化与实现》第八章(暂时用不到)

1.CMSIS的代码 书里给的5&#xff0c;https://github.com/ARM-software/CMSIS_5 现在有6了&#xff0c;https://github.com/ARM-software/CMSIS_6 这是官网的书&#xff0c;介绍cmsis函数的https://arm-software.github.io/CMSIS_5/Core/html/index.html 2.CMSIS介绍 Cort…

Git命令在线练习网址--非常友好的提示及动画展示

Git命令在线练习 https://learngitbranching.js.org/ 举个栗子: 在练习时会给你相应提示,你可以按照相应步骤进行操作,并且每一步都有动画演示

A股风格因子看板 (2023.10 第05期)

该因子看板跟踪A股风格因子&#xff0c;该因子主要解释沪深两市的市场收益、刻画市场风格趋势的系列风格因子&#xff0c;用以分析市场风格切换、组合风格暴露等。 今日为该因子跟踪第05期&#xff0c;指数组合数据截止日2023-09-30&#xff0c;要点如下 近1年A股风格因子检验统…

Windows10 Docker 安装教程

Docker Desktop是什么&#xff1f; Docker Desktop是适用于Windows的Docker桌面&#xff0c;是Docker设计用于在Windows 10上运行。它是一个本地 Windows 应用程序&#xff0c;为构建、交付和运行dockerized应用程序提供易于使用的开发环境。Docker Desktop for Windows 使用 …

手机应用app打开游戏显示连接服务器失败是什么原因?排查解决方案?

亲爱的同学们&#xff0c;有时候我们在使用手机设备时&#xff0c;可能会遇到一个很头疼的问题——连接服务器失败。这个问题不仅让我们感到困扰&#xff0c;还影响到了我们的用户体验。那么&#xff0c;我们究竟能如何解决这个问题呢&#xff1f;今天&#xff0c;笔者就和大家…

一百九十、Hive——Hive刷新分区MSCK REPAIR TABLE

一、目的 在用Flume采集Kafka中的数据直接写入Hive的ODS层静态分区表后&#xff0c;需要刷新表&#xff0c;才能导入分区和数据。原因很简单&#xff0c;就是Hive表缺乏分区的元数据 二、实施步骤 &#xff08;一&#xff09;问题——在Flume采集Kafka中的数据写入HDFS后&am…

Scrum 敏捷管理流程图及敏捷管理工具

​敏捷开发中的Scrum流程通常可以用一个简单的流程图来表示&#xff0c;以便更清晰地展示Scrum框架的各个阶段和活动。以下是一个常见的Scrum流程图示例&#xff1a; 转自&#xff1a;Leangoo.com 免费敏捷工具 这个流程图涵盖了Scrum框架的主要阶段和活动&#xff0c;其中包括…