leethomason / MicroPather

MicroPather is a path finder and A* solver (astar or a-star) written in platform independent C++ that can be easily integrated into existing code. MicroPather focuses on being a path finding engine for video games but is a generic A* solver.
326 stars 71 forks source link

Add a virtual comperator function to the MicroPather class #4

Closed HWiese1980 closed 10 years ago

HWiese1980 commented 10 years ago

I've introduced a virtual comperator method to the MicroPather class. This way comparison of two nodes can be done in the Graph subclass. There might be other places where replacing node A == node B with graph->NodesEqual(A, B) might be necessary.

leethomason commented 10 years ago

SeveQ -

This won't work. Micropather assumes that bit equality works. It's not just in the call back, but in the PathNode cache and the Path Cache. And it's not a concept I would introduce in the API in any case. Clearly if:

a == b

Then they are the same node, and are equal. This would allow for:

Equal(a,b) == true if a != b

which is esoteric and difficult to document.

[edit: equality misspelled]

HWiese1980 commented 10 years ago

In my setup there are nodes that are objects and whose data fingerprint is defined by their coordinates x, y, and theta (angle). Since these objects are created and deleted dynamically I just cannot be sure that

a == b 

is sufficient. I needed a way to get a comparison like

a.x == b.x AND a.y == b.y AND a.theta == b.theta

It's just because I need to know if the current node pose object is equal to the goal pose which are two different objects, unfortunately. I cannot do

current_node == goal_node

That's why I had to change the way the nodes are getting compared. It appears to be working at least for me. However, for any new path that I need I create a whole new MicroPather object. Maybe that's why...

Anyway, I'd really appreciate it if you could tell me how I'd go on and use the unmodified MicroPather with nodes that are objects representing poses.

leethomason commented 10 years ago

"However, for any new path that I need I create a whole new MicroPather object"

Yeah...that's not good. :)

Remember that each PathNode is a node in a graph...so if your graph has a very large number of potential nodes, that's a memory and performance challenge. If x, y, and theta are discrete enough for bit packing, that's the best solution:

state = x | (y<<8) | (theta <<16) // an example that may or may not work for you

If you really do have more states than can be bit packed, you can put the unique states in a hash table and then the state is the pointer to the structure in the hash table. But that's at least a yellow flag that something is going wrong.

HWiese1980 commented 10 years ago

Alright. I'll see if I can get my data bit packed, appears to be a lot easier...

All three values are floats with a precision of 3 (i.e. meters with a maximum precision of one millimeter and radians with a maximum precision of pi/500). I have a map of 3 by 2 meters and so I've got a maximum number of 3000 x 2000 x 500 = 3 billion nodes. That's a damn lot and I don't need this high precision. My actual map however has a resolution of 5 millimeters and pi/4 per node. Still 600 x 400 x 4 = 960.000 nodes. But that's acceptable. So, according to your comment I'd pack the data like this, right?

uint32_t state = x | (y << 10) | (theta << 19); // something like that

'cos I need at least 10 bits for x (max 1024), 9 bits for y (max 512) and 3 bits for theta (pi/4 = eight directions).

Is that correct? I guess, I'll give it a try tomorrow. Should also be a little bit faster than my current solution.