Autoware源码分析——astar_avoid

2023-05-16

概要

本文是对autoware中waypoint_planner功能包的相关文件组成和具体节点的分析。由于程序比较复杂,我认为还存在一些不完整的地方,之后也会继续分析,继续更新。在看代码的过程中也学习了一些之前不清楚的ROS和C++的要点和ROS和autoware的一些具体消息类型(这部分在文末)。

有任何错误或不足之处,望指正!

1. waypoint_planner功能包的概述及整体结构

1.1 功能包概述

waypoint_planner功能包用于生成到目标的道路点waypoints的集合。它与lane_planner的区别在于它发布的是一个道路点而不是道路点的数组。

1.2 文件结构

从下图可以看出,waypoint planner的源文件src中由两个子功能包组成。一个是astar_avoid,另一个是velocity_set,astar_avoid文件夹中最重要的就是astar_avoid.cpp文件。
在这里插入图片描述

2. astar_avoid介绍

2.1 功能概述

autoware自带readme文件中提到,这里的astar_avoid使用的算法是基于hybrid A* 的,相关算法在astar_search的功能包里。

astar_avoid存在两种模式,一种是relay模式,第二种是avoidance模式,前者不能实现避障的功能,只是根据当前车辆的位姿生成waypoints;后者可以根据hybrid A* 算法中的内部状态转移的规则进行避障。

2.2 所使用到的文件

运行该算法依靠的文件是astar_avoid.launch文件,该文件实现的两个功能,第一个功能是设置一些astar_avoid程序中构造函数和A* search程序中的参数;第二个功能是启动astar_avoid节点。
在这里插入图片描述

2.3 astar_avoid.cpp分析

i. 所含部分

该文件基本可以分为5个部分,分别是:类AstarAvoid的构造函数、类的析构函数、回调函数callbacks、“主函数”(AstarAvoid::run())、“主函数”所用到的子函数定义。

以上五个部分所使用的库均在astar_avoid.h文件中定义。该头文件中定义了必要的公有变量(用于avoidance模式下的状态)、私有“变量”(包括ROS中的节点句柄NodeHandle、订阅者和发布者;定义启动节点需要设置的参数parameters,线程所用到的类;程序内部使用的变量)、回调函数和私有成员函数原型的定义。

在这里插入图片描述

ii. 具体包含的函数分析

AstarAvoid::AstarAvoid()

这部分是该类的构造函数,做了三件事:

  • 赋给程序用到的参数一些默认值
  • 设置节点句柄所用的parameters
  • 定义了唯一一个发布者,即safety_waypoints_pub_ = nh_.advertise<autoware_msgs::Lane>("safety_waypoints", 1, true);
  • 定义若干订阅者

advertise(), subsribe()函数见第三部分)

AstarAvoid::~AstarAvoid()

第二部分是该类的析构函数,这里只有一行代码:publish_thread_.join();,这里join()的目的是在类消失的时候,阻塞主函数,让该线程继续运行,运行结束之后,再运行主函数。(C++11多线程)

回调函数callbacks

...
  // functions, callback
  void costmapCallback(const nav_msgs::OccupancyGrid& msg);
  void currentPoseCallback(const geometry_msgs::PoseStamped& msg);
  void currentVelocityCallback(const geometry_msgs::TwistStamped& msg);
  void baseWaypointsCallback(const autoware_msgs::Lane& msg);
  void closestWaypointCallback(const std_msgs::Int32& msg);
  void obstacleWaypointCallback(const std_msgs::Int32& msg);
  ...

通过astar_avoid.h中的回调函数原型定义可以看出,如果该程序接受到了这几类消息,那么在ros::spinOnce()之后,这些回调函数就会被执行一次(通常ros::spinOnce()在一个循环内部,所以说执行一次)比如costmapCallback函数接收含有消息类型nav_msgs::OccupancyGrid的消息之后,将其存储到变量costmap_中,对其地图的原点位姿消息转换到TF坐标系中(tf::poseMsgToTF(costmap_.info.origin, local2costmap_);),并将costmap初始化标志位置为true,也就是costmap_initialized_ = true;

个人认为以上这些回调函数的目的是为了用于程序判断程序是否已初始化完成

AstarAvoid::run()

为什么这里是“主函数”?先看astar_avoid_node.cpp文件的代码:

...
#include "waypoint_planner/astar_avoid/astar_avoid.h"

int main(int argc, char** argv)
{
  ros::init(argc, argv, "astar_avoid");
  AstarAvoid node;
  node.run();
  return 0;
}

其中最主要的语句就是node.run(),它将执行AstarAvoid::run()这个类的方法,所以这里类比为“主函数”。

该函数的基本流程
  1. 定义或重置一些Index和时间,并检查程序是否初始化完成,如果失败,则继续等待要订阅的相关消息。
...
void AstarAvoid::run()
{
  // check topics
  state_ = AstarAvoid::STATE::INITIALIZING;

  while (ros::ok())
  {
    ros::spinOnce();
    if (checkInitialized())
    {
      break;
    }
    ROS_WARN("Waiting for subscribing topics...");
    ros::Duration(1.0).sleep();
  }
  ...
  1. 做主循环开始之前的一些准备工作
....
  // main loop
  int end_of_avoid_index = -1;//初始化用于终止发布路径点的索引
  ros::WallTime start_plan_time = ros::WallTime::now();//设置规划开始的时间。
  ros::WallTime start_avoid_time = ros::WallTime::now();

  // reset obstacle index
  obstacle_waypoint_index_ = -1;//初始化用于表示障碍物的索引

  // relaying mode at startup
  state_ = AstarAvoid::STATE::RELAYING;

  // start publish thread
  publish_thread_ = std::thread(&AstarAvoid::publishWaypoints, this);//开启第二个线程。
...
  1. 循环中的第一个阶段:relay mode(默认模式)
...
 while (ros::ok())
  {
    ros::spinOnce();

    // relay mode
    if (!enable_avoidance_)
    {
      rate_->sleep();
      continue;
    }
    ...
  1. 循环中的第二部分:在满足相应条件之后开启avoidance模式(这段代码比较长,这里不做粘贴了)
    首先,定义了两个用于后续判断任务的变量:受否发现障碍物bool found_obstacle,速度是否超过规定的速度bool avoid_velocitybool replan(用于判断是否需要重新规划)和bool reached(用于判断是否已经到了终点)。在avoidance模式下,总共有四种状态,分别是relaying, stopping, planning和avoiding,本人总结了以下转移的过程,如下图所示:(线段中的字符表示判断条件)

在这里插入图片描述

状态转移中用到的其他子函数

...
  // functions
  bool checkInitialized();
  bool planAvoidWaypoints(int& end_of_avoid_index);
  void mergeAvoidWaypoints(const nav_msgs::Path& path, int& end_of_avoid_index);
  void publishWaypoints();
  tf::Transform getTransform(const std::string& from, const std::string& to);
  int getLocalClosestWaypoint(const autoware_msgs::Lane& waypoints, const geometry_msgs::Pose& pose, const int& search_size);
};
...

(由于另一个功能包A* search还没有仔细分析,后续将不断对这部分进行更新)

代码较短的部分我就粘贴在这里。

a. bool AstarAvoid::checkInitialized

该函数用于检测初始化的条件是否满足。最初initialized的值是false。从以下的程序可以看出,relay mode需要满足的条件比avoidance mode要少。后者还需要检查costmap(或者说就是occupancy grid map)和current_velocity是否初始化完成。

bool AstarAvoid::checkInitialized()
{
  bool initialized = false;

  // check for relay mode
  //这里的relay mode需要满足四个条件。
  initialized = (current_pose_initialized_ && closest_waypoint_initialized_ && base_waypoints_initialized_ &&
                 (closest_waypoint_index_ >= 0));

  // check for avoidance mode, additionally
  if (enable_avoidance_)
  {
    initialized = (initialized && (current_velocity_initialized_ && costmap_initialized_));
  }

  return initialized;
}

(b和c都用到了A* search包中的函数,这里之后更新。)

b. bool AstarAvoid::planAvoidWaypoints
c. void mergeAvoidWaypoints
d. void publishWaypoints

该函数的目的是单独创建一个发布安全的道路点waypoints的线程。这个发布者也是astar_avoid中的唯一一个发布者,从中也可以直观看出该程序的功能就是经过一番运算,发布车辆可以安全行驶的道路点。

该函数的两大步骤就是:

  1. 根据状态选择当前的waypoints, 也就是current_waypoints的设置。
    switch (state_)
    {
      case AstarAvoid::STATE::RELAYING:
        current_waypoints = base_waypoints_;
        break;
      case AstarAvoid::STATE::STOPPING:
        // do nothing, keep current waypoints
        break;
      case AstarAvoid::STATE::PLANNING:
        // do nothing, keep current waypoints
        break;
      case AstarAvoid::STATE::AVOIDING:
        current_waypoints = avoid_waypoints_;
        break;
      default:
        current_waypoints = base_waypoints_;
        break;
    }

  1. 把waypoints“压”到数组中,即道路点的发布
    这里用到了vector中的push_back()函数,解释见第三部分。
...
    if (safety_waypoints.waypoints.size() > 0)
    {
      safety_waypoints_pub_.publish(safety_waypoints);
    }
    ...
e. tf::Transform getTransform

这一部分使用了ROS中的tf功能包。这个函数的目的就是通过tf::transform_listener,用try...except语句找到两个带有frame id的数据之间的变换,找到之后会返回这个变换,否则报错。

tf::Transform AstarAvoid::getTransform(const std::string& from, const std::string& to)
{
  tf::StampedTransform stf;
  try
  {
    tf_listener_.lookupTransform(from, to, ros::Time(0), stf);
  }
  catch (tf::TransformException ex)
  {
    ROS_ERROR("%s", ex.what());
  }
  return stf;
}
f. int getLocalClosestWaypoint

(该函数的步骤也后续更新)

3. 分析过程中的问题解决

由于是第一次看如此复杂的工程,期间遇到了一些记不太清楚和不太明白的编程要点,这部分对这些问题进行汇总,便于之后的查阅。

3.1 C++和ROS语法相关的一些要点

I. ROS:

ROS相关的问题大部分都可以在官方的wiki上找到答案。

a. 订阅者和发布者相关的函数

http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29
http://wiki.ros.org/roscpp/Overview/Publishers%20and%20Subscribers#Subscribing_to_a_Topic

发布者的advertise()函数
该函数会先与ros master进行通信,注册相关参数。常见语法如下:

ros::Publisher pub = node_handle.advertise<message_type>(topic_name, queue_size);

形参 (parameters) 是: message_type, topic_name, queue_size(队列的大小一般为1000)

该函数的返回值是ros::Publisher对象,其有两个目的:

  1. 之后使用对象中的publish()方法进行消息发布;
  2. 当消息超出范围之后,该对象会自动停止发布。

定义完该对象之后,在后续的主函数中使用自定义或ROS的标准消息类型(message-type)定义具体的消息(message content),通过pub.publish(msg)即可,格式如下:

message-type msg;
msg.xxx=xxx;

关于advertise中的第三个参数,可以参考以下图片。该参数为true的时候,该话题的上一个消息会被保存并且发给新的订阅者。
在这里插入图片描述

b. subscriber的写法

根据ROS官方wiki给出的教程:

callback:NodeHandle::subscribe() returns a ros::Subscriber object. When the Subscriber object is destructed, it will automatically unsubscribe from the chatter topic.

上文说明subscribe()函数返回的是Subscriber对象,以下是该函数的定义:

ros::Subscriber subscribe(const std::string& topic, uint32_t queue_size, <callback, which may involve multiple arguments>, 
const ros::TransportHints& transport_hints = ros::TransportHints());

如果回调函数是在某个类中进行定义,则这里的<callback>中既要包含方法的指针还要包含到该类的指针。例如:

current_velocity_sub_ = nh_.subscribe("current_velocity", 1, &AstarAvoid::currentVelocityCallback, this);

一开始并不太理解this,这里的this就是指向AstarAvoid该类的指针。

整个订阅者的简要过程

  1. 初始化ROS节点
  2. 订阅某个话题(topics)
  3. ros::spinOnce()会等待这些消息的到来
  4. 消息接收之后,执行回调函数。

c. nodehandler中的.param函数

不理解的语句如下:

private_nh_.param<bool>("enable_avoidance", enable_avoidance_, false);

括号内参数的含义:

(查找过程:在网页http://docs.ros.org/melodic/api/roscpp/html/classros_1_1NodeHandle.html中搜索ros::NodeHandle::param)

相关定义为:

template<typename T >
bool ros::NodeHandle::param	(const std::string& param_name, T& param_val, const T& default_val)

This method tries to retrieve the indicated parameter value from the parameter server, storing the result in param_val. If the value cannot be retrieved from the server, default_val is used instead.

可以看出,param()函数的目的就是从参数服务器中取出keyparam_name的值,并将其存放到param_val中,如果服务器中不存在此参数,则使用默认值。本节中的例子可以解释为:从参数服务器中取出keyenable_avoidance的值,将其存放到enable_avoidance_中,如果没有取出,则使用false作为该参数的默认值。

d. rate_->sleep();

相关链接:http://docs.ros.org/diamondback/api/rostime/html/classros_1_1Rate.html

该语句的目的就是一个周期内的剩余时间均处于sleep状态。计时是从上一次睡眠,重置或调用constructor开始。

e. ros::ok()

ros::ok()返回false的情况有:
(该情况下,所有的ROS调用都会失败)
a. 终端输入ctrl-C
b. 相同节点名称的节点将当前节点踢出网络(kick off)
c. ros::shutdown()被调用
d. 所有的ros::NodeHandles被消除。

f. ros::spinOnce()

相关链接: http://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning
该语句属于单线程(single-threaded spinning)。

还有一种方式是是ros::spin(),这条语句的目的就是循环使用ros::spinOnce(),也就是所有的回调函数在其内部被调用,直到调用ros::shutdown()或ctrl-C出现,程序终止。

加入ros::spinOnce()之后,ROS把订阅相关(收到Message)的回调函数推到一个队列(queues/spinning)中,ROS不会立即调用它。

g. ros::Duration(1.0).sleep()和ros::WallTime

ros::Duration(1.0).sleep()
相关链接:http://wiki.ros.org/roscpp/Overview/Time

例子:

ros::Duration(0.5).sleep(); // sleep for half a second

ros::WallTime

Wall Time可以理解为墙上时间,墙上挂着的时间没有人改变的了,永远在往前走;ROS Time可以被人为修改,你可以暂停它,可以加速,
可以减速,但是Wall Time不可以。
wall time 的接口与Time类的接口一样

h. tf listener相关

相关链接:http://docs.ros.org/diamondback/api/tf/html/c++/classtf_1_1TransformListener.html

lookupTransform的格式可以参考以下链接:
http://docs.ros.org/diamondback/api/tf/html/c++/classtf_1_1Transformer.html#ac01a9f8709a828c427f1a5faa0ced42b

II. C++相关

C++的官方文档链接:http://www.cplusplus.com/reference/

a. 析构函数destructor

参考链接:https://www.runoob.com/cplusplus/cpp-constructor-destructor.html

类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

b. thread和mutex:

#include <thread>
#include <mutex>

以上两个include是C++11关于多线程任务的新标准。

多线程是多任务处理的一种特殊形式,多任务处理允许让电脑同时运行两个或两个以上的程序。一般情况下,两种类型的多任务处理:基于进程和基于线程。

  1. 基于进程的多任务处理是程序的并发执行。
  2. 基于线程的多任务处理是同一程序的片段的并发执行

创建线程的方法std::thread name(threadFunction)join()是让阻塞当前主线程,等待所有的子线程执行完毕之后主线程才能继续执行或退出。

mutex是用来保证线程同步的,防止不同的线程同时操作同一个共享数据。

std::mutex mutex_;
std::lock_guard<std::mutex> lock(mutex_);

c. C++ 关键字this

相关链接:https://www.runoob.com/cplusplus/cpp-this-pointer.html
在 C++ 中,每一个对象都能通过this指针来访问自己的地址。this指针是所有成员函数的隐含参数。只有成员函数才有this 指针。

d. static_cast

相关链接:https://www.cnblogs.com/QG-whz/p/4509710.html

static_cast是一个强制类型转换操作符。强制类型转换,也称为显式转换。

例如,static_cast <int>就是将某个数据类型强制转化为int

e. C++ 中的push_back函数

use a vector member named push_back to add elements at runtime. The push_back operation takes a value and “pushes” that value as a new last element onto the “back” of the vector.

f. C++ 中的auto数据类型和for循环中的冒号写法

  1. auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型。
  2. C++ 11中for循环的新写法
    相关链接:https://blog.csdn.net/qq_39856931/article/details/106764565
int array[10] = { 54, 23, 78, 9, 15, 18, 63, 33, 87, 66 };
	
for (auto a : array) {
	cout << a << " ";		//输出:54 23 78 9 15 18 63 33 87 66
}

可以解释为aarray中的某个元素,将每次遍历array得到的结果赋值给a

g. .at(i)操作:返回vector中下标为i的元素

vector(T是某种类型)的at函数接收一个vector::size_type类型的参数n(一种无符号整型类型),返回容器位置为n的元素的引用(注意第一个位置为0)。

3.2 该程序所需要的消息类型(可能不太全,可以自行查阅相关msgs文件)

ROS的msgs文件的路径在:/opt/ros/kinetic/share/,或者通过ROS WIKI进行搜索。

autoware的相关msgs文件路径在:~/autoware.ai/src/autoware/msessages/(版本1.12.0)

1. nav_msgs::OccupancyGrid

# This represents a 2-D grid map, in which each cell represents the probability of
# occupancy.
Header header 
#MetaData for the map
MapMetaData info

# The map data, in row-major order, starting with (0,0).  Occupancy
# probabilities are in the range [0,100].  Unknown is -1.
int8[] data

# compact message def:
std_msgs/Header header
nav_msgs/MapMetaData info
int8[] data

子类型定义:
std_msgs/Header

# Standard metadata for higher-level stamped data types.
# This is generally used to communicate timestamped data 
# in a particular coordinate frame.
# 
# sequence ID: consecutively increasing ID 
uint32 seq
#Two-integer timestamp that is expressed as:
# * stamp.sec: seconds (stamp_secs) since epoch (in Python the variable is called 'secs')
# * stamp.nsec: nanoseconds since stamp_secs (in Python the variable is called 'nsecs')
# time-handling sugar is provided by the client library
time stamp
#Frame this data is associated with
string frame_id

nav_msgs/MapMetaData

# This hold basic information about the characterists of the OccupancyGrid

# The time at which the map was loaded
time map_load_time
# The map resolution [m/cell]
float32 resolution
# Map width [cells]
uint32 width
# Map height [cells]
uint32 height
# The origin of the map [m, m, rad].  This is the real-world pose of the
# cell (0,0) in the map.
geometry_msgs/Pose origin

geometry_msgs/Pose

geometry_msgs/Point position
geometry_msgs/Quaternion orientation

geometry_msgs/Quaternion

float64 x
float64 y
float64 z
float64 w

geometry_msgs::PoseStamped

# A Pose with reference coordinate frame and timestamp
std_msgs/Header header
geometry_msgs/Pose pose

geometry_msgs::TwistStamped

# A twist with reference coordinate frame and timestamp
std_msgs/Header header
geometry_msgs/Twist twist

其中的子类型定义:
geometry_msgs::Twist(代表车辆的速度)

# This expresses velocity in free space broken into its linear and angular parts.
geometry_msgs/Vector3 linear
geometry_msgs/Vector3 angular

geometry_msgs/Vector3

float64 x
float64 y
float64 z

autoware_msgs::Lane

Header header
int32 increment
int32 lane_id
Waypoint[] waypoints

uint32 lane_index
float32 cost
float32 closest_object_distance
float32 closest_object_velocity
bool is_blocked

autoware_msgs::Waypoint

# global id
int32 gid 
# local id
int32 lid
geometry_msgs/PoseStamped pose
geometry_msgs/TwistStamped twist
DTLane dtlane
int32 change_flag
WaypointState wpstate

uint32 lane_id
uint32 left_lane_id
uint32 right_lane_id
uint32 stop_line_id
float32 cost
float32 time_cost

# Lane Direction
# FORWARD				= 0
# FORWARD_LEFT	 		= 1
# FORWARD_RIGHT			= 2
# BACKWARD				= 3 
# BACKWARD_LEFT			= 4
# BACKWARD_RIGHT		= 5
# STANDSTILL	 		= 6
uint32 direction

本文实在有点长,见谅 😃

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Autoware源码分析——astar_avoid 的相关文章

  • Avoid mutating a prop directly since the value will be overwritten whenever

    在vue中 父组件向子组件传值 并在子组件改变了父组件的值 就会发出警告 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定 xff1a 父级 prop 的更新会向下流动到子组件中 xff0c 但是反过来则不行 这样会防止
  • Freertos 源码分析 队列queue

    队列queue xff08 零 xff09 队列的基础概念和形态 xff08 一 xff09 Freertos 队列 queue c FreeRTOS Kernel 10 4 6 include queue h Freertos队列模块包含
  • apache源码分析v2.0

    一 概要 1 平台功能层 xff0c 可移植运行库层 xff0c 核心功能层 xff0c 可选功能层 xff0c 第三方支持库 2 核心功能层 xff1a mod core 处理配置文件中的大部分配置指令 mod so 动态加载其余模块 m
  • 【死磕 Java 集合】— ConcurrentSkipListMap源码分析

    转自 xff1a http cmsblogs com p 61 4773 隐藏目录 前情提要简介存储结构源码分析 主要内部类构造方法添加元素添加元素举例删除元素删除元素举例查找元素查找元素举例彩蛋 作者 xff1a 彤哥 出处 xff1a
  • 【ROS】源码分析-消息订阅与发布

    说明 本文通过NodeHandle subscribe和Publication publish 源码作为入口 xff0c 来分析PubNode SubNode之间是网络连接是如何建立的 xff0c 消息是如何发布的 xff0c topic队
  • AUTOWARE下底盘CAN通讯实现

    无人驾驶系列 autoware与底盘CAN通讯实现 本文介绍在使用autoware时 xff0c 如何将autoware发送的消息传输给底盘 xff0c 实现对线控底盘的控制 准备工作 xff1a 1 系统具备ROS和autoware 2
  • autoware花屏重影问题

    autoware 安装 花屏 重影问题 最近尝试下autoware来做建图 xff0c 无奈各类安装太过麻烦 xff0c 这里给几个小问题做下纪律 1 xff0c 安装过程 xff0c 走的官网那个 xff0c 事实证明官网教程最全面 xf
  • 反序列化漏洞攻击原理(Dubbo反序列化漏洞剖析)

    关联文章 给服务端发送自定义类实例序列化数据实现反序列化攻击 一 前言 最近大家都在讨论Dubbo反序列化漏洞问题 想必各个大V也都推送了相关文章 看了下各大文章差不多都是一个套路 两个步骤 第一步开始描述下Dubbo的反序列化漏洞 几乎都
  • mybatis 自动化处理 mysql 的json类型字段 终极方案

    文章目录 mybatis 自动化处理 mysql 的json类型字段 终极方案 why json 简介 mysql 建表 json 字段 添加1条json 数据 对应的java对象 JsonEntity mybatis 不使用 通用mapp
  • Spring IOC容器初始化过程 源码分析

    本文主要记录Spring容器创建 源码分析过程 首先贴上一张时序图 好久没画 忘的差不多了 画的不好 可以凑合看一下 接下来 贴上一份测试代码 这里使用AnnotationConfigApplicationContext来初始化Spring
  • Mybatis整合Spring源码分析

    一 整合配置 POM
  • IDEA国际化资源Key无法全局重命名的解决方案

    一 前言 最近在开发中使用到了HibernateValidator进行入参校验以及错误消息的国际化支持 大家应该都知道在使用HibernateValidator进行校验的时候 我们只需在需要在校验的变量上添加相应的注解 同时在message
  • PHP 中的 A* 搜索算法 [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 有没有人有实施A 算法在 PHP 中 我知道维基百科有一个伪代码和一个 C 伪代码的链接 但我似乎找不到已经用 PHP 编写的伪代码 我也在寻找一种高效的书面 A 算法 None
  • Astar 可以多次访问节点吗?

    我一直在阅读维基百科的 Astararticle 在他们的实现中 他们检查每个节点是否在closed设置 如果是这样 他们会跳过它 是不是有可能 如果启发式是可以接受的 但是NOT一致 我们可能需要重新访问一个节点两次 或更多次 才能改进它
  • 路径查找算法:A* 与跳跃点搜索

    我知道 A 比 Dijkstra 算法更好 因为它考虑了启发式值 但是从 A 和跳跃点搜索来看 哪种算法是在有障碍物的环境中找到最短路径的最有效算法 有何不同 跳跃点搜索是基于图表上的某些条件的改进的 A 因此 如果满足这些条件 主要是统一
  • 寻找有界子图之间的最小割集

    如果游戏地图被划分为子图 如何最小化子图之间的边 我有一个问题 我试图通过基于网格的游戏 如 pacman 或 sokoban 进行 A 搜索 但我需要找到 外壳 外壳是什么意思 子图尽可能少切边 http en wikipedia org
  • 如何实现A*算法? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在 C 中简单实现 AN A 星 算法应该采用哪种方法 本文 https web archive org web 2017050503
  • 如何在 QuickGraph Dijkstra 或 A* 中设置目标顶点

    我使用的是 QuickGraph 3 6 版 我找到了函数 SetRootVertex 但没有 SetTagretVertex 我需要这个 因为我正在巨大的图中搜索短路径 这会大大加快程序速度 有问题的类是 DijkstraShortest
  • A* 在 HTML5 Canvas 中开始寻路

    我正在尝试在我的游戏中实现 A Start 路径查找 用 JavaScript HTML5 Canvas 编写 A Start 的图书馆发现了这个 http 46dogs blogspot com 2009 10 star pathrout
  • 机器人路径规划 - A*(星级)

    我正在用 C 为我的主要机器人探索行为实现 A 路径规划算法 当机器人移动时 它将自身周围的环境映射为二维图形 从这张图中 我设置了一个 Vector2D 元组 x y 它保存了这个路径点的位置 我希望机器人也能在其中导航 我对 A 所做的

随机推荐

  • 代理模型介绍大全

    已剪辑自 https zhuanlan zhihu com p 555814030 1 代理模型简介 一次看文献的时候 xff0c 看到一篇关于代理模型的文章 xff0c 讲解的十分细致 xff0c 深受启发 xff0c 醍醐灌顶 xff0
  • 一篇文章让你了解ISIGHT

    已剪辑自 https vsystemes com 35621 1 概述 经过了二十年的发展 xff0c 对于国内CAE仿真 xff0c 众多企业的目光已经不再只关注仿真本身 xff0c 更多的将目光放在了以下三个方面 xff1a 1 关注的
  • DDS(data distribution service,数据分发服务)简介

    已剪辑自 http www uml org cn modeler 20201010112 asp 编辑推荐 文章主要介绍了DDS高级数据中心接口取代了以消息为中心的编程和基本技术概念等相关内容 来自于dds foundation org 由
  • Oracle 删除表空间回收磁盘空间

    1 查询表空间和表空间数据库文件路径 span class token keyword SQL span span class token operator gt span span class token keyword select s
  • 在Ubuntu中使用雷电3外接显卡(eGPU)进行深度学习

    sud种种很凑巧的因素 xff0c 需要用这么一套设备做深度学习 笔记本是联想yoga s730 xff0c 两年前在某多多入手 xff0c 显卡坞是技嘉gaming box 43 GTX1070 xff0c 某鱼入手 折腾了一上午 xff
  • make和cmake命令

    我们在安装Ubuntu软件时 xff0c 有时我们会用到make和cmake命令 所以在这篇文章我们来讲解一下 xff0c make命令和cmake命令他们的作用 xff0c 以及什么关系和区别 首先假设你有一定的计算机基础 xff0c 能
  • 小觅双目相机自带参数配置ORBSLAM3双目参数文件

    ORBSLAM3相机需要的参数 打开 home knight ORB SLAM3 Examples Stereo EuRoC yaml 以这个开源数据集的参数为模板 1 Camera type PinHole 相机模型 小觅双目相机也是针孔
  • GVINS编译出现大量的error: ‘CV_CALIB_CB_ADAPTIVE_THRESH’ was not declared in this scope错误

    错误 xff1a home knight GVINS GI src GVINS main camera model src chessboard Chessboard cc 38 43 error CV CALIB CB NORMALIZE
  • 3.CMakeLists——完成脚本、说明文档、版权文件doc文件夹的指定位置安装

    1 实例 在CMakeLists txt目录下加入如下语句执行安装操作 xff1a INSTALL FILES COPYRIGHT README DESTINATION share doc cmake t2 INSTALL PROGRAMS
  • 1.vinsfusion-从数据流看程序

    本节介绍 xff0c 图像数据和惯导数据是如何传入程序中的 xff0c 以及之后的图像数据格式转化 和惯导数据的初步处理 图像数据流 1 订阅话题数据 xff1a 订阅左图 ros Subscriber sub img0 span clas
  • vlsam容易混洗的概念

    特征点 角点 关键点 xff1a 这些概念虽然在细节上有所不同 xff0c 但都可以统一称为特征点或者关键点 xff0c 也就是具有特征性质的点 外点 xff08 outlier point xff09 xff1a 简单的理解为不符合条件的
  • 5.vinsdusion globalOptNode.cpp

    IO输出的 nav msgs Odometry 类型消息 xff0c 这个定位信息包含了VIO的位置和姿态 xff0c 其坐标系原点位于VIO的第一帧处 GPS输出的sensor msgs NavSatFixConstPtr 类型消息 xf
  • ros节点启动和关闭相关

    1 ros运行单位 xff1a Ros程序运行的单位是ros node 2 ros 节点的启动 xff1a xff08 1 xff09 初始化ros节点 xff1a 通过调用ros init 接口实现 xff1b 可以通过参数指定默认节点名
  • VINSFUSION-运行,并评估。

    1 修改yaml文件 output path home tong output xff0c 改成自己的 xff0c 其他的看自己用的啥相机 xff0c 改话题名字和相关参数 2 修改程序中的输出 xff0c 改成tum格式 当前帧在滑动窗口
  • Linux Windows Mac 临时 HTTP 服务传输文件(python http server)

    http 传输文件比 scp 和 ftp 都要可靠稳定和方便 xff0c 在 Linux 系统上 xff08 Windows 和 Mac 也一样 xff09 xff0c 我们经常需要把一堆文件或者某个大文件发送到别处 xff0c 遇到这种需
  • Docker容器显示图像界面配置

    Docker容器显示图像界面配置 原理概述 可以把docker看做一台没配显示器的主机 xff0c linux目前的主流图像界面服务X11支持 客户端 服务端 xff08 Client Server xff09 的工作模式只要在容器启动的时
  • ubuntu服务器有多个网卡时设置网卡的优先级

    有时候服务器会有多个网卡 xff0c 分别连接局域网和外网 xff0c 当局域网的优先级更高时会出现无法访问外网的情况 只需要设置默认网关就行了 首先查看默认网关 ip route show 然后通过 span class token fu
  • C_C++架构如何学?2020必备的最新懒人攻略指南(持续更新)

    C C 43 43 架构师学习之路 如同加锁和解锁操作 xff0c 在看文章之前先点个赞 xff0c 如果你看完文章觉得对您没有帮助 xff0c 希望您取消您的点赞 您的点赞是对笔者的一次鼓励 xff0c 您的取消是让笔者有对文章质量的把控
  • 嵌入式

    嵌入式 嵌入式开发就是指在嵌入式操作系统下进行开发 xff0c 一般常用的系统有WinCE xff0c ucos xff0c vxworks xff0c linux xff0c android等 另外 xff0c 用c xff0c c 43
  • Autoware源码分析——astar_avoid

    概要 本文是对autoware中waypoint planner功能包的相关文件组成和具体节点的分析 由于程序比较复杂 xff0c 我认为还存在一些不完整的地方 xff0c 之后也会继续分析 xff0c 继续更新 在看代码的过程中也学习了一