a star路径规划

created by Dejavu

这里写的c++代码是对process大神的代码进行移植的
大神用JavaScript写的a_star视频,用到p5.js
[完结]


a_star 简介

  • a star(a*) 是一种启发式路径规划的算法,该算法得到的路径不一定是全局最优的,但是因为路径规划速度较快所以被广泛使用。

  • A算法访问的节点比较少,因此可以缩短搜索时间。他的算法思想是:
    最终路径长度f = 起点到该点的已知长度h + 该点到终点的估计长度g。

      O表(open):
             待处理的节点表。
      C表(close):
             已处理过的节点表。
    
  • 伪代码

        function A*(start, goal)
            // The set of nodes already evaluated
            closedSet := {}

            // The set of currently discovered nodes that are not evaluated yet.
            // Initially, only the start node is known.
            openSet := {start}

            // For each node, which node it can most efficiently be reached from.
            // If a node can be reached from many nodes, cameFrom will eventually contain the
            // most efficient previous step.
            cameFrom := the empty map

            // For each node, the cost of getting from the start node to that node.
            gScore := map with default value of Infinity

            // The cost of going from start to start is zero.
            gScore[start] := 0

            // For each node, the total cost of getting from the start node to the goal
            // by passing by that node. That value is partly known, partly heuristic.
            fScore := map with default value of Infinity

            // For the first node, that value is completely heuristic.
            fScore[start] := heuristic_cost_estimate(start, goal)

            while openSet is not empty
                current := the node in openSet having the lowest fScore[] value
                if current = goal
                    return reconstruct_path(cameFrom, current)

                openSet.Remove(current)
                closedSet.Add(current)

                for each neighbor of current
                    if neighbor in closedSet
                        continue        // Ignore the neighbor which is already evaluated.

                    if neighbor not in openSet  // Discover a new node
                        openSet.Add(neighbor)

                    // The distance from start to a neighbor
                    tentative_gScore := gScore[current] + dist_between(current, neighbor)
                    if tentative_gScore >= gScore[neighbor]
                        continue        // This is not a better path.

                    // This path is the best until now. Record it!
                    cameFrom[neighbor] := current
                    gScore[neighbor] := tentative_gScore
                    fScore[neighbor] := gScore[neighbor] + heuristic_cost_estimate(neighbor, goal)

            return failure

        function reconstruct_path(cameFrom, current)
            total_path := [current]
            while current in cameFrom.Keys:
                current := cameFrom[current]
                total_path.append(current)
            return total_path

c++ 实现

需要opencv库,如果自己添加opencv内的类型到该文件也可以不用配置opencv

  • a_star.h 存放数据结构

          #ifndef _a_star_h
          #define _a_star_h
    
          #include <opencv2/opencv.hpp>
          #include <stdio.h>
          using namespace std;
          using namespace cv;
    
          #define N 100
          #define M 100
          #define map_info(v) obj.info.map[v.x][v.y]
          #define map_center(v) obj.info.map[v.x][v.y].center
          #define isNeighborExist (current.neighbors[i].x>=0 && current.neighbors[i].y>=0)
          #define copy(v1,v2) v1.assign(v2.begin(), v2.end())
          #define add(v1,v2) vector<Point>::iterator it;for(it = v2.begin();it!=v2.end();++it) v1.push_back(*it)
          #define add_o(v1,v2) vector<Info>::iterator it_o;for(it_o = v2.begin();it_o!=v2.end();++it_o) v1.push_back(*it_o)
          #define COLS 1024
          #define ROWS 720
          #define DUBUG false
          class Pt {
          public:
              Point pt;
              int r;
          };
    
          class  Info {
          public:
              bool isWall;
              Point index;
              Point pt;
              Point center;
              double F;
              double G;
              double H;
              Point neighbors[8];
              int previous;
              Point previous_pt;
              void init() {
                  F = 0;
                  G = 0;
                  H = 0;
                  previous = -1;
                  previous_pt = Point(-1,-1);
                  for (int i = 0;i < 8;i++) neighbors[i] = Point(-1, -1);
              }
              void addNeighbors() {
                  int x = index.x, y = index.y;
                  if (x > 0 && y > 0)
                      neighbors[0] = Point((x - 1), (y - 1));
                  if (y > 0)
                      neighbors[1] = Point(x, (y - 1));
                  if (x < COLS - 1 && y > 0)
                      neighbors[2] = Point((x + 1), (y - 1));
                  if (x < COLS - 1)
                      neighbors[3] = Point((x + 1), y);
                  if (x < COLS - 1 && y < ROWS - 1)
                      neighbors[4] = Point((x + 1), (y + 1));
                  if (y < ROWS - 1)
                      neighbors[5] = Point(x, (y + 1));
                  if (x > 0 && y < ROWS - 1)
                      neighbors[6] = Point((x - 1), (y + 1));
                  if (x > 0)
                      neighbors[7] = Point((x - 1), y);
              }
              int sq() { return index.y*COLS + index.x; }
              void show(Mat &src, Scalar rectColor) {
                  circle(src,center,25,Scalar(100,200,0),-1);
              }
          };
    
          class GridMapInfo {
          public:
              Mat obj_img;
              Info map[N][M];
              Point target, dest;
          };
    
          class Obj {
          public:
              Mat obj_src;
              Pt target, dest;
              GridMapInfo info;
          };
    
          class Params {
          public:
              Point start,end;
              vector<Point> path_pt;
              vector<Info> target_obj;
              Mat take_look;
          };
    
          class Select_path {
          public:
              bool direct;
              double F;
              vector<Info> path_obj;
              vector<Point> path;
          };
    
          double heuristic(Point spot_pt, Point end_pt);
          double a_star(Obj obj,Params &params);
    
          #endif
    
  • a_star.cpp

      #include "a_star.h"
    
      double heuristic(Point spot_pt, Point end_pt) {
          double dx = spot_pt.x - end_pt.x;
          double dy = spot_pt.y - end_pt.y;
          return sqrt(dx*dx*1.0 + dy*dy*1.0);
      }
      bool includes(list<Info> _dataSet, Info *target) {
          list<Info>::iterator it = _dataSet.begin();
          for (int i = 0; i<_dataSet.size(); i++) {
              if (it->sq() == target->sq()) return true;
              else ++it;
          }
          return false;
      }
      bool includes(Info _dataSet[],int len,Info* target) {
          for (int i = 0;i < len;i++) if (_dataSet[i].sq() == target->sq()) return true;
          return false;
      }
      void removeData(list<Info> &_dataSet, Info current) {
          list<Info>::iterator it = _dataSet.begin();
          for (int i = 0; i<_dataSet.size(); i++) {
              if (it->sq() == current.sq()) {
                  it = _dataSet.erase(it);
                  break;
              }
              else ++it;
          }
      }
    
      double a_star(Obj obj,Params &params) {
          Point start = params.start, dest = params.end;
          Mat show = params.take_look.clone();
          list<Info> openSet;
          list<Info> path;
          list<Info>::iterator it;
          int closed_len(0);
          Info closedSet[N*M];
          Info current = map_info(start);
          Info begin = current;
          Info end = map_info(dest);
          int winner(0);
          openSet.push_back(current);
    
          params.path_pt.clear();
          params.target_obj.clear();
    
          while (openSet.size() > 0) {
              it = openSet.begin();
              if (winner == openSet.size()) winner--;
              advance(it, winner);
              current = *it;
              double minF = it->F;
    
              int index(0);
              for (it = openSet.begin(); it != openSet.end(); ++it, index++) {
                  double currentF = it->F;
                  if (currentF < minF) {
                      winner = index;
                      minF = currentF;
                      current = *it;
                  }
              }
    
              if (current.sq() == end.sq()) {
                  reverse(params.path_pt.begin(),params.path_pt.end());
                  reverse(params.target_obj.begin(),params.target_obj.end());
                  return current.F;
              }
              params.take_look = show.clone();
    
              removeData(openSet, current);
              closedSet[closed_len++] = current;
    
              int tmpG(0);
              for (int i = 0; i < 8; i++) {
                  if (!isNeighborExist) continue;
                  Info *neighbor = &obj.info.map[current.neighbors[i].x][current.neighbors[i].y];
                  if (!includes(closedSet, closed_len, neighbor) && !neighbor->isWall) {
                      tmpG = current.G + 1;
                      if (includes(openSet, neighbor)) {
                          neighbor->G = tmpG;
                          continue;
                      }
                      neighbor->G = tmpG;
                      neighbor->H = heuristic(neighbor->center, end.center);
                      neighbor->F = neighbor->G + neighbor->H;
                      neighbor->previous = current.sq();
                      neighbor->previous_pt = current.index;
    
                      openSet.push_back(*neighbor);
                  }
              }
    
              path.clear();
              Info tmp = current;
              path.push_back(tmp);
              it = path.begin();
              while(tmp.previous != -1) {
                  tmp = map_info(tmp.previous_pt);
                  path.push_back(tmp);
              }
              params.path_pt.clear();
              params.target_obj.clear();
              params.path_pt.push_back(end.center);
              params.target_obj.push_back(map_info(end.index));
              for( it = path.begin(); it != path.end(); ++it ) {
                  it->show(params.take_look,Scalar(100,200,0));
                  params.path_pt.push_back(it->center);
                  params.target_obj.push_back((*it));
              }
          }
          return 0;
      }
    
a_star_gen
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容