DWA算法是局部路径规划算法,在全局路径规划算法完成后,DWA算法能够根据当前小车(机器人)位置、障碍物、终点的位置进行控制空间(速度、角速度)的采用,从而完成局部路径规划。
DWA算法流程:
初始化一一小车最大最小速度、加速度,评价函数权重等循环
{
判断是否到达目的地
计算当前采样的速度范围(动态窗口)
遍历所有速度v&w,根据模型模拟一段时间的路径根据评价函数打分(包括评价函数、归一化、权重)选取最优解——v&w,下发给运动底盘
小车继续移动
}
下面是DWA算法的代码实现,主要步骤给了注释:
变量定义:
#include <iostream>
#include <vector>
using namespace std;
#define M_PI 3.1415927
#define MAX_VELOCITY 1.0
#define MIN_VELOCITY 0
#define MAX_OMEGA 20.0 / 180.0 * M_PI
#define MIN_OMEGA 0
#define MAX_ACCELERATE 0.2
#define MAX_ACCOMEGA 50.0 / 180.0 * M_PI
#define SAMPLING_VELOCITY 0.01
#define SAMPLING_OMEGA 1 / 180.0 * M_PI
#define DT 0.1
#define PREDICT_TIME 3.0
#define WEIGHT_HEADING 0.05
#define WEIGHT_CLEARANCE 0.2
#define WEIGHT_VELOCITY 0.1
#define GOAL_X 10
#define GOAL_Y 10
#define ROBOT_RADIUS 0.5
struct RobotState
{
float xPosition, yPosition, orientation, velocity, omega;
};
int obstacle[18][2] = { { 0, 2 },
{ 4, 2 },
{ 4, 4 },
{ 5, 4 },
{ 5, 5 },
{ 5, 6 },
{ 5, 9 },
{ 8, 8 },
{ 8, 9 },
{ 7, 9 },
{ 6, 5 },
{ 6, 3 },
{ 6, 8 },
{ 6, 7 },
{ 7, 4 },
{ 9, 8 },
{ 9, 11 },
{ 9, 6 } };
struct EvaluationPara
{
float heading, clearance, velocity, v, w;
};
具体实现:
#include <iostream>
#include "Constant.h"
#include <numeric>
#include <fstream>
using namespace std;
vector<float> DynamicWindowApproach(RobotState rState, int obs[][2], int target[]);
RobotState Motion(RobotState curState, float velocity, float omega);
vector<float> CreateDW(RobotState state);
vector<RobotState> GenerateTraj(RobotState initState, float vel, float ome);
float CalcHeading(RobotState rState, int goal[]);
float CalcClearance(RobotState rState, int obs[][2]);
float CalcBreakingDist(float velo);
void main()
{
RobotState currentState = { 0, 0, M_PI / 2, 0, 0 };
int goal[2] = { GOAL_X, GOAL_Y };
vector<RobotState> path;
cout << "Begin!" << endl;
int i = 0;
while (1)
{
if (currentState.xPosition < (goal[0] + 0.1) && currentState.xPosition > (goal[0] - 0.1) && currentState.yPosition < (goal[1] + 0.1) && currentState.yPosition > (goal[1] - 0.1))
{
cout << "Reach the Goal!" << endl;
break;
}
vector<float> selectedVelocity = DynamicWindowApproach(currentState, obstacle, goal);
currentState = Motion(currentState, selectedVelocity[0], selectedVelocity[1]);
path.push_back(currentState);
cout << selectedVelocity[0] << " " << selectedVelocity[1] << " ";
cout << currentState.xPosition << " " << currentState.yPosition << endl;
}
ofstream file("map.txt");
for (vector<RobotState>::iterator i = path.begin(); i < path.end(); i++)
{
file << i->xPosition << " " << i->yPosition << endl;
}
file.close();
system("pause");
}
vector<float> DynamicWindowApproach(RobotState rState, int obs[][2], int target[])
{
vector<float> velocityAndOmegaRange = CreateDW(rState);
vector<EvaluationPara>evalParas;
float sumHeading = 0;
float sumClearance = 0;
float sumVelocity = 0;
for (double v = velocityAndOmegaRange[0]; v < velocityAndOmegaRange[1]; v += SAMPLING_VELOCITY)
{
for (double w = velocityAndOmegaRange[2]; w < velocityAndOmegaRange[3]; w += SAMPLING_OMEGA)
{
vector<RobotState> trajectories = GenerateTraj(rState, v, w);
EvaluationPara tempEvalPara;
float tempClearance = CalcClearance(trajectories.back(), obstacle);
float stopDist = CalcBreakingDist(v);
if (tempClearance > stopDist)
{
tempEvalPara.heading = CalcHeading(trajectories.back(), target);
tempEvalPara.clearance = tempClearance;
tempEvalPara.velocity = abs(v);
tempEvalPara.v = v;
tempEvalPara.w = w;
sumHeading = sumHeading + tempEvalPara.heading;
sumClearance = sumHeading + tempEvalPara.clearance;
sumVelocity = sumVelocity + tempEvalPara.velocity;
evalParas.push_back(tempEvalPara);
}
}
}
float selectedVelocity = 0;
float selectedOmega = 0;
float G = 0;
for (vector<EvaluationPara>::iterator i = evalParas.begin(); i < evalParas.end(); i++)
{
float smoothHeading = i->heading / sumHeading;
float smoothClearance = i->clearance / sumClearance;
float smoothVelocity = i->velocity / sumVelocity;
float tempG = WEIGHT_HEADING*smoothHeading + WEIGHT_CLEARANCE*smoothClearance + WEIGHT_VELOCITY*smoothVelocity;
if (tempG > G)
{
G = tempG;
selectedVelocity = i->v;
selectedOmega = i->w;
}
}
vector<float> selVelocity(2);
selVelocity[0] = selectedVelocity;
selVelocity[1] = selectedOmega;
return selVelocity;
}
vector<float> CreateDW(RobotState curState)
{
vector<float> dw(4);
float tmpMinVelocity = curState.velocity - MAX_ACCELERATE*DT;
float tmpMaxVelocity = curState.velocity + MAX_ACCELERATE*DT;
float tmpMinOmega = curState.omega - MAX_ACCOMEGA*DT;
float tmpMaxOmega = curState.omega + MAX_ACCOMEGA*DT;
dw[0] = tmpMinVelocity > MIN_VELOCITY ? tmpMinVelocity : MIN_VELOCITY;
dw[1] = tmpMaxVelocity < MAX_VELOCITY ? tmpMaxVelocity : MAX_VELOCITY;
dw[2] = tmpMinOmega;
dw[3] = tmpMaxOmega < MAX_OMEGA ? tmpMaxOmega : MAX_OMEGA;
return dw;
}
RobotState Motion(RobotState curState, float velocity, float omega)
{
RobotState afterMoveState;
afterMoveState.xPosition = curState.xPosition + velocity*DT*cos(curState.orientation);
afterMoveState.yPosition = curState.yPosition + velocity*DT*sin(curState.orientation);
afterMoveState.orientation = curState.orientation + omega * DT;
afterMoveState.velocity = velocity;
afterMoveState.omega = omega;
return afterMoveState;
}
vector<RobotState> GenerateTraj(RobotState initState, float vel, float ome)
{
RobotState tempState = initState;
vector<RobotState> trajectories;
float time = 0;
trajectories.push_back(initState);
while (time < PREDICT_TIME)
{
tempState = Motion(tempState, vel, ome);
trajectories.push_back(tempState);
time += DT;
}
return trajectories;
}
float CalcHeading(RobotState rState, int goal[])
{
float heading;
float dy = goal[1] - rState.yPosition;
float dx = goal[0] - rState.xPosition;
float goalTheta = atan2(dy, dx);
float targetTheta;
if (goalTheta > rState.orientation)
{
targetTheta = goalTheta - rState.orientation;
}
else
{
targetTheta = rState.orientation - goalTheta;
}
heading = 180 - targetTheta / M_PI * 180;
return heading;
}
float CalcClearance(RobotState rState, int obs[][2])
{
float dist = 100;
float distTemp;
for (int i = 0; i < 18; i++)
{
float dx = rState.xPosition - obs[i][0];
float dy = rState.yPosition - obs[i][1];
distTemp = sqrt(pow(dx,2) + pow(dy,2)) - ROBOT_RADIUS;
if (dist > distTemp)
{
dist = distTemp;
}
}
if (dist >= 2 * ROBOT_RADIUS)
{
dist = 2 * ROBOT_RADIUS;
}
return dist;
}
float CalcBreakingDist(float velo)
{
float stopDist = 0;
while (velo > 0)
{
stopDist = stopDist + velo*DT;
velo = velo - MAX_ACCELERATE*DT;
}
return stopDist;
}
ROS 2D导航原理系列(六)|局部路径规划-DWA算法
DWA算法总结
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)