A星寻路算法C++实现

A*寻路算法的C++实现,共两个文件 astar.h astar.cpp

代码如下

// astar.h BEGIN

#ifndef ASTAR_H
#define ASTAR_H

#include <stdio.h>
#include <vector>
#include <set>

// 地图格子数据结构
struct grid_t
{
int id; // grid id {1,100}
int x; // x location {0,9}
int y; // y location {0,9}
int g; // g value 10{front, back, left, right}
//14{east_north, east_south, west_east, west_south}
int h; // h value ( diffx + diffy ) * 10
int block; // if available
int total; // total = g + h*10

void show(){
printf("{%d,%d,%d,%d,%d,%d,%d}, ", id, x, y, g, h, block, total);
}
};

// 地图格子信息 规格 10*10
extern std::vector<grid_t> map;

// 地图初始化 大小: 10*10 以左下角(0,0)作为坐标起点
void init_map();

//经过的格子编号 因有先后顺序 因此需要用vector存储
extern std::vector<int> path_grid_id;
grid_t* find(int x, int y);
#endif


// astar.h END



// astar.cpp BEGIN

#include <sys/time.h>
#include <stdlib.h>
#include <time.h>
#include "astar.h"

std::vector<grid_t> map;
std::vector<int> path_grid_id;


int start = 12;
int end = 78;

int abs(int val)
{
if( val >= 0 ){
return val;
}
return -val;
}

//grid_t* end_grid = &map[end-1];
grid_t* end_grid = NULL;
void init_map()
{
map.clear();
for( int i=1; i<=100; i++ ){
grid_t grid;
grid.id = i;
grid.x = (i-1) % 10;
grid.y = (i - 1) / 10;
grid.h = 0;
grid.g = 0;
grid.block = 0;
grid.total = 0;

// 设置障碍
if( grid.x==4 && grid.y >= 3 && grid.y <= 6 ){
grid.block = 1;
}

map.push_back(grid);
}
}

struct id_val_t
{
int id;
int val;
};

grid_t* find(int x, int y)
{
if( x < 0 || x > 9 ){
return NULL;
}
if( y < 0 || y > 9 ){
return NULL;
}
int id = y*10 + (x+1);
if( id <= 0 || id > map.size() ){
return NULL;
}
return &map[id-1];
}

grid_t* find_next_grid(int id)
{
if( id <= 0 || id > 100 ){
return NULL;
}
grid_t* grid = &map[id-1];

// 8 grid around
//path_grid_id.push_back(id);

// all ready find the path
for( int i=0; i<path_grid_id.size(); i++ ){
if( path_grid_id[i] != end ){
continue;
}
return NULL;
}

std::vector<id_val_t> vec_id_val;

int loc[][2] = {
{grid->x+1, grid->y},
{grid->x-1, grid->y},
{grid->x, grid->y+1},
{grid->x, grid->y-1},
{grid->x+1, grid->y+1},
{grid->x+1, grid->y-1},
{grid->x-1, grid->y+1},
{grid->x-1, grid->y-1}
};

for( int i=0; i<8; i++ ){
int loc_x = loc[i][0];
int loc_y = loc[i][1];
grid_t* find_grid = find(loc_x, loc_y);
if( NULL == find_grid ){
continue;
}
if( find_grid->block == 1 ){
continue;
}
}


//front grid
grid_t* find_grid = find(grid->x+1, grid->y);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 10;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}

//back grid
find_grid = find(grid->x-1, grid->y);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 10;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}

//left grid
find_grid = find(grid->x, grid->y+1);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 10;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}

//right grid
find_grid = find(grid->x, grid->y-1);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 10;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}

//east-north
find_grid = find(grid->x+1, grid->y+1);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 14;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}

//east-south
find_grid = find(grid->x+1, grid->y+1);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 14;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}

//west-north
find_grid = find(grid->x-1, grid->y+1);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 14;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}






//west-south
find_grid = find(grid->x-1, grid->y-1);
if( NULL != find_grid && find_grid->block == 0 ){
find_grid->g = 14;
find_grid->h = abs(end_grid->y - find_grid->y) + abs(end_grid->x - find_grid->x);
find_grid->total = find_grid->h * 10 + find_grid->g;
id_val_t id_val;
id_val.id = find_grid->id;
id_val.val = find_grid->total;
vec_id_val.push_back(id_val);
}


int tid = vec_id_val[0].id;
int tval = vec_id_val[0].val;
for( int i=0; i<vec_id_val.size(); i++ ){
if( vec_id_val[i].val >= tval ){
continue;
}
tid = vec_id_val[i].id;
tval = vec_id_val[i].val;
}

return &map[tid-1];

//
}


int main(int argc, char* argv[])
{
init_map();
for( int i=0; i<100; i++ ){
if( i % 5 == 0 ){
printf("\n");
}
map[i].show();

// set grid 74 block
if( i>= 73 && i<= 75 ){
map[i].block = 1;
}

}
end_grid = &map[end-1];

int round = 1;
if( argc >= 2 ){
round = atoi(argv[1]);
}

struct timeval tv1;
struct timeval tv2;

gettimeofday(&tv1, NULL);
int time1 = time(NULL);
for( int round_num = 0; round_num < round; round_num++ ){
path_grid_id.clear();
path_grid_id.push_back(start);
int grid_id = start;
while(true){
grid_t* grid = find_next_grid(grid_id);
if( NULL == grid ){
break;
}
path_grid_id.push_back(grid->id);

bool is_over = false;
for( int i=0; i<path_grid_id.size(); i++ ){
if(path_grid_id[i] != end_grid->id){
continue;
}
is_over = true;
break;
}

if( is_over ){
break;
}

grid_id = grid->id;
}
}
int time2 = time(NULL);

gettimeofday(&tv2, NULL);

printf("path_grid_id size: %d\n", path_grid_id.size());
for( int i=0; i<path_grid_id.size(); i++ ){
printf("grid_id:%d\n", path_grid_id[i]);
}
printf("round:%d, use:%d\n", round, time2-time1);
printf("tv1_sec:%d, tv1_usec:%d\n", tv1.tv_sec, tv1.tv_usec);
printf("tv2_sec:%d, tv2_usec:%d\n", tv2.tv_sec, tv2.tv_usec);
return 0;
}

// astar.cpp END


编译

$ g++ -g -o hello astar.cpp


测试

$ ./hello  [round]


精确到微秒, 测试结果:
执行1次
round:1 use:0
tv1_sec:1506153329, tv1_usec:920483
tv2_sec:1506153329, tv2_usec:920516
时间为920516-920483=33微秒

执行1W次
round:10000, use:0
tv1_sec:1506154327, tv1_usec:283682
tv2_sec:1506154327, tv2_usec:770319

执行10W次
round:100000, use:2
tv1_sec:1506154390, tv1_usec:71109
tv2_sec:1506154392, tv2_usec:666823

round:1000000, use:25
tv1_sec:1506154417, tv1_usec:960088
tv2_sec:1506154442, tv2_usec:562360



  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于ROS栅格地图的A*算法是一种常用的路径规划算法。在ROS中,栅格地图是通过将连续环境划分为一组离散的栅格单元来表示的。A*算法通过在这些栅格上进行搜索,找到从起始点到目标点的最优路径。 A*算法的基本思路是维护一个开放列表和一个关闭列表,以及每个栅格上的代价函数值。开放列表保存待探索的栅格,关闭列表保存已经考虑过的栅格。算法通过计算每个栅格的估计代价和实际代价之和,来选择下一个探索的栅格。栅格的估计代价可以通过启发式函数来计算,比如欧几里得距离或曼哈顿距离。 具体来说,A*算法可以分为以下几个步骤: 1. 初始化起始点和目标点,并将起始点加入开放列表。 2. 重复以下步骤直到找到目标点或开放列表为空: - 从开放列表中选择估计代价最小的栅格作为当前栅格。 - 将当前栅格从开放列表中移除,并将其加入关闭列表。 - 遍历当前栅格周围的邻居栅格,并计算它们的估计代价和实际代价。 - 如果邻居栅格不在开放列表和关闭列表中,将它们加入开放列表,并更新它们的代价函数值。 - 如果邻居栅格已经在开放列表中,比较新的路径代价和原来的路径代价,并更新为较小的值。 3. 如果找到目标点,根据关闭列表中存储的父节点信息,从目标点回溯到起始点,得到最优路径。 ROS中提供了很多路径规划的工具包,包括nav_core,move_base等,这些包已经实现了基于ROS栅格地图的A*算法,并通过调用相应的API来实现路径规划功能。开发者可以根据具体的应用场景选择适当的路径规划算法进行使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值