当前位置:   article > 正文

【MATLAB】PRM+A star(A*)寻路算法改进_a星算法改进matlab代码

a星算法改进matlab代码

目录

1 原算法链接

2 改进部分

3 改进代码运行效果


1 原算法链接

【MATLAB】PRM+A star(A*)寻路算法实现_一只小白白的博客-CSDN博客

2 改进部分

原算法是在PRM建立好图G后再确定起始点和终止点,这样就存在一个问题,就是原算法没有将设定的起始点和终止点信息纳入图G中,导致A*搜索出来的路径虽然是最优的,但其实那段起始路径(连接起始点和G中起始点的路径)和终止的路径(连接终止点和G中终止点的路径)不是全局最优的,原算法寻路效果如下:

 改进方法也很简单,将设定的起始点和终止点纳入图G中,原本nxn的图变为了(n+2)x(n+2)的图,改进后的PRM算法代码如下:

  1. function [allV,graph,Index_startInPRM,Index_endInPRM]= build_PRM(n,k,QLIST,MAX_X,MAX_Y,qset)
  2. % 随机生成节点数组
  3. V=[];
  4. % 初始化图的二维数组(n+2 * n+2)----包含起始点和终止点qset
  5. G=zeros(n+2);
  6. % 障碍物个数
  7. Obstacle_Num = size(QLIST,1);
  8. %% 绘制障碍物模型
  9. for i=1:Obstacle_Num
  10. Q = [QLIST(i,1:4);QLIST(i,5:8)];
  11. fill(Q(1,:),Q(2,:),'k');
  12. hold on
  13. end
  14. %% 初始化图G的相邻节点间边的权值
  15. for i=1:n+2
  16. for j=1:n+2
  17. if ~isequal(i,j)
  18. G(i,j)=inf;
  19. end
  20. end
  21. end
  22. %% 随机生成n个节点,判断是否落在障碍物上,如果不在障碍物中,将其加入节点数组V中
  23. % 将初始点和终止点先加入V中
  24. V = [V,qset(:,1)];
  25. V = [V,qset(:,2)];
  26. % 返回搜索初始点和终止点的索引
  27. Index_startInPRM = 1;
  28. Index_endInPRM = 2;
  29. % 随机生成节点加入V中
  30. if Obstacle_Num==0
  31. while size(V,2)<n+2
  32. qrand=[MAX_X*rand;MAX_Y*rand];
  33. V=[V,qrand]; % 由于没有障碍物,直接填充即可
  34. end
  35. else
  36. while size(V,2)<n+2
  37. qrand=[MAX_X*rand;MAX_Y*rand];
  38. % 存在障碍物时,需要剔除随机生成在障碍物上的点,保留符合条件的点
  39. for m=1:Obstacle_Num
  40. Q = [QLIST(m,1:4);QLIST(m,5:8)];
  41. Q = [Q,Q(:,1)];
  42. [in,on] = inpolygon(qrand(1),qrand(2),Q(1,:),Q(2,:));
  43. if (in==1 || on==1)
  44. plot(qrand(1),qrand(2),'r*'); hold on;
  45. break;
  46. elseif m==Obstacle_Num
  47. V=[V,qrand];
  48. plot(qrand(1),qrand(2),'k*'); hold on;
  49. end
  50. end
  51. end
  52. end
  53. %% 根据上面生成的n个节点,填充图G的数据
  54. if Obstacle_Num==0
  55. for j=1:size(V,2)
  56. % 找出当前节点j邻近的k个节点,找出的邻近点包括自己,且为第一个索引值,即ind(1)
  57. ind= knnsearch( V', V(:,j)', 'k',k+1);
  58. ind_temp = [];
  59. for i=2:size(ind,2)
  60. % 保证邻近节点Nq不包括自己
  61. ind_temp = [ind_temp,ind(i)];
  62. Nq(:,i-1)= V(:,ind(i));
  63. end
  64. ind = ind_temp;
  65. % 遍历这k个节点,因为没有障碍物,所以直接把当前节点与其邻近节点相连即可
  66. for i=1:size(Nq,2)
  67. G(j,ind(i))=1; % 如果一直到最后一个障碍物都没有交叉,则此邻近节点与j节点可通行,权值设为1
  68. G(ind(i),j)=1;
  69. plot([V(1,j),Nq(1,i)],[V(2,j),Nq(2,i)],'g--');
  70. pause(0.01);
  71. hold on
  72. end
  73. end % 结束 for 循环
  74. else
  75. for j=1:size(V,2)
  76. plot(V(1,j),V(2,j),'rs'); hold on;
  77. % 找出当前节点j邻近的k个节点,找出的邻近点包括自己,且为第一个索引值,即ind(1)
  78. ind= knnsearch( V', V(:,j)', 'k',k+1);
  79. ind_temp = [];
  80. % 保证邻近节点Nq不包括自己
  81. for i=2:size(ind,2)
  82. ind_temp = [ind_temp,ind(i)];
  83. Nq(:,i-1)= V(:,ind(i));
  84. plot(Nq(1,i-1),Nq(2,i-1),'bs'); hold on;
  85. end
  86. ind = ind_temp;
  87. % 遍历这k个节点,如果与父节点连线不与障碍物碰撞,则G中相应权值为1,代表两节点之间可通行
  88. for i=1:size(Nq,2)
  89. % 遍历所有障碍物,判断第i个邻近节点与j节点的连线与障碍物是否有交叉
  90. for m=1:Obstacle_Num
  91. Q = [QLIST(m,1:4);QLIST(m,5:8)];
  92. if isIntersection( V(:,j),Nq(:,i),Q )==1
  93. % plot([V(1,j),Nq(1,i)],[V(2,j),Nq(2,i)],'r--');
  94. break; % 如果有交叉,直接break,进入下一个邻近节点的判断
  95. elseif m==Obstacle_Num
  96. G(j,ind(i))=1; % 如果一直到最后一个障碍物都没有交叉,则此邻近节点与j节点可通行,权值设为1
  97. G(ind(i),j)=1;
  98. plot([V(1,j),Nq(1,i)],[V(2,j),Nq(2,i)],'g--');
  99. % pause(0.01);
  100. hold on
  101. end
  102. end
  103. end
  104. end % 结束 for 循环
  105. end % 结束 if和else 判断
  106. % 输出图G和节点信息V
  107. allV=V;
  108. graph=G;
  109. end

A*算法部分代码不用改动,主函数改动如下:

  1. %%----------------------------------------------
  2. % Author: Yinsong Qu
  3. % Date: 8,14,2023
  4. % Email: quyinsong@hrbeu.edu.cn
  5. %%----------------------------------------------
  6. clc
  7. clear all
  8. close all
  9. %% 1. Run PRM
  10. %get the graph by running PRM and map lot
  11. %V is all the qs'
  12. qset=[3 19;3 19]; % 1st column: q_initial, 2nd: q_goal
  13. n=50; % 随机生成的节点数
  14. k=20; % 每个节点最大允许的邻近子节点数量
  15. % 多边形表示的障碍物
  16. Q1=[1 2 2 1;1 1 2 2]; % 障碍物
  17. Q2=[10 15 15 10;
  18. 10 10 15 15]; % 障碍物
  19. Q3=[5 10 10 5;
  20. 5 5 10 10]; % 障碍物
  21. Q4=[2 4 4 2;14 14 16 16]; % 障碍物
  22. Q5=[4 6 6 4;16 16 18 18]; % 障碍物
  23. Q6=[16 18 18 16;4 4 6 6]; % 障碍物
  24. Q7=[12 14 14 12;2 2 4 4]; % 障碍物
  25. Q8=[6 8 8 6;12 12 14 14]; % 障碍物
  26. % 障碍物列表
  27. QLIST = [Q1(1,1:4),Q1(2,1:4);
  28. Q2(1,1:4),Q2(2,1:4);
  29. Q3(1,1:4),Q3(2,1:4);
  30. Q4(1,1:4),Q4(2,1:4);
  31. Q5(1,1:4),Q5(2,1:4);
  32. Q6(1,1:4),Q6(2,1:4);
  33. Q7(1,1:4),Q7(2,1:4);
  34. Q8(1,1:4),Q8(2,1:4);];
  35. % QLIST = [];
  36. % QLIST = [Q2(1,1:4),Q2(2,1:4);Q3(1,1:4),Q3(2,1:4)];
  37. % 设置地图范围
  38. MAX_X = 20;
  39. MAX_Y = 20;
  40. % 绘制地图,起始点和终止点
  41. figure(1)
  42. set(gcf, 'Renderer', 'painters');
  43. set(gcf, 'Position', [500, 50, 700, 700]);
  44. set(gca, 'XTick', 0:1:MAX_X);
  45. set(gca, 'YTick', 0:1:MAX_Y);
  46. grid on;
  47. axis equal;
  48. axis ([0 MAX_X 0 MAX_Y ]);
  49. hold on;
  50. LL = 0.3;
  51. fill([qset(1,1)-LL,qset(1,1)+LL,qset(1,1)+LL,qset(1,1)-LL],[qset(2,1)-LL,qset(2,1)-LL,qset(2,1)+LL,qset(2,1)+LL],'r'); % 起始点
  52. fill([qset(1,2)-LL,qset(1,2)+LL,qset(1,2)+LL,qset(1,2)-LL],[qset(2,2)-LL,qset(2,2)-LL,qset(2,2)+LL,qset(2,2)+LL],'b'); % 终点
  53. % 创建随机路图
  54. [V,G,Index_startInPRM,Index_endInPRM]=build_PRM(n,k,QLIST,MAX_X,MAX_Y,qset);
  55. %% 1. 利用A star算法寻路
  56. path = A_star_search( G, V, Index_startInPRM,Index_endInPRM );
  57. repath = [];
  58. repath = [repath;qset(:,1)'];
  59. kk = size(path,1);
  60. for i=1:size(path,1)
  61. repath = [repath;path(kk,:)];
  62. kk = kk-1;
  63. end
  64. repath = [repath;qset(:,2)'];
  65. plot(repath(:,1)',repath(:,2)','m-','LineWidth',2)

可以看出相比源代码,不需要找起始点和终止点的函数[Index_startInPRM, Index_endInPRM] = findStartAndEndInPRM( V, qset, QLIST)了

3 改进代码运行效果

4 github链接

【github】移动机器人运动规划

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

闽ICP备14008679号