SLAM从入门到精通(dwa速度规划算法)

news2025/3/13 6:33:59

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

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

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

1、了解机器人的参数

        每一款机器人都有自己独特的参数,比如最小速度、最大速度;最小角速度、最大角速度;最小线加速度、最大线加速度等等。这些数据都需要做很好的了解。不仅如此,我们还需要知道机器人的最小转弯半径。如果可以原地旋转,这固然很好。但是大多数机器人不一定可以做到这一点。

2、了解机器人的运动学模型

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

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

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

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

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

4、轨迹评价标准

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

5、测试代码

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

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/1104092.html

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

相关文章

入侵检测代码

在人工智能中有个入侵检测&#xff1a;当检测到的目标位于指定区域内才算是入侵&#xff0c;思路很简单&#xff0c;判断相关坐标即可&#xff1a; from matplotlib import pyplot as plt, patches from shapely.geometry import Polygon, Pointdef is_intrusion(target_box, …

HTML基础入门03

1.表单标签 表单是让用户输入信息的重要途径. 分成两个部分: 表单域: 包含表单元素的区域. 重点是 form 标签. 表单控件: 输入框, 提交按钮等. 重点是 input 标签. 1.1form标签 <form action"test08.html">hello world </form> 描述了要把数据按照什…

特斯拉pre-test (Go)

特斯拉pre-test &#xff08;Go&#xff09; 1 Q12 Q23 Q3 1 Q1 原文&#xff1a; You are given an implementation of a function Solution that, given a positive integer N, prints to standard output another integer, which was formed by reversing a decimal repres…

互联网Java工程师面试题·Java 总结篇·第五弹

目录 47、Java 语言如何进行异常处理&#xff0c;关键字&#xff1a;throws、throw、try、catch、finally 分别如何使用&#xff1f; 48、运行时异常与受检异常有何异同&#xff1f; 49、列出一些你常见的运行时异常&#xff1f; 50、阐述 final、finally、finalize 的区别…

【Java学习之道】指引篇:从入门到入世

引言 你是否曾为找不到适合自己的Java学习之路而烦恼&#xff1f;是否想摆脱混乱的Java知识体系&#xff0c;找到一条从入门到精通的捷径&#xff1f;来《Java学习之道》吧&#xff0c;本专栏为你量身打造&#xff0c;让我们一起轻松踏上Java学习之旅&#xff01; 第一章、Jav…

AD620A运算放大器的原理、应用和性能特点 | 百能云芯

在电子领域&#xff0c;AD620A是一种广泛应用的运算放大器&#xff0c;也被称为运放。它在信号放大、传感器接口和测量应用中扮演着重要的角色。接下来云芯将带您深入探讨AD620A运放的原理、应用领域以及性能特点&#xff0c;以帮助您更好地理解它的作用和价值。 AD620A是一种精…

CentOS有IP地址,连接不上Xshell或使用Xshell时突然断开

问题原因&#xff1a;未在电脑主机的网络中进行IP地址配置 解决办法&#xff1a; 1.打开控制面板&#xff0c;选择‘网络与共享中心’ 2.选择“更改适配器设置” 3.右键点击以太网3“属性” 4.选择协议版本4&#xff0c;点击属性 5.IP地址填写CentOS的IP地址&#xff1a;192.…

微信小程序进阶——Flex弹性布局轮播图会议OA项目(首页)

目录 一、Flex弹性布局 1.1 什么是Flex弹性布局 1.1.1 详解 1.1.2 图解 1.1.3 代码演示效果 1.2 Flex弹性布局的核心概念 1.3 Flex 弹性布局的常见属性 1.4 Flex弹性布局部分属性详解 1.4.1 flex-direction属性 1.4.2 flex-wrap属性 1.4.3 flex-flow属性 1.4.4 ju…

Redis数据结构之quicklist

前言 为了节省内存&#xff0c;Redis 推出了 ziplist 数据类型&#xff0c;采用一种更加紧凑的方式来存储 hash、zset 元素。因为查找的时间复杂度是 O(N)&#xff0c;且写入需要重新分配内存&#xff0c;所以它仅适用于小数据量的存储&#xff0c;而且它还存在 连锁更新 的风…

Redis AOF持久化和ReWrite

前言 Redis 的 RDB 持久化机制简单直接&#xff0c;把某一时刻的所有键值对以二进制的方式写入到磁盘&#xff0c;特点是恢复速度快&#xff0c;尤其适合数据备份、主从复制场景。但如果你的目的是要保证数据可靠性&#xff0c;RDB 就不太适合了&#xff0c;因为 RDB 持久化不…

Epoch、批量大小、迭代次数

梯度下降 它是 机器学习中使用的迭代 优化算法&#xff0c;用于找到最佳结果&#xff08;曲线的最小值&#xff09;。 坡度 是指 斜坡的倾斜度或倾斜度 梯度下降有一个称为 学习率的参数。 正如您在上图&#xff08;左&#xff09;中看到的&#xff0c;最初步长较大&#…

2023年中国半导体缺陷检测设备市场规模及发展趋势分析[图]

前道检测设备帮助晶圆厂在更快时间内提升芯片良率&#xff0c;按功能可分为参数量测、缺陷检测。前道检测设备按功能可分为参数量测、缺陷检测。 半导体缺陷检测设备分类 资料来源&#xff1a;共研产业咨询&#xff08;共研网&#xff09; 2023-2029年中国半导体缺陷检测设备行…

libcurl库使用

libcurl介绍 libcurl是一个跨平台的网络协议库&#xff0c;支持http, https,ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权&#xff0c;HTTP POST,HTTP PUT, FTP 上传, HTTP基本表单上传&#xff0c;代理&#xff0c;cookies和用户认证。 基本…

linux加密和安全

sudo实现授权 添加 vim /etc/sudoers luo ALL(root) /usr/bin/mount /deb/cdrom /mnt/ 切换luo用户使用 sudo mount /dev/cdrom /mnt %sudo ALL(ALL:ALL) ALL %sudo 表示该规则适用于sudo用户组中的所有成员。 ALL(ALL:ALL) 表示可以在任何主机上&#xff0c;以任何用户身份来…

2023.10.17 关于 wait 和 notify 的使用

目录 引言 方法的使用 引入实例&#xff08;wait 不带参数版本&#xff09; wait 方法执行流程 wait 和 notify 组合实例 wait 带参数版本 notify 和 notifyAll 的区别 经典例题 总结 引言 线程最大的问题是抢占式执行&#xff0c;随机调度虽然线程在内核里的调度是随…

UITesting 界面测试

1. 创建界面测试视图 UITestingBootcampView.swift import SwiftUI/// 界面测试 ViewModel class UITestingBootcampViewModel: ObservableObject{let placeholderText: String "Add name here..."Published var textFiledText: String ""Published var…

CVE-2021-26084 漏洞分析

基础知识 Velocity .vm 结尾的文件一般为Velocity模板文件$action $action 是 velocity 上下⽂中的⼀个变量&#xff0c;⼀般在进⾏模板渲染前会设置到 context ⾥⾯。$action 是当前访问路由对应的具体 Action 类。$action.xxx 表⽰取对应 Action 类的 xxx 属性值 ${} 和 $!…

Kotlin中的字符串基本操作

字符串定义&#xff1a; val str: String "Hello World"val str1 "Hello World"获取字符串的长度&#xff1a; println(str.length)通过索引方式访问某个字符&#xff0c;索引从0开始&#xff1a; println(str[4])通过for循环迭代字符串&#xff1a; for…

Python-Python高阶技巧:闭包、装饰器、设计模式、多线程、网络编程、正则表达式、递归

版本说明 当前版本号[20231018]。 版本修改说明20231018初版 目录 文章目录 版本说明目录Python高阶技巧闭包简单闭包修改外部函数变量的值实现以下atm取钱的闭包实现了闭包注意事项 装饰器装饰器的一般写法&#xff08;闭包写法&#xff09;装饰器的语法糖写法 设计模式单例…

微信小程序中如何使用fontawesome6的免费图标

一、官网下载fontawesome6 Download Font Awesome Free or Pro | Font Awesome 二、使用transfer编码成Base64 transfer打开官网&#xff1a;Online font-face generator — Transfonter 首先先把刚刚下载的fontawesome6解压&#xff0c;将文件夹中的字体上传&#xff08;点…