• ROS1云课→20迷宫不惑之A*大法(一种虽古老但实用全局路径规划算法)


    ROS1云课→19仿真turtlebot(stage)

    19提及的机器人如何实现全局路径规划?A*算法是一种可行的选择。 

    www.gamedev.net/reference/articles/article2003.asp 


    A*算法的基本介绍可以查询网络资源。这里,列出一些案例:

    蓝桥ROS扩展笔记CppRobotics编译_zhangrelay的博客-CSDN博客


    第一种:

    1. /*************************************************************************
    2. > File Name: a_star.cpp
    3. > Author: TAI Lei
    4. > Mail: ltai@ust.hk
    5. > Created Time: Sat Jul 20 12:38:43 2019
    6. ************************************************************************/
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. using namespace std;
    16. class Node{
    17. public:
    18. int x;
    19. int y;
    20. float sum_cost;
    21. Node* p_node;
    22. Node(int x_, int y_, float sum_cost_=0, Node* p_node_=NULL):x(x_), y(y_), sum_cost(sum_cost_), p_node(p_node_){};
    23. };
    24. std::vectorfloat> > calc_final_path(Node * goal, float reso, cv::Mat& img, float img_reso){
    25. std::vector<float> rx;
    26. std::vector<float> ry;
    27. Node* node = goal;
    28. while (node->p_node != NULL){
    29. node = node->p_node;
    30. rx.push_back(node->x * reso);
    31. ry.push_back(node->y * reso);
    32. cv::rectangle(img,
    33. cv::Point(node->x*img_reso+1, node->y*img_reso+1),
    34. cv::Point((node->x+1)*img_reso, (node->y+1)*img_reso),
    35. cv::Scalar(255, 0, 0), -1);
    36. }
    37. return {rx, ry};
    38. }
    39. std::vectorint> > calc_obstacle_map(
    40. std::vector<int> ox, std::vector<int> oy,
    41. const int min_ox, const int max_ox,
    42. const int min_oy, const int max_oy,
    43. float reso, float vr,
    44. cv::Mat& img, int img_reso){
    45. int xwidth = max_ox-min_ox;
    46. int ywidth = max_oy-min_oy;
    47. std::vectorint> > obmap(ywidth, vector<int>(xwidth, 0));
    48. for(int i=0; i
    49. int x = i + min_ox;
    50. for(int j=0; j
    51. int y = j + min_oy;
    52. for(int k=0; ksize(); k++){
    53. float d = std::sqrt(std::pow((ox[k]-x), 2)+std::pow((oy[k]-y), 2));
    54. if (d <= vr/reso){
    55. obmap[i][j] = 1;
    56. cv::rectangle(img,
    57. cv::Point(i*img_reso+1, j*img_reso+1),
    58. cv::Point((i+1)*img_reso, (j+1)*img_reso),
    59. cv::Scalar(0, 0, 0), -1);
    60. break;
    61. }
    62. }
    63. }
    64. }
    65. return obmap;
    66. }
    67. bool verify_node(Node* node,
    68. vectorint> > obmap,
    69. int min_ox, int max_ox,
    70. int min_oy, int max_oy){
    71. if (node->x < min_ox || node->y < min_oy || node->x >= max_ox || node->y >= max_oy){
    72. return false;
    73. }
    74. if (obmap[node->x-min_ox][node->y-min_oy]) return false;
    75. return true;
    76. }
    77. float calc_heristic(Node* n1, Node* n2, float w=1.0){
    78. return w * std::sqrt(std::pow(n1->x-n2->x, 2)+std::pow(n1->y-n2->y, 2));
    79. }
    80. std::vector get_motion_model(){
    81. return {Node(1, 0, 1),
    82. Node(0, 1, 1),
    83. Node(-1, 0, 1),
    84. Node(0, -1, 1),
    85. Node(-1, -1, std::sqrt(2)),
    86. Node(-1, 1, std::sqrt(2)),
    87. Node(1, -1, std::sqrt(2)),
    88. Node(1, 1, std::sqrt(2))};
    89. }
    90. void a_star_planning(float sx, float sy,
    91. float gx, float gy,
    92. vector<float> ox_, vector<float> oy_,
    93. float reso, float rr){
    94. Node* nstart = new Node((int)std::round(sx/reso), (int)std::round(sy/reso), 0.0);
    95. Node* ngoal = new Node((int)std::round(gx/reso), (int)std::round(gy/reso), 0.0);
    96. vector<int> ox;
    97. vector<int> oy;
    98. int min_ox = std::numeric_limits<int>::max();
    99. int max_ox = std::numeric_limits<int>::min();
    100. int min_oy = std::numeric_limits<int>::max();
    101. int max_oy = std::numeric_limits<int>::min();
    102. for(float iox:ox_){
    103. int map_x = (int)std::round(iox*1.0/reso);
    104. ox.push_back(map_x);
    105. min_ox = std::min(map_x, min_ox);
    106. max_ox = std::max(map_x, max_ox);
    107. }
    108. for(float ioy:oy_){
    109. int map_y = (int)std::round(ioy*1.0/reso);
    110. oy.push_back(map_y);
    111. min_oy = std::min(map_y, min_oy);
    112. max_oy = std::max(map_y, max_oy);
    113. }
    114. int xwidth = max_ox-min_ox;
    115. int ywidth = max_oy-min_oy;
    116. //visualization
    117. cv::namedWindow("astar", cv::WINDOW_NORMAL);
    118. int count = 0;
    119. int img_reso = 5;
    120. cv::Mat bg(img_reso*xwidth,
    121. img_reso*ywidth,
    122. CV_8UC3,
    123. cv::Scalar(255,255,255));
    124. cv::rectangle(bg,
    125. cv::Point(nstart->x*img_reso+1, nstart->y*img_reso+1),
    126. cv::Point((nstart->x+1)*img_reso, (nstart->y+1)*img_reso),
    127. cv::Scalar(255, 0, 0), -1);
    128. cv::rectangle(bg,
    129. cv::Point(ngoal->x*img_reso+1, ngoal->y*img_reso+1),
    130. cv::Point((ngoal->x+1)*img_reso, (ngoal->y+1)*img_reso),
    131. cv::Scalar(0, 0, 255), -1);
    132. std::vectorint> > visit_map(xwidth, vector<int>(ywidth, 0));
    133. std::vectorfloat> > path_cost(xwidth, vector<float>(ywidth, std::numeric_limits<float>::max()));
    134. path_cost[nstart->x][nstart->y] = 0;
    135. std::vectorint> > obmap = calc_obstacle_map(
    136. ox, oy,
    137. min_ox, max_ox,
    138. min_oy, max_oy,
    139. reso, rr,
    140. bg, img_reso);
    141. // NOTE: d_ary_heap should be a better choice here
    142. auto cmp = [](const Node* left, const Node* right){return left->sum_cost > right->sum_cost;};
    143. std::priority_queue, decltype(cmp)> pq(cmp);
    144. pq.push(nstart);
    145. std::vector motion = get_motion_model();
    146. while (true){
    147. Node * node = pq.top();
    148. if (visit_map[node->x-min_ox][node->y-min_oy] == 1){
    149. pq.pop();
    150. delete node;
    151. continue;
    152. }else{
    153. pq.pop();
    154. visit_map[node->x-min_ox][node->y-min_oy] = 1;
    155. }
    156. if (node->x == ngoal->x && node->y==ngoal->y){
    157. ngoal->sum_cost = node->sum_cost;
    158. ngoal->p_node = node;
    159. break;
    160. }
    161. for(int i=0; isize(); i++){
    162. Node * new_node = new Node(
    163. node->x + motion[i].x,
    164. node->y + motion[i].y,
    165. path_cost[node->x][node->y] + motion[i].sum_cost + calc_heristic(ngoal, node),
    166. node);
    167. if (!verify_node(new_node, obmap, min_ox, max_ox, min_oy, max_oy)){
    168. delete new_node;
    169. continue;
    170. }
    171. if (visit_map[new_node->x-min_ox][new_node->y-min_oy]){
    172. delete new_node;
    173. continue;
    174. }
    175. cv::rectangle(bg,
    176. cv::Point(new_node->x*img_reso+1, new_node->y*img_reso+1),
    177. cv::Point((new_node->x+1)*img_reso, (new_node->y+1)*img_reso),
    178. cv::Scalar(0, 255, 0));
    179. // std::string int_count = std::to_string(count);
    180. // cv::imwrite("./pngs/"+std::string(5-int_count.length(), '0').append(int_count)+".png", bg);
    181. count++;
    182. cv::imshow("astar", bg);
    183. cv::waitKey(5);
    184. if (path_cost[node->x][node->y]+motion[i].sum_cost < path_cost[new_node->x][new_node->y]){
    185. path_cost[new_node->x][new_node->y]=path_cost[node->x][node->y]+motion[i].sum_cost;
    186. pq.push(new_node);
    187. }
    188. }
    189. }
    190. calc_final_path(ngoal, reso, bg, img_reso);
    191. delete ngoal;
    192. delete nstart;
    193. // std::string int_count = std::to_string(count);
    194. // cv::imwrite("./pngs/"+std::string(5-int_count.length(), '0').append(int_count)+".png", bg);
    195. cv::imshow("astar", bg);
    196. cv::waitKey(5);
    197. };
    198. int main(){
    199. float sx = 10.0;
    200. float sy = 10.0;
    201. float gx = 50.0;
    202. float gy = 50.0;
    203. float grid_size = 1.0;
    204. float robot_size = 1.0;
    205. vector<float> ox;
    206. vector<float> oy;
    207. // add edges
    208. for(float i=0; i<60; i++){
    209. ox.push_back(i);
    210. oy.push_back(60.0);
    211. }
    212. for(float i=0; i<60; i++){
    213. ox.push_back(60.0);
    214. oy.push_back(i);
    215. }
    216. for(float i=0; i<61; i++){
    217. ox.push_back(i);
    218. oy.push_back(60.0);
    219. }
    220. for(float i=0; i<61; i++){
    221. ox.push_back(0.0);
    222. oy.push_back(i);
    223. }
    224. for(float i=0; i<40; i++){
    225. ox.push_back(20.0);
    226. oy.push_back(i);
    227. }
    228. for(float i=0; i<40; i++){
    229. ox.push_back(40.0);
    230. oy.push_back(60.0 - i);
    231. }
    232. a_star_planning(sx, sy, gx, gy, ox, oy, grid_size, robot_size);
    233. cin.ignore();
    234. return 0;
    235. }

    效果如下:

     

     但是,需要通过修改代码,定位起点终点和障碍物等。


    如何,解决下面这种迷宫呢(mazegenerator.net)?

    迷宫有中杯,大杯,超大杯。

    中杯版本如下:

    大杯版本如下:

     

    超超大杯版本:

     

    咱就不玩超大号的了。 

    就用下面这个地图吧:

    中:

    大:

    代码参考: 

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace cv;
    8. using namespace std;
    9. //
    10. Mat pool_max(Mat image_source, int size);
    11. Mat pool_min(Mat image_source, int size);
    12. int f(int x1,int x2,int z1,int z2);
    13. class A
    14. {
    15. private:
    16. int rate=6;
    17. int map[300][300];
    18. Mat m;
    19. //
    20. int tag_open=0,tag_close=0;
    21. //
    22. int map_root[300][300][2];
    23. //
    24. int x1;
    25. int x2;
    26. //
    27. int z1;
    28. int z2;
    29. //
    30. int way[1000][2];
    31. //
    32. //
    33. int close[24400][3];
    34. //
    35. int open[24400][4];
    36. public:
    37. //
    38. Mat image_source;
    39. //
    40. void deal_image();
    41. //
    42. void find_ori();
    43. //
    44. void deal_A();
    45. //
    46. void draw_road();
    47. };
    48. void A::draw_road()
    49. {
    50. Mat rgb;
    51. rgb=imread("maze.png",1);
    52. VideoWriter witer = VideoWriter("maze.avi",CV_FOURCC('M','P','4','2'),40,Size(image_source.cols,image_source.cols),1);//
    53. int mm=0;
    54. //
    55. while(1)
    56. {
    57. mm++;
    58. //
    59. for(int tag_a=4;tag_a<7;tag_a++)
    60. for(int tag_b=4;tag_b<7;tag_b++)
    61. for(int tag_c=0;tag_c<2;tag_c++)
    62. rgb.at((map_root[z1][z2][0]*rate+tag_a),(map_root[z1][z2][1]*rate+tag_b))[tag_c%3]=0;
    63. imshow("a",rgb);
    64. waitKey(1);
    65. z1=map_root[z1][z2][0];
    66. z2=map_root[z1][z2][1];
    67. //
    68. witer<
    69. printf("%d %d \n",z1,z2);
    70. //
    71. if(((z1==x1)&&(z2==x2))||mm>1000)break;
    72. }
    73. //
    74. imshow("a",rgb);
    75. witer.release();
    76. }
    77. void A::find_ori()
    78. {
    79. Mat image_b;
    80. GaussianBlur(image_source,image_b,Size(3,3),5);
    81. //
    82. for(int tag_a=0;tag_a
    83. {
    84. for(int tag_b=0;tag_b
    85. if(image_b.at(tag_a,tag_b)>100)image_b.at(tag_a,tag_b)=255;
    86. else image_b.at(tag_a,tag_b)=0;
    87. }
    88. //
    89. for(int tag_b=0;tag_b
    90. if(image_b.at(tag_b,0)==255)
    91. {
    92. x1=tag_b/rate-1;
    93. x2=0;
    94. }
    95. for(int tag_b=0;tag_b
    96. if(image_b.at(tag_b,image_b.rows-1)==255)
    97. {
    98. z1=tag_b/rate-1;
    99. z2=(image_b.rows)/rate-1;
    100. }
    101. }
    102. void A::deal_image()
    103. { //
    104. image_source = imread("maze.png",0);
    105. //
    106. Mat b;
    107. //
    108. GaussianBlur(image_source,b,Size(3,3),5);
    109. //
    110. for(int tag_a=0;tag_a
    111. {
    112. for(int tag_b=0;tag_b
    113. if(b.at(tag_a,tag_b)>100)b.at(tag_a,tag_b)=255;
    114. else b.at(tag_a,tag_b)=0;
    115. }
    116. //
    117. //m=pool_min(pool_max(b,3),3);
    118. m=pool_min(b,6);
    119. //
    120. for(int tag_a=0;tag_a
    121. {
    122. for(int tag_b=0;tag_b
    123. if(m.at(tag_a,tag_b)>100)m.at(tag_a,tag_b)=255;
    124. else m.at(tag_a,tag_b)=0;
    125. }
    126. //
    127. imshow("c",m);
    128. //
    129. for(int tag_a=0;tag_a
    130. for(int tag_b=0;tag_b
    131. map[tag_a][tag_b]=m.at(tag_a,tag_b);
    132. }
    133. void A::deal_A()
    134. {
    135. int keyy1=0,keyy2=0,keyy3=0,keyy4=0;
    136. map_root[z1][z2][0]=5;
    137. //
    138. close[0][0]=x1;
    139. close[0][1]=x2;
    140. tag_close++;
    141. //
    142. int com[2]={10000,0};
    143. while(1)
    144. {
    145. //
    146. if(map[close[tag_close-1][0]][close[tag_close-1][1]+1]==255&&close[tag_close-1][0]>=0&&(close[tag_close-1][1]+1)>=0)
    147. { //close
    148. for(int tag_a=0;tag_a
    149. {
    150. //
    151. if((close[tag_close-1][0])==open[tag_a][0]&&(close[tag_close-1][1]+1)==open[tag_a][1])
    152. { //
    153. //open[tag_a][2]=close[tag_close-1][2]+1;
    154. keyy1=1;
    155. break;
    156. }
    157. if(keyy1==0)
    158. {
    159. map_root[close[tag_close-1][0]][close[tag_close-1][1]+1][0]=close[tag_close-1][0];
    160. map_root[close[tag_close-1][0]][close[tag_close-1][1]+1][1]=close[tag_close-1][1];
    161. }
    162. keyy1=0;
    163. }
    164. //
    165. if(open[com[1]][3]==100000)
    166. {
    167. open[com[1]][0]=close[tag_close-1][0];
    168. open[com[1]][1]=close[tag_close-1][1]+1;
    169. open[com[1]][2]=close[tag_close-1][2]+1;
    170. open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    171. }
    172. else
    173. {
    174. //
    175. open[tag_open][0]=close[tag_close-1][0];
    176. open[tag_open][1]=close[tag_close-1][1]+1;
    177. open[tag_open][2]=close[tag_close-1][2]+1;
    178. open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    179. tag_open++;
    180. }
    181. }
    182. if(map[close[tag_close-1][0]][close[tag_close-1][1]-1]==255&&close[tag_close-1][0]>=0&&(close[tag_close-1][1]-1)>=0)
    183. {
    184. for(int tag_a=0;tag_a
    185. {
    186. if((close[tag_close-1][0])==open[tag_a][0]&&(close[tag_close-1][1]-1)==open[tag_a][1])
    187. {
    188. //open[tag_a][2]=close[tag_close-1][2]+1;
    189. keyy2=1;
    190. break;
    191. }
    192. if(keyy2==0)
    193. {
    194. map_root[close[tag_close-1][0]][close[tag_close-1][1]-1][0]=close[tag_close-1][0];
    195. map_root[close[tag_close-1][0]][close[tag_close-1][1]-1][1]=close[tag_close-1][1];
    196. }
    197. keyy2=0;
    198. }
    199. if(open[com[1]][3]==100000)
    200. {
    201. open[com[1]][0]=close[tag_close-1][0];
    202. open[com[1]][1]=close[tag_close-1][1]-1;
    203. open[com[1]][2]=close[tag_close-1][2]+1;
    204. open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    205. }
    206. else
    207. {
    208. open[tag_open][0]=close[tag_close-1][0];
    209. open[tag_open][1]=close[tag_close-1][1]-1;
    210. open[tag_open][2]=close[tag_close-1][2]+1;
    211. open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    212. tag_open++;
    213. }
    214. }
    215. if(map[close[tag_close-1][0]+1][close[tag_close-1][1]]==255&&(close[tag_close-1][0]+1)>=0&&(close[tag_close-1][1])>=0)
    216. {
    217. for(int tag_a=0;tag_a
    218. {
    219. if((close[tag_close-1][0]+1)==open[tag_a][0]&&(close[tag_close-1][1])==open[tag_a][1])
    220. {
    221. //open[tag_a][2]=close[tag_close-1][2]+1;
    222. keyy3=1;
    223. break;
    224. }
    225. if(keyy3==0)
    226. {
    227. map_root[close[tag_close-1][0]+1][close[tag_close-1][1]][0]=close[tag_close-1][0];
    228. map_root[close[tag_close-1][0]+1][close[tag_close-1][1]][1]=close[tag_close-1][1];
    229. }
    230. keyy3=0;
    231. }
    232. if(open[com[1]][3]==100000)
    233. {
    234. open[com[1]][0]=close[tag_close-1][0]+1;
    235. open[com[1]][1]=close[tag_close-1][1];
    236. open[com[1]][2]=close[tag_close-1][2]+1;
    237. open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    238. }
    239. else
    240. {
    241. open[tag_open][0]=close[tag_close-1][0]+1;
    242. open[tag_open][1]=close[tag_close-1][1];
    243. open[tag_open][2]=close[tag_close-1][2]+1;
    244. open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    245. tag_open++;
    246. }
    247. }
    248. if(map[close[tag_close-1][0]-1][close[tag_close-1][1]]==255&&(close[tag_close-1][0]-1)>=0&&(close[tag_close-1][1])>=0)
    249. {
    250. for(int tag_a=0;tag_a
    251. {
    252. if((close[tag_close-1][0]-1)==open[tag_a][0]&&(close[tag_close-1][1])==open[tag_a][1])
    253. {
    254. //open[tag_a][2]=close[tag_close-1][2]+1;
    255. keyy4=1;
    256. break;
    257. }
    258. if(keyy4==0)
    259. {
    260. map_root[close[tag_close-1][0]-1][close[tag_close-1][1]][0]=close[tag_close-1][0];
    261. map_root[close[tag_close-1][0]-1][close[tag_close-1][1]][1]=close[tag_close-1][1];
    262. }
    263. keyy4=0;
    264. }
    265. if(open[com[1]][3]==100000)
    266. {
    267. open[com[1]][0]=close[tag_close-1][0]-1;
    268. open[com[1]][1]=close[tag_close-1][1];
    269. open[com[1]][2]=close[tag_close-1][2]+1;
    270. open[com[1]][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    271. }
    272. else
    273. {
    274. open[tag_open][0]=close[tag_close-1][0]-1;
    275. open[tag_open][1]=close[tag_close-1][1];
    276. open[tag_open][2]=close[tag_close-1][2]+1;
    277. open[tag_open][3]=f(open[tag_open][0],open[tag_open][1],z1,z2);
    278. tag_open++;
    279. }
    280. }
    281. com[0]=10000;
    282. com[1]=0;
    283. //
    284. for(int tag_a=0;tag_a
    285. {
    286. if((open[tag_a][2]+open[tag_a][3])0])
    287. {
    288. com[1]=tag_a;
    289. com[0]=open[tag_a][2]+open[tag_a][3];
    290. }
    291. }
    292. //
    293. close[tag_close][0]=open[com[1]][0];
    294. close[tag_close][1]=open[com[1]][1];
    295. //map_root[close[tag_close][0]][close[tag_close][1]][0]=close[tag_close-1][0];
    296. //map_root[close[tag_close][0]][close[tag_close][1]][1]=close[tag_close-1][1];
    297. //
    298. map[close[tag_close-1][0]][close[tag_close-1][1]]=0;
    299. //
    300. open[com[1]][3]=100000;
    301. tag_close++;
    302. //printf("\n %d %d\n",close[tag_close-1][0],close[tag_close-1][1]);
    303. //waitKey(5);
    304. if(map[z1][z2]==0)break;
    305. }
    306. }
    307. int f(int x1,int x2,int z1,int z2)
    308. {
    309. return abs(x1-z1)+abs(x2-z2);
    310. }
    311. Mat pool_max(Mat image_source, int size)
    312. {
    313. int rows = image_source.rows;
    314. int cols = image_source.cols;
    315. int tag_x=0,tag_y=0,tag1=0,tag2=0;
    316. int tag3[3]={0,0,0};
    317. Mat image_new(image_source.rows/size,image_source.cols/size,CV_8UC1);
    318. while(tag_x>=0&&tag_x<=rows-size)//
    319. {
    320. while(tag_y>=0&&tag_y<=cols-size)
    321. {
    322. while(tag1>=0&&tag1<=size)
    323. {
    324. while(tag2>=0&&tag2<=size)
    325. {
    326. if(image_source.at(tag_x+tag1,tag_y+tag2)>tag3[1])(tag3[1]=image_source.at(tag_x+tag1,tag_y+tag2));
    327. tag2++;
    328. }
    329. tag1++;
    330. tag2=0;
    331. }
    332. image_new.at(tag_x/size,tag_y/size)=tag3[1];
    333. tag3[1]=0;
    334. tag_y+=size;tag1=0;tag2=0;
    335. }
    336. tag_x+=size;
    337. tag_y=0;tag1=0;tag2=0;
    338. }
    339. return image_new;
    340. }
    341. Mat pool_min(Mat image_source, int size)
    342. {
    343. int rows = image_source.rows;
    344. int cols = image_source.cols;
    345. int tag_x=0,tag_y=0,tag1=0,tag2=0;
    346. int tag3[3]={0,0,0};
    347. Mat image_new(image_source.rows/size,image_source.cols/size,CV_8UC1);
    348. while(tag_x>=0&&tag_x<=rows-size)//
    349. {
    350. while(tag_y>=0&&tag_y<=cols-size-1)
    351. {
    352. while(tag1>=0&&tag1<=size)
    353. {
    354. while(tag2>=0&&tag2<=size)
    355. {
    356. if(image_source.at(tag_x+tag1,tag_y+tag2)1])(tag3[1]=image_source.at(tag_x+tag1,tag_y+tag2));
    357. tag2++;
    358. }
    359. tag1++;
    360. tag2=0;
    361. }
    362. image_new.at(tag_x/size,tag_y/size)=tag3[1];
    363. tag3[1]=255;
    364. tag_y+=size;tag1=0;tag2=0;
    365. }
    366. tag_x+=size;
    367. tag_y=0;tag1=0;tag2=0;
    368. }
    369. return image_new;
    370. }
    371. int main()
    372. {
    373. A a;
    374. a.deal_image();
    375. a.find_ori();
    376. a.deal_A();
    377. a.draw_road();
    378. cin.ignore();
    379. }

    www.gamedev.net/reference/articles/article2003.asp 

    A*(发音为 A-star)算法对于初学者来说可能很复杂。虽然网上有很多解释 A* 的文章,但大多数都是为已经了解基础知识的人编写的。这篇文章是为真正的初学者准备的。

    本文并不试图成为该主题的权威著作。相反,它描述了基础知识,并让准备好出去阅读所有其他材料并理解他们在说什么。本文末尾的进一步阅读下提供了一些最佳链接。

    最后,本文不是特定于程序的。应该能够使这里的内容适应任何计算机语言。然而,正如所料,我在本文末尾提供了一个示例程序的链接。示例包包含两个版本:一个是 C++ 版本,一个是 Blitz Basic 版本。如果只想查看 A* 的运行情况,它还包含可执行文件。

    将其从打开列表中删除并将其添加到关闭列表中。
    检查所有相邻的方块。忽略那些在封闭列表中或无法行走(有墙壁、水或其他非法地形的地形)的那些,如果它们已经不在开放列表中,则将它们添加到开放列表中。使选定的方块成为新方块的“父级”。
    如果相邻的方格已经在打开列表中,请检查通往该方格的这条路径是否更好。换句话说,如果我们使用当前方格到达那里,请检查该方格的 G 分数是否较低。如果没有,不要做任何事情。
    另一方面,如果新路径的 G 成本较低,则将相邻方格的父方更改为选定方格(在上图中,将指针的方向更改为指向选定方格)。最后,重新计算该方格的 F 和 G 分数。如果这看起来令人困惑,您将在下面看到它。
    将起始方块(或节点)添加到打开列表中。
    重复以下操作:
    a) 在开放列表中寻找最低的 F 成本方。我们将其称为当前方格。
    b) 将其切换到关闭列表。
    c) 对于与当前方格相邻的 8 个方格中的每一个 ...
    如果它不可步行或在封闭列表中,请忽略它。否则请执行以下操作。
    如果它不在打开列表中,请将其添加到打开列表中。使当前方格成为该方格的父方。记录正方形的 F、G 和 H 成本。
    如果它已经在开放列表中,请使用 G 成本作为衡量标准,检查通往该方格的这条路径是否更好。较低的 G 成本意味着这是一条更好的路径。如果是,则将方块的父级更改为当前方块,并重新计算该方块的 G 和 F 分数。如果您保持您的开放列表按 F 分数排序,您可能需要借助该列表来说明更改。
    将目标方块添加到封闭列表中,在这种情况下已找到路径(请参见下面的注释),或
    找不到目标方格,打开列表为空。在这种情况下,没有路径。
    保存路径。从目标方格向后工作,从每个方格到其父方格,直到到达起始方格。那是你的道路。注意:在本文的早期版本中,建议您可以在目标方格(或节点)已添加到打开列表而不是关闭列表时停止。这样做会更快,它几乎总是会给你最短的路径,但并非总是如此。这样做可能会产生影响的情况是,从第二个节点移动到最后一个节点到最后一个(目标)节点的移动成本可能会有很大差异 - 例如,在两个节点之间的河流交叉的情况下。 


  • 相关阅读:
    drone ci 是什么
    用递归算法得到Java的树形结构
    【Cesium4UE】使用问题及解法统计
    Rebex Total Pack 6.0 for .Net Crack
    数据采集之:巧用布隆过滤器提取数据摘要
    cocos creator实现浏览星球的功能,附源码
    算法竞赛进阶指南:装满的油箱(Python)
    【java_wxid项目】【第六章】【Spring Cloud Gateway集成】
    金融业务系统云原生技术转型:从传统架构到云原生的跨越
    win10 上PHP artisan storage:link 出现 symlink (): Protocol error的解决办法
  • 原文地址:https://blog.csdn.net/ZhangRelay/article/details/126735454