当前位置:   article > 正文

常用路径规划算法

常用路径规划算法

很全的资料(ROS实现):GitHub - ai-winter/ros_motion_planning: Motion planning and Navigation of AGV/AMR:ROS planner plugin implementation of A*, JPS, D*, LPA*, D* Lite, Theta*, RRT, RRT*, RRT-Connect, Informed RRT*, ACO, PSO, Voronoi, PID, DWA, APF etc.

 大佬博主博客:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法_自动驾驶驾驶动态规划算法-CSDN博客

一、基于图搜索的global planner

1、Dijkstra

参考文献:

[1]https://ieeexplore.ieee.org/document/736775

[2]https://ieeexplore.ieee.org/document/1690266

原文链接:Dijkstra算法图文详解-CSDN博客

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<iostream>
  5. #define Inf 0x3f3f3f3f
  6. using namespace std;
  7. int map[1005][1005];
  8. int vis[1005], dis[1005];
  9. int n, m;
  10. void Init()
  11. {
  12. memset(map, Inf, sizeof(map));
  13. for (int i = 1; i <= n; i++)
  14. {
  15. map[i][i] = 0;
  16. }
  17. }
  18. void Getmap()
  19. {
  20. int u, v, w;
  21. for (int t = 1; t <= m; t++)
  22. {
  23. scanf_s("%d%d%d", &u, &v, &w);
  24. if (map[u][v] > w)
  25. {
  26. map[u][v] = w;
  27. map[v][u] = w;
  28. }
  29. }
  30. }
  31. void Dijkstra(int u)
  32. {
  33. memset(vis, 0, sizeof(vis));
  34. for (int t = 1; t <= n; t++)
  35. {
  36. dis[t] = map[u][t];
  37. }
  38. vis[u] = 1;
  39. for (int t = 1; t < n; t++)
  40. {
  41. int minn = Inf, temp;
  42. for (int i = 1; i <= n; i++)
  43. {
  44. if (!vis[i] && dis[i] < minn)
  45. {
  46. minn = dis[i];
  47. temp = i;
  48. }
  49. }
  50. vis[temp] = 1;
  51. for (int i = 1; i <= n; i++)
  52. {
  53. if (map[temp][i] + dis[temp] < dis[i])
  54. {
  55. dis[i] = map[temp][i] + dis[temp];
  56. }
  57. }
  58. }
  59. }
  60. int main()
  61. {
  62. /*
  63. input;
  64. 5 4
  65. 1 2 3
  66. 2 3 4
  67. 3 4 1
  68. 4 1 8
  69. 2 4 2*/
  70. scanf_s("%d%d", &m, &n);//5,4
  71. Init();
  72. Getmap();
  73. Dijkstra(n);//4
  74. printf("%d\n", dis[1]);
  75. return 0;
  76. }

 

2、A* 家族

2.1A* 

参考文献:[1]https://www.roboticsproceedings.org/rss04/p28.pdf

  1. #include <stdio.h>
  2. #include <vector>
  3. using namespace std;
  4. #define ROWS 10
  5. #define COLS 10
  6. #define ZXDJ 10
  7. #define XXDJ 14
  8. enum direct { p_up, p_down, p_left, p_right, p_lup, p_ldown, p_rup, p_rdown };
  9. struct MyPoint {
  10. int row; //y
  11. int col; //x
  12. int f, g, h; //用来量化评估的
  13. void getF() { f = g + h; }
  14. };
  15. //树节点
  16. struct treeNode {
  17. MyPoint pos;
  18. treeNode* pParent;
  19. vector<treeNode*> child;
  20. };
  21. treeNode* createNode(MyPoint pos) {
  22. treeNode* pNew = new treeNode;
  23. //memset(pNew, 0, sizeof treeNode);//清空
  24. *pNew = { 0 };
  25. pNew->pos.row = pos.row;
  26. pNew->pos.col = pos.col;
  27. return pNew;
  28. }
  29. int getH(MyPoint pos, MyPoint endPos);
  30. int main() {
  31. //描述地图
  32. int map[ROWS][COLS] = {
  33. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  34. { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
  35. { 0, 1, 0, 1, 1, 0, 0, 0, 0, 0 },
  36. { 0, 1, 1, 0, 1, 0, 0, 0, 0, 0 },
  37. { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
  38. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  39. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  40. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
  41. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  42. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }
  43. };
  44. bool pathMap[ROWS][COLS] = { 0 };//全部都是false 没有走过
  45. //起点和终点
  46. MyPoint begPos = { 1, 1 };
  47. MyPoint endPos = { 6, 7 };
  48. pathMap[begPos.row][begPos.col] = true;//起点标记走过
  49. treeNode* pRoot = createNode(begPos);//起点成为树根
  50. //准备一个数组用来存储并获取f最小的点
  51. vector<treeNode*> buff;
  52. vector<treeNode*>::iterator it;
  53. vector<treeNode*>::iterator itMin;
  54. treeNode* pCurrent = pRoot;//当前点
  55. bool isFindEnd = false;
  56. //寻路
  57. while (1) {
  58. //当前点发散出8个点
  59. for (int i = 0; i < 8; i++) {
  60. treeNode* pTemp = createNode(pCurrent->pos);
  61. switch (i)
  62. {
  63. case p_up:
  64. pTemp->pos.row--;
  65. pTemp->pos.g += ZXDJ;
  66. break;
  67. case p_down:
  68. pTemp->pos.row++;
  69. pTemp->pos.g += ZXDJ;
  70. break;
  71. case p_left:
  72. pTemp->pos.col--;
  73. pTemp->pos.g += ZXDJ;
  74. break;
  75. case p_right:
  76. pTemp->pos.col++;
  77. pTemp->pos.g += ZXDJ;
  78. break;
  79. case p_lup:
  80. pTemp->pos.row--;
  81. pTemp->pos.col--;
  82. pTemp->pos.g += XXDJ;
  83. break;
  84. case p_ldown:
  85. pTemp->pos.row++;
  86. pTemp->pos.col--;
  87. pTemp->pos.g += XXDJ;
  88. break;
  89. case p_rup:
  90. pTemp->pos.row--;
  91. pTemp->pos.col++;
  92. pTemp->pos.g += XXDJ;
  93. break;
  94. case p_rdown:
  95. pTemp->pos.row++;
  96. pTemp->pos.col++;
  97. pTemp->pos.g += XXDJ;
  98. break;
  99. }//end of switch
  100. //能走的才考虑 已经走过的应该不考虑
  101. if (pathMap[pTemp->pos.row][pTemp->pos.col] == false &&
  102. map[pTemp->pos.row][pTemp->pos.col] == 0 &&
  103. pTemp->pos.row >= 0 && pTemp->pos.row < ROWS &&
  104. pTemp->pos.col >= 0 && pTemp->pos.col < COLS) {
  105. //计算h值
  106. pTemp->pos.h = getH(pTemp->pos, endPos);
  107. //计算f值
  108. pTemp->pos.getF();
  109. //入树
  110. pCurrent->child.push_back(pTemp);
  111. pTemp->pParent = pCurrent;
  112. //数组存储
  113. buff.push_back(pTemp);
  114. }
  115. else {//不能走
  116. //delete pTemp;//释放pTemp
  117. }
  118. }//end of for
  119. //找出buff中 f最小的节点
  120. itMin = buff.begin();//假设第一个的f值最小
  121. //从第一个找到最后一个
  122. for (it = buff.begin(); it != buff.end(); it++) {
  123. itMin = (((*itMin)->pos.f < (*it)->pos.f) ? itMin : it);
  124. }
  125. //pCurrent指向它
  126. pCurrent = *itMin;
  127. pathMap[pCurrent->pos.row][pCurrent->pos.col] = true;//标记走过
  128. printf("current(%d,%d)\n", pCurrent->pos.row, pCurrent->pos.col);
  129. //buff中删掉它
  130. buff.erase(itMin);
  131. //是否到达终点
  132. if (pCurrent->pos.row == endPos.row &&
  133. pCurrent->pos.col == endPos.col) {
  134. isFindEnd = true;
  135. break;
  136. }
  137. //是否buff空了
  138. if (buff.size() == 0) break;
  139. }//end of while
  140. if (isFindEnd) {
  141. printf("找到终点了!\n");
  142. while (pCurrent) {
  143. printf("(%d,%d)", pCurrent->pos.row, pCurrent->pos.col);
  144. pCurrent = pCurrent->pParent;
  145. }
  146. printf("\n");
  147. }
  148. while (1);
  149. return 0;
  150. }
  151. int getH(MyPoint pos, MyPoint endPos) {
  152. int x = ((pos.col > endPos.col) ? (pos.col - endPos.col) : (endPos.col - pos.col));
  153. int y = ((pos.row > endPos.row) ? (pos.row - endPos.row) : (endPos.row - pos.row));
  154. return (x + y) * ZXDJ;
  155. }

 

2.2动态A*(D*)

参考文献:https://ieeexplore.ieee.org/document/351061

  1. #pragma once
  2. #include<vector>
  3. #include<queue>
  4. #include<memory>
  5. #include<algorithm>
  6. #include<iostream>
  7. namespace DStar {
  8. enum State
  9. {
  10. New,
  11. Open,
  12. Closed
  13. };
  14. struct DNode {
  15. explicit DNode(int X, int Y, DNode* Next = nullptr) : x(X), y(Y), next(Next) {}
  16. DNode() = default;
  17. void setObstacle()
  18. {
  19. is_obstacle = true;
  20. }
  21. int x = 0;
  22. int y = 0;
  23. int H = 0; // distance to target
  24. int K = 0; //所有时刻最小的H!
  25. State state = New;
  26. DNode* next = nullptr;
  27. bool is_obstacle = false;
  28. };
  29. struct MyCompare
  30. {
  31. bool operator()(DNode* lhs, DNode* rhs) const {
  32. return lhs->K > rhs->K;
  33. }
  34. };
  35. class DStar {
  36. public:
  37. DStar(const std::vector<std::vector<int>> map) : Map(map), shortestPaths(map.size(), std::vector<DNode*>(map.front().size(), nullptr)) {}
  38. void find_first_path(const std::pair<int, int>& start, const std::pair<int, int>& target, const std::vector<std::pair<int, int>>& obstacles);
  39. ~DStar()
  40. {
  41. for (int i = 0; i < shortestPaths.size(); ++i)
  42. {
  43. for (int j = 0; j < shortestPaths.front().size(); ++j)
  44. {
  45. if (shortestPaths[i][j])
  46. delete shortestPaths[i][j];
  47. }
  48. }
  49. }
  50. private:
  51. int cost(DNode* lhs, DNode* rhs) const;
  52. void insert(DNode* node, int Cost);
  53. //核心函数
  54. int process_state();
  55. int modify(DNode* node);
  56. void setObstacles(const std::vector<std::pair<int, int>>& obstacles);
  57. private:
  58. const static int _cost_low = 10;
  59. const static int _cost_high = 14;
  60. const static int _cost_max = 65536;
  61. std::priority_queue<DNode*, std::vector<DNode*>, MyCompare> openlist;
  62. std::vector<std::vector<int>> Map;
  63. std::vector<std::vector<DNode*>> shortestPaths; //保存每个节点到终点的最短路径信息
  64. };
  65. int DStar::cost(DNode* lhs, DNode* rhs) const
  66. {
  67. if (lhs->is_obstacle || rhs->is_obstacle)
  68. return _cost_max;
  69. if (lhs->x != rhs->x && lhs->y != rhs->y)
  70. return _cost_high;
  71. else
  72. return _cost_low;
  73. }
  74. void DStar::insert(DNode* node, int new_H)
  75. {
  76. new_H = (new_H >= _cost_max) ? _cost_max : new_H;
  77. if (node->state == New)
  78. {
  79. node->H = new_H;
  80. node->K = new_H;
  81. node->state = Open;
  82. shortestPaths[node->x][node->y] = node;
  83. openlist.push(node);
  84. }
  85. else if (node->state == Open) //节点已经在openlist中 那么只需要改变对应openlist位置的节点的H和K即可
  86. {
  87. node->H = new_H;
  88. node->K = std::min(node->K, new_H);
  89. }
  90. else
  91. {
  92. node->K = std::min(node->H, new_H);
  93. node->H = new_H;
  94. node->state = Open;
  95. openlist.push(node);
  96. }
  97. }
  98. int DStar::process_state()
  99. {
  100. DNode* cur_min = openlist.top();
  101. if (!cur_min)
  102. return -1;
  103. openlist.pop();
  104. cur_min->state = Closed;
  105. int K_old = cur_min->K;
  106. if (K_old < cur_min->H)
  107. {
  108. for (int i = cur_min->x - 1; i <= cur_min->x + 1; ++i)
  109. {
  110. for (int j = cur_min->y - 1; j <= cur_min->y + 1; ++j)
  111. {
  112. if (i >= 0 && j >= 0 && i < Map.size() && j < Map.front().size() && shortestPaths[i][j])
  113. {
  114. if (i == cur_min->x && j == cur_min->y)
  115. continue;
  116. if (shortestPaths[i][j]->H <= K_old && cur_min->H > shortestPaths[i][j]->H + cost(cur_min, shortestPaths[i][j]))
  117. {
  118. cur_min->H = shortestPaths[i][j]->H + cost(cur_min, shortestPaths[i][j]);
  119. cur_min->next = shortestPaths[i][j];
  120. }
  121. }
  122. }
  123. }
  124. }
  125. if (K_old == cur_min->H)
  126. {
  127. for (int i = cur_min->x - 1; i <= cur_min->x + 1; ++i)
  128. {
  129. for (int j = cur_min->y - 1; j <= cur_min->y + 1; ++j)
  130. {
  131. if (i >= 0 && j >= 0 && i < Map.size() && j < Map.front().size())
  132. {
  133. if (i == cur_min->x && j == cur_min->y)
  134. continue;
  135. if (!shortestPaths[i][j] && !Map[i][j]) //表示当前节点为New
  136. {
  137. DNode* neighbor = new DNode(i, j, cur_min);
  138. insert(neighbor, cur_min->H + cost(neighbor, cur_min));
  139. }
  140. else if (shortestPaths[i][j] && !shortestPaths[i][j]->is_obstacle)
  141. {
  142. if ((shortestPaths[i][j]->next == cur_min && shortestPaths[i][j]->H != cur_min->H + cost(shortestPaths[i][j], cur_min))
  143. || (shortestPaths[i][j]->next != cur_min && shortestPaths[i][j]->H > cur_min->H + cost(shortestPaths[i][j], cur_min)))
  144. {
  145. insert(shortestPaths[i][j], cur_min->H + cost(shortestPaths[i][j], cur_min));
  146. shortestPaths[i][j]->next = cur_min;
  147. }
  148. }
  149. }
  150. }
  151. }
  152. }
  153. else
  154. {
  155. //传递raise状态
  156. for (int i = cur_min->x - 1; i <= cur_min->x + 1; ++i)
  157. {
  158. for (int j = cur_min->y - 1; j <= cur_min->y + 1; ++j)
  159. {
  160. if (i == cur_min->x && j == cur_min->y)
  161. continue;
  162. if (i >= 0 && j >= 0 && i < Map.size() && j < Map.front().size())
  163. {
  164. if (!shortestPaths[i][j] && !Map[i][j]) //表示当前节点为New
  165. {
  166. DNode* neighbor = new DNode(i, j, cur_min);
  167. insert(neighbor, cur_min->H + cost(neighbor, cur_min));
  168. }
  169. else if (shortestPaths[i][j] && !shortestPaths[i][j]->is_obstacle)
  170. {
  171. if (shortestPaths[i][j]->next == cur_min && shortestPaths[i][j]->H != cur_min->H + cost(cur_min, shortestPaths[i][j]))
  172. {
  173. insert(shortestPaths[i][j], cur_min->H + cost(cur_min, shortestPaths[i][j]));
  174. }
  175. else
  176. {
  177. if (shortestPaths[i][j]->next != cur_min)
  178. {
  179. int temp = (shortestPaths[i][j]->H + cost(shortestPaths[i][j], cur_min) >= _cost_max) ? _cost_max : shortestPaths[i][j]->H + cost(shortestPaths[i][j], cur_min);
  180. if (cur_min->H < temp)
  181. insert(cur_min, cur_min->H);
  182. else if (shortestPaths[i][j]->next != cur_min && cur_min->H > shortestPaths[i][j]->H + cost(shortestPaths[i][j], cur_min)
  183. && shortestPaths[i][j]->state == Closed && shortestPaths[i][j]->K > K_old)
  184. {
  185. insert(shortestPaths[i][j], shortestPaths[i][j]->H);
  186. }
  187. }
  188. }
  189. }
  190. }
  191. }
  192. }
  193. }
  194. return openlist.top()->K;
  195. }
  196. void DStar::setObstacles(const std::vector<std::pair<int, int>>& obstacles)
  197. {
  198. if (obstacles.empty())
  199. return;
  200. for (const auto& rhs : obstacles)
  201. {
  202. if (shortestPaths[rhs.first][rhs.second])
  203. {
  204. shortestPaths[rhs.first][rhs.second]->is_obstacle = true;
  205. shortestPaths[rhs.first][rhs.second]->H = _cost_max;
  206. }
  207. Map[rhs.first][rhs.second] = '#';
  208. }
  209. }
  210. int DStar::modify(DNode* node)
  211. {
  212. DNode* next = node->next;
  213. openlist.push(next);
  214. int k_old;
  215. do {
  216. k_old = process_state();
  217. if (k_old == -1)
  218. break;
  219. } while (node->H == _cost_max || k_old < node->H);
  220. return k_old;
  221. }
  222. void DStar::find_first_path(const std::pair<int, int>& start, const std::pair<int, int>& target,
  223. const std::vector<std::pair<int, int>>& obstacles)
  224. {
  225. DNode* end = new DNode(target.first, target.second);
  226. shortestPaths[target.first][target.second] = end;
  227. openlist.push(end);
  228. while (true)
  229. {
  230. process_state();
  231. if (shortestPaths[start.first][start.second] && shortestPaths[start.first][start.second]->state == Closed)
  232. break;
  233. }
  234. setObstacles(obstacles);
  235. DNode* begin = shortestPaths[start.first][start.second];
  236. int i;
  237. while (begin)
  238. {
  239. Map[begin->x][begin->y] = '*';
  240. if (begin->next && begin->next->is_obstacle)
  241. {
  242. i = modify(begin);
  243. if (i == -1)
  244. {
  245. break;
  246. }
  247. }
  248. begin = begin->next;
  249. }
  250. if (i == -1)
  251. {
  252. std::cout << "No New Path To Target" << std::endl;
  253. return;
  254. }
  255. else
  256. {
  257. for (const auto& i : Map)
  258. {
  259. for (const auto& j : i)
  260. {
  261. if (j > 1)
  262. std::cout << char(j) << " ";
  263. else
  264. std::cout << j << " ";
  265. }
  266. std::cout << std::endl;
  267. }
  268. }
  269. }
  270. }
  1. #include <time.h>
  2. #include"DStar.h"
  3. int main()
  4. {
  5. std::vector<std::vector<int>> map2(25, std::vector<int>(25));
  6. for (int j = 3; j < 8; ++j)
  7. map2[6][j] = 1;
  8. for (int j = 4; j < 7; ++j)
  9. map2[7][j] = 1;
  10. clock_t start = clock();
  11. DStar::DStar d(map2);
  12. d.find_first_path({ 3, 2 }, { 23, 16 }, { {12, 4}, {12, 5}, {12, 6}, {12, 7}, {12, 8}, {12, 9}, {12, 10}, {12, 11}, {11, 7}, {13, 3}, {10, 6}, {14, 5}, {6, 2} });
  13. clock_t ends = clock();
  14. std::cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC * 1000 << "ms" << std::endl;
  15. return 0;
  16. }

原文链接:基于C++的D*算法详解_dstar算法-CSDN博客

2.3 Field D∗

参考文献:https://www.ri.cmu.edu/pub_files/pub4/ferguson_david_2006_3/ferguson_david_2006_3.pdf

原文链接:Field D*路径规划算法_field d*-CSDN博客

2.4Theta*

参考文献:http://idm-lab.org/bib/abstracts/papers/aaai07a.pdf

扩展:Lazy Theta* 

2.5ARA*和AD*

参考文献:https://www.sciencedirect.com/science/article/pii/S000437020800060X

2.6A*结合voronoi图

参考文献:https://ieeexplore.ieee.org/document/4621302

2.7Hybrid A*

参考文献:http://robots.stanford.edu/papers/junior08.pdf

3、State Lattice

参考文献:https://www.cs.cmu.edu/~alonzo/pubs/papers/TrajGenSubmitFinalCompressed.pdf

二、基于采样的global planner

1、PRM(Probabilistic Roadmap Method)

 参考文献:Sci-Hub | Probabilistic roadmaps for path planning in high-dimensional configuration spaces | 10.1109/70.508439

2、RRT 

参考文献:Randomized kinodynamic planning | IEEE Conference Publication | IEEE Xplore 

3、RRT* 

参考文献: Optimal motion planning with the half-car dynamical model for autonomous high-speed driving | IEEE Conference Publication | IEEE Xplore

三、基于插值的曲线planner 

1、Lines and Circles 

参考文献: Sci-Hub | [IEEE 2013 American Control Conference (ACC) - Washington, DC (2013.6.17-2013.6.19)] 2013 American Control Conference - Optimal motion planning with the half-car dynamical model for autonomous high-speed driving | 10.1109/acc.2013.6579835

2、 Clothoid Curves

参考文献: Real-time Approximation of Clothoids With Bounded Error for Path Planning Applications | IEEE Journals & Magazine | IEEE Xplore

 3、多项式差值曲线(Polynomial Curves)

参考文献:https://www.ri.cmu.edu/pub_files/2012/5/ICRA12_xuwd_Final.pdf

 4. 贝塞尔曲线(Bézier Curves)

参考文献:Continuous curvature planning with obstacle avoidance capabilities in urban scenarios | IEEE Conference Publication | IEEE Xplore

5. 样条曲线(Spline Curves)

参考文献: Pythagorean—Hodograph Curves

四、基于数值优化的planner(最优化理论)

       需要构建优化模型,设置目标函数,并考虑各种约束,比如运动学、动力学、障碍物、舒适性、安全性等等。 

五、总结

      最常用的是基于插值的曲线路径生成,其次是基于图搜索的路径规划,其中最长用的是lattice planner。

     从控制的角度来看,必须考虑多种约束,从车辆运动学限制到乘客舒适度。最近的发展旨在在规划阶段考虑这些限制因素,从而实现平滑和可实现的轨迹,减少控制阶段的限制。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/623604
推荐阅读
相关标签
  

闽ICP备14008679号