Closed WDobert closed 2 years ago
Here is my general idea for updating the map at each time step based on the discussion in the meeting today and some more reflection on how to make it a tiny bit more efficient :
Description: More complicated but more efficient as we only re-draw part of the occupancy grid each time.
Data Structures:
cones
: Dict with structure {(x,y): [(x,y), (x,y), ...]}
. The key of the dict is a tuple containing two floats representing the (x,y) position of a cone. The value for each key is a list of tuples that are other keys in cones
representing the neighbors of this cone. We will draw a wall between this cone and its neighbors.cones_to_erase
: Dict with the same structure as cones
but representing the cones (and their neighbors) to erase from the occupancy grid for the current iteration.cones_to_draw
: List of (x,y) tuples where each is a key into cones
representing the cones that were updated.neighbor_thresh
: Some number that is slightly larger than the expected distance between cones and much less than the track width.update_occupancy_grid
: Takes a dict of cones to draw (see structure of cones
above) and a flag for whether to erase (set grid square probability to 0) or to fill in (set grid square probability to 100) on the occupancy grid. Squares will be erased/filled in between the coord given by each key and the list of neighbors given by the value for each key in the cones dict provided. Drawing lines on the grid could be accomplished using Bresenham's line algorithm.Algorithm:
new_cones
.new_cones
to those in cones
. For each point, (call this point new_cone
) compare the distance to the nearest neighbor (call this nearest_cone
):
neighbor_thresh
-- add newly seen cones (ensure this does not happen after the first lap):
new_cone
into cones
and set its value to the list of neighbors that are less than or equal to neighbor_thresh
distance away.new_cone
to cones_to_draw
.insignif_thres
< dist < neighbor_thresh
-- updating cone positions:
cones[nearest_cone]
call this list nearest_cone_neighbors
. cone_to_erase = cones.pop('nearest_cone')
) and add cone_to_erase
to cones_to_erase
. C{new_cone: nearest_cone_neighbors}
to cones
.new_cone
to cones_to_draw
.insignif_thres
do nothing since cone position difference is negligable.cones_to_erase
to update_occupancy_grid
with the erase flag set to true.{k: v for k, v in cones.items() if k in cones_to_draw}
to update_occupancy_grid
with the erase flag set to false.Description: Simpler but less efficient as we re-draw the entire occupancy grid at each step.
Data Structures:
cones
: List of tuples where each tuple contains two floats representing the (x,y) position of each cone. cones_to_update
: List of int
s where each int
is an index into cones
representing the cones that were updated.Algorithm:
new_cones
.new_cones
to those in cones
. For each point, check if the distance to the nearest neighbor is greater than the track width:
cones
.cones
to cones_to_update
AND update the value in cones
with the new position.cones
into the function that creates a 2D occupancy grid from points. This function will simply draw lines between all cones that are within neighbor_thresh
distance of each other.For the Method 1 implementation-specific approach, when trying to find the nearest cone neighbors within a certain threshold, it might be helpful to use a KD-tree for storing the structures. A rudimentary algorithm that can be modified to fit our needs is here: https://en.wikipedia.org/wiki/K-d_tree#Nearest_neighbour_search. It might be more efficient with a larger number of points, such that we don't have to check every point in cones for every point in new_cones.
I also looked into the actual line drawing under the assumption we have the correct two cones to connect, and there is actually a premade python package that does this: https://pypi.org/project/bresenham/. I tested it out on a basic scale and it works fine, so if we can get the first parts of method 1, update_occupancy_grid shouldn't be too much of a problem.
Looked at the bresenham source code in a little more detail, and one note mentioned in the README was that the following solves the problem faster: skimage.draw.line
Description
Given a new snapshot of current cone positions, publish an occupancy map that gives a representation of the track with "walls".
The cone positions will be provided by the
cone_finder
node, publishing ConeList messages on the/cone_finder/cones_found
topic.The node you create should publish nav_msgs/OccupancyGrid messages to the "/map" topic.
Sub-tasks
Resources