In the above example, take the cell with
the red dot in it into consideration (I would have outlined it, but
didn't have time to learn all of the intricacies of the Gimp). In
any case, when decomposing this cell, it would be pointless to check
for collisions with any of the other obstacles in the C-space because
they do not occur.
Cell collisions with C-space obstacles occur as follows: For each
obstacle in the potential collisions list I check to see if for each
edge in this obstacle, there are any intersections with any of the
edges of the cell using the CGAL edge intersection functions. If
there are any intersections, this obstacle is added to this cell's
collision list and we update the cell's status if it is unknown.
Otherwise we leave the cell status alone, and we proceed on to check
the next obstacle. If this test is inconclusive, the planner then
checks to see if the obstacle lies entirely within the cell. I do
this using CGAL's point intersection algorithms. If all of the
obstacles vertices lie within the cell, then the cell is labeled as
mixed if its status is unknown and we proceed to the next potential
collision. If the cell is not determined to be mixed, we check to see
if the cell is full. This is again done by using CGAL's point
intersection algorithms, but this time we check to see if the cell's
vertices lie entirely within that of the obstacle if they do, then the
cell is labeled as full. If we check all of the potential
obstacles that could cause collisions and no collisions occur, then the
cell is labeled as empty.
After each refinement of the quadtree, two things automatically
happen. The first thing that happens is the recalculation of all
of the visible cells in the quadtree. As a result of the
decomposition, all of the leaf cells that were formerly of mixed status
are no longer leaves. The original list of visible (leaf) cells
is erased and recalculated by simply traversing through the tree and
adding all of the cells that are leaves. At the same time that
the list of visible cells is being recalculated, the planner also
determines the cell adjacencies.
Cell Adjacencies
Cell adjacencies are calculated at the same time that the visible cells
are being calculated because at this point for two reasons. The
first is that it is guarenteed that all of the cells in the quadtree
have been refined. We cannot determine the adjacencies for a cell
at the time it was refined because the cells around it may not have
been refined as well. The second reason is that we are traversing
through the tree and finding all of the leaf cells anyway, so there is
no reason to traverse through the tree a second time if we don't need
to.
It took me a little while to figure out how to determine
adjacencies. I decided to look at some suggestions presented to
by Professor Huang to his students
here.
While I didn't really like the ideas that were presented in their
current form, they inspired me to do the following:
I already had a function in my code (getCell()) that took a point
(x,y), and returned the leaf cell that this node was in. I had
used this function so that I could color the start and goal cells of
the quadtree appropriately, so that the user could see which cell the
planer thought the start and goal cells were in. Starting at the
top of the tree, this function simply looks at the point you pass it,
and determines if it lies in the upper-left, upper-right, lower-left,
or lower-right portion of the cell. It then looks at the
appropriate child of this cell and continues until it reaches a leaf
cell. This is the cell in the quadtree that the point lies in.
In order to apply this to adjacencies, for each cell in the quadtree
that I want to calculate adjacencies for, I first find the midpoint of
the cell. I then figure out the size of this cell using the depth
of this cell which is known. I will continue this example
explaining how I find the neighbors to the North of a given cell, but
the method is similar for finding the South, East, and West adjacencies
as well.
To find the Northen neighbors of a cell, I take the cells midpoint and
add the height of the cell. Ignoring the cells at the very top of
the quadtree, which are special cases, this generates a point that lies
in the cell to the North of this one. I then use the getCell()
function to determine the cell which this point lies in. I then
check the depth of this cell. If the depth of the new cell is
less than or equal to the depth of the cell I am finding adjacencies
for, then this cell is an adjacency and it is added to the adjacencies
list. If the depth of the new cell is greater than the depth of
the cell we are finding adjacencies for, then there will be more than
one adjacency to the North. I then traverse backward through the
tree looking at this cell's parents until I find a cell that is of the
same depth. I then recursively look at this cells lower children
and add any leaves that are present to the adjacencies list. At
this point, the Northern adjacencies have been found.