-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shortest path finding issue #19
Comments
Yes, this has been annoying me for a while. The problem originates from the module I am using for pathfinding (and maybe from polygon based mesh pathfinding in general?) Using the examples from the module hxdaedalus-js As far as I can tell it is initially optimising the route based on the number of navigation mesh triangles a path passes though, rather than the resulting distance. |
Judging by my "awesome" visualization which took me way more time than it should've, it is working on the shortest path, the problem is that it's considering shortest whatever can be solved with a lesser amount of waypoints: Which, on a 2D grid system would be equivalent, and I think A* might bring the same results. I didn't investigate hxDaedalus enough, and I'm not an expert on pathfinding, so I don't know if there's a different way to weight the distances. If I'm not mistaken there was an option in the libDaedalus hx is using that forced a maximum distance to be considered as a step, and if there's an option to do it while using hx, setting it to 5 units would increase significantly the path length of the longer paths, at the cost of a bigger drawing time. Edit: path sampling |
The path sampling seems to refer to stepping along a path for use in animation once a path has been calculated. Rather than in adjusting how the path is calculated. |
Ah, yeah, seems I misread that. I was also looking at their implementation of the A* algorithm, and I might have found the issue: euclidean distance squared. I've found several instances inside the hxDaedalus implementation of this technique, although I'm not a 100% sure that's what causes this bug. Eventually, if we were to reimplement portions of hxDaedalus and adapt the A* algorithm, it would be possible to just alter the distance calculation using manhattan, diagonal or euclidean distances, fixing #9 in the process while having minimal to no impact on the codebase. I'll tinker some more with the library and see if I'm correct about the assumption. |
GOT IT. Their A* algorithm is broken. Here's the problem, visualised: cyan = walls, purple = triangulation edges, white circles = middle points, green = start, orange = red Basically the algo performs quite well up until the point where there are no big wide gaps, because if they do they only calculate the passing points as the middle between the two vertexes of the segment. In my tests above, the middle point would drift some 2000+ pixels, which would skew the path toward the right one. I "fixed" it for my case scenario by checking the closest vertex of the segment and using that to go through, and now Route Finder performs fairly well. To actually fix it, we need to add a "shortest intersection" between the current position and the the open path segment, which I didn't do yet. So, here comes the question, now. Do we:
I'm up for anything, including doing nothing, since this is your module I'll let you choose. This is the place that needs fixing, for reference: |
Yeah, it looks like the same issue. I'm currently fixing hxDaedalus and kinda want to optimise it a bit, reduce it to the most useful things and publish it as a separate foundry module. Pathfinding in Foundry could be quite useful to a lot of people if implemented correctly. Think automated patrols across dungeons and things like that. At the moment I only tested a hackish version but it temporarily works "alright". If you open entryPoint.x = ( innerEdge.originVertex.pos.x + innerEdge.destinationVertex.pos.x ) / 2;
entryPoint.y = ( innerEdge.originVertex.pos.y + innerEdge.destinationVertex.pos.y ) / 2; with var v = innerEdge.get_originVertex().get_pos();
var w = innerEdge.get_destinationVertex().get_pos();
entryPoint = fromPoint.distanceTo(v) <= fromPoint.distanceTo(w) ? v : w; it should perform significantly better. I'm working on a generalisation, hope to have it available today. |
Ok, so, after having spent way too much time on this:
@Norc I've tested your scenario as well, it seems to be working much better. If you want to try you can download the JS linked above, replace the node-modules version, and compile the addon with webpack. Of course since A* needs specific fine tuning, it won't ever be perfect, that's the tradeoff for its speed. Post scriptum
|
Hey, Sorry, I've been quiet on this for a few days, busy at work etc. I had a look this afternoon at removing all the external modules and attempting to write a foundry specific implementation. Not ready as a module yet, but as a start: The general problem is that while the main system is grid based the walls are not, so regular wall/no wall grid arrays won't work. I opted to use the inbuilt foundry methods of raycasting from each grid cell to find if a token would be allowed to walk to the adjacent squares. This allows a linked list to be built about which grid squares can link together. After this is it pretty much boring old A*, I've added config to allow different weights to diagonal vs orthogonal. |
I've thought of it but that won't work (as) nicely, I think. There's a lot of overhead which increases proportionally to the size of the grid and the number of walls, it could easily tank the performance. The changes to the A* I introduced reduce the travel distances by quite a lot and work quite predictably and accurately. The only thing left to do would be to lock them to the grid during funneling, and that's where all the grid customization can take place. I love how your module is agnostic, I wouldn't want to lose that. Then, again, if you implement the pathfinding system by itself detached from Route Finder, it'd be easy for Route Finder to use whatever system a user decides to have on their system, RouteFinder+Grid or RouteFinder+Ariadne, or even other new and different pathfinding modules that would come up at a later date. Edit: I was thinking back and maybe you're correct, while it most definitely changes and increases the computation, it's the best way to get the most accurate path. |
I was doing some testing with lights and paths, when I did a simple test across a wall and this happened:
Instead of choosing the 29 feet path, it went all around the wall on the other side and chose the 77 feet path. The wall is grid-aligned (despite me roughly drawing the wall position by hand).
The text was updated successfully, but these errors were encountered: