-
Notifications
You must be signed in to change notification settings - Fork 2
Understanding the Code
The code consists of a struct GraphNode
and three classes ,viz , Color
,PathVisualizer
and AStarPlanner
. Each of them has been explained one by one in the following section of the page.
It consists of :
- an unsigned integer which is used for indices later in the code
- an Eigen::Vector3d point which is simply a column vector having three double values.
- a vector of pointers of the struct which is used to contain the info about neighbours
- a function to add neighbours to a particular GraphNode
- a constructor which has
- the first argument as a PointXYZI from pcl library which simply is a collection of 3 coordinate values and one intensity value
- the second argument is an unsigned integer.
It is a class inherited from std_msgs::ColorRGBA class which consists of 4 float values.
This class has 3 constructors:
- a default one
- one which initialises RGB values
- and the last which initialises RGBA values
This class consists of functions like white, black ,etc which return constructors having initialised the RGB values corresponding to them .
The functions of this class are used to decide that in which color do we want the vertices/edges of our graph and path to be visualized inside rviz using visualizeGraph
and visualizePath
.
It is used to visualize the path as the name suggests.
It has the following functions:
It takes the nodeHandles as it's arguments. It fetches the parameter visualize and voxel_size from the server. It creates colour maps for the colours like white,black,etc. Their first arguments are values like 0,1,2.. and the second arguments are the functions white,black,etc.
It takes the reference of a string as an argument.It makes a publisher object whose message type is visualization_msgs::MarkerArray and the topic name is the same as the argument of the function.It then creates a map the topic and the publisher.
This function is used to visualize the graph(whose smallest unit is struct Graphnode
) generated by function createGraph
which is a part of class AStarPlanner
.
If the graph is empty then the function ends simply and does nothing.
For a non-empty graph it does the following things:
-
It creates a variable
markers
of the message typevisualization_msgs::MarkerArray
and uses thismarkers
as the second entry to create a publish map (publisher_map_
) whose first entry istopic_name
. -
The
markers
containsvertex_marker
andedge_marker
which are of message typevisualization_msgs::Marker
.-
vertex_marker
,as the name suggests, is used to visualize vertices of the graph.To understand the different initialization of it's fields (which is included in the code) you can have a look at this .For every unit node of the graph, it copies the values of the three coordinates from it'sposition_
variable into ageometry_msgs::Point
variable and pushes it into thevertex_marker
. After doing the aforementioned step with every node, it simply pushesvertex_marker
intomarkers
. -
edge_marker
,as the name suggests, is used to visualize the edges connecting the nodes of the graph.It initializes different fields of this marker in a similar way as did forvertex_marker
. For every unit node in the graph,it copies the values of the three coordinates from it'sposition_
variable into ageometry_msgs::Point
variablestart_point
and the coordinates of all of it's neighbours are also copied into variables calledend_point
and pushed intoedge_marker
. Finally theedge_marker
is pushed intomarkers
.
-
-
Eventually the
markers
is published.
This function is used to visualize the path
found by the function findPath
.
If the path is empty it simply ends and does nothing.
For a non-empty path it does the following things:
- A
marker
is created of the message typevisualization_msgs::Marker
.It is initialised in a similar fashion asedge_marker
in the previous function because this marker is also going to give us some curve and not vertices. - The
path
is a vector ofEigen::Vector3d
points. For every point of the path, it copies it's three coordinates into a variables of typegeometry_msgs::Point
and pushes them intopoints
field of themarker
. - A
markers
is created of the message typevisualization_msgs::MarkerArray
and then themarker
is pushed into it. - Eventually
markers
is published after it has been incorporated intopublisher_map_
as done intovisualizeGraph
.
This class has a constructor and a few functions which are described below:
It initializes some variables,fetches some parameters,creates some publishers,some subscribers and some services and sets up some planners and other functions.
In particular,it does the following things:
- fetches parameters like
robot_radius
,visualize
andframe_id
from parameter server. - creates the following publishers:
-
path_marker_pub
to publish themarkers
for visualizing the path. -
sparse_graph_pub
to publish themarkers
for visualizing the graph generated. -
esdf_slice_pub_
to publish the pointCloud of points of typepcl::PointXYZI
. -
waypoint_list_pub
to publish the list of points that constitute the path.
-
- creates a subscriber
esdf_slice_sub_
to subscribe to the topic on which the slices are being published. - creates the following services:
-
planner_srv_
which responds when requested to plan the path usingPlannerServiceCallback
. -
path_pub_srv_
which responds when requested to publish the path usingpublishPathCallback
.
-
- sets the traversability radius which simply means minimum distance from the obstacles that our robot should maintain in order to avoid collisions.
- sets up the skeleton generator
- sets up the A* planner
- sets up the shortener.
It takes two points start
and end
as it's arguments of the type Eigen::Vector3d
and then copies them into Start
and End
of the type pcl::PointXYZI
.
It clears the graph graph_
first so that nothing is inside it beforehand and then pushes Start
and End
into it.Then iteratively it pushes all those points from pointCloud whose intensity values are greater than robot_radius_
into the graph.
Then it clears the tree_
(which is an Rtree) .For every node of the graph_
it takes their coordinates and make pairs with their id_
and pushes them inside the tree_
.
Then for each node of the graph_
it does the following things:
- It creates a vector of a data type which is a pair of a Point from boost library and an unsigned integer and calls it
neighbours
. - It copies the coordinates of the
position_
of the node into thePoint
and pushes 5 nearest points intoneighbours
. - Then for each neighbour from
neighbours
,if it'sid_
is not equal to the second argument of the neighbour ,then adds into the neighbour field of the node by using theaddNeighbour
function.
This function is used to search the path based on A* search algorithm.
The basic idea of A* algorithm is explained below:
- At each step it picks the node according to a value-
f
which is a parameter equal to the sum of two other parameters –g
andh
. - The first parameeter
g
is a movement cost parameter that is used to calculate the distance from starting point to the current location. - The second parameter
h
is a heuristic parameter that is to calculate our estimated distance from the current location to the end location. - The
h
parameter can be calculated using Euclidean distance , Manhattan distance , Diagonal distance, etc. In our case we use the Euclidean one.
The containers that has been used in the code for this are :
-
f_score_map
which is a pair of double value and an unsigned int value to calculate thef
parameter. -
open_set
which is a priority_queue off_score_map
which keeps it sorted into non-decreasing order. -
g_score
which is vector of doubles and keeps record of theg
parameter. -
parent
which is a vector of unsigned integers which keeps the record of the previous index of the current node.
This function is used to find the path as the name suggests.
It first creates the graph using createGraph
, visualize it using visualizeGraph
and eventually searches the path between the points using searcPath
.
This function is used to generate a sparse graph. A sparse graph is a graph in which the number of edges is much less than the possible number of edges.
It first updates the skeleton from layer after removing any pre-existing points in the skeleton.Then it calls the generateSparseGraph
function which is in voxblox::SkeletonGenerator
and is different from the generateSparseGraph
of class AStarPlanner
.
It then visualizes the graph using visualization_msgs::MarkerArray
and publishing it using the publisher sparse_graph_pub_
on the topic sparse_graph
.
This function is used to make a skeleton from the esdf layer.
It does the following things:
- sets the esdf layer.
- gets the minimum separation angle ( Minimum separation angle between two edges of a sparse graph node in radians) from
getMinSeparationAngle
function which is used to set the default value ofmin_seperation_angle
. Then it fetches it from the parameter server and uses it to set themin_seperation_angle
usingsetMinSeperationAngle
function. - In the very similar fashion as the previous point,
generate_by_layer_neighbors
( which decides whether to generate vertices/edges by number of basis points (false, default) or number of neighbors on the discretized medial axis (true) ) andnum_neighbors_for_edge
are processed. - Finally it sets the minimum GVD distance ( GVD stands for Generalized Voronoi Diagram which is commonly used as a safe roadmap in the context of path planning and it is used to compute distance between robots and points in the environment).
This function responds by planning the path once requested to do so using rviz.
It does the following things :
- generates the skeleton
- generates the sparse graph
- finds the path
- creates a
marker_array
of the typevisualization_msgs::MarkerArray
in order to visualize the generated path inside rviz - gets the path using Esdf and diagram
- shortens the path if possible
- publishes the
marker_array
usingpath_marker_pub
- and finally visualizes the path inside rviz.
This funtion is used to publish waypoints of the path searched.
It creates a variable pose_array
of the type geometry_msgs::PoseArray
. For every point in the last_waypoints_
(a variable of type mav_msgs::EigenTrajectoryPointVector
) ,it creates a variable pose_stamped
of type geometry_msgs::PoseStamped
,uses the point and the pose_stamped
to create a pose and finally pushes it inside the pose_array
.
Finally it publishes the pose_array
using waypoint_list_pub_
on the topic waypoint_list
.
It takes a pointcloud and publishes it using the esdf_slice_pub_
publisher on the esdf_slice_out
topic.
Then it declares and initializes start and end points of the type Eigen::Vector3d
and passes them as arguments into createGraph
to create the graph.
It finally calls the visualizeGraph
function which visualizes the graph into rviz.