Skip to content
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

Flowfield & collision avoidance #3078

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

gantsevdenis
Copy link
Contributor

@gantsevdenis gantsevdenis commented Jan 5, 2023

replaces the (dead? I guess) PR: #1213, I don't have the rights to modify it anyway.

Compiles and merges cleanly with latest master.
(I only added logging, and fixed the debugDraw to use the right perspective matrix)

UPDATE, I am dumping what I came up to here so that I am not alone carrying those heavy thoughts:

  1. I believe initial direction was wrong
  • Flow field itself is only the small half of the problem: it finds a globally optimal solution to a static problem. Flow field doesn't take into account dynamic obstacles. As such, most players won't even notice that pathfinder changed from A* to Flow field, because dynamic obstacles is what causing all problems. "Pathfinding" != "collision avoidance" !
  • We obviosuly try to navigate in a system with dynamic obstacles, and what we are looking for is called "potential fields", the best paper I found on the subject is "Continuum Crowds by Adrien Treuille, Seth Cooper, University of Washington
    Zoran Popović, 2 Electronic Arts
    " 1 .
    If you read another suggested paper (Crowd Pathfinding and Steering using Flow Field tiles) 2 ,
    out of 10 pages, only 1 (one) sentence on two lines briefly mentions dynamic obstacles. Not the best source for inspiration!
  • Trying to update a Flow field with dynamic obstacles doesn't scale, because we need a high resolution (the smallest dynamic obstacle is small cyborg, which is only 32 world units ("wu"), one full tile is 128wu), and that's just waayy too slow and in any case it doesn't make much sense to calculate an optimal solution just to throw it away the next logical tick.
  1. What I think we should do instead:
  • We need to combine globally optimal Flow field solution, to local solution to dynamic problem. Note, that because it's local, there is no way to ensure that droid will always take the correct path (which kinda mimics the real life: you can't know how far a wall goes unless you follow it). This is against what is described in the book 1 , as they do search for a global solution in even with dynamic obstacles. I don't think this limits us in any way, going from local solution to global is easy: just run cost-minimizing function over the full field.

  • Compute costs for flow field (at coarse grained resolution of 1 tile), but do not compute directions yet. Assume minimum cost is 4, not 1. This is for easier interpolation later. Flow field result can be cached, and they should be valid for targets of different radius. When a structure is built/destroyed it triggers recalculation of all flow fields for ground propulsions (DONE).
    This can be optimized, somewhat easily, for ex by delaying re-computation of FF only to when a droid actually stumbles upon a new, unknown static obstacle.
    But this optimization is only possible for newly built structures.
    Another solution would be to delay re-computation by N logical ticks, so that we update only once per multipe structures built/destroyed.

  • Each logical tick, create a fresh, high resolution (1/16 of a tile, let's call it "cell": so that each tile is 4x4 cells) array. For each moving droid, populate high-resolution array with an area of discomfort in the approximate direction the unit is currently moving, (do not create a circle area around it, that make movement decision look pretty dumb: I tried it). Continuous direction (uint16_t) are sampled to fit into 8 predefined directions. (DONE)

  • For each moving droid, calculate the sum of comfort fields, and discomfort fields (so our flow field cost is a "discomfort"), but subtract the part of the droid itself (DONE). Notice that our flow field has lower resolution, so interpolate its cost (per tile) for each cell. (this is annoying and error prone, because interpolation is different for 8 discreet directions... IN PROGRESS)

  • Now, calculate the path N cells ahead, aka, choose the direction of least discomfort N times. I don't know yet how large N should be, I am thinking about between 1 (=one cell) and 8 (=2 full tiles) (TODO).

  • Now that we know what is the discreet path along high-resolution comfort field, interpolate the angles of all N calculated directions, so that we move Direction back to continuous values from discreet (EDIT: or use those points as control points in Bézier curve describing the path). This is crucial to make droid behave naturally, otherwise they abruptly change their movement vector on the seems between cells/tiles. Note that movement behaviors inherent to propulsions (like wheels making circles and hovers drifting around) should be prioritized over directions suggested by our "pathfinder+avoidance" logic: I think the directions obtained above should only be used to gently steer droids in the right direction, instead of assigning it directly (TODO) (EDIT: again, consider using Bézier curves)

  • Use (dis)comfort fields to create "activity zones" of different types: for ex, artificially increase comfort values around a building under constructions so that Trucks automatically choose the next closest possible emplacement, instead of being stuck behind each other; or add discomfort for droids with full health which are next to a repair station: this will automatically push them away; add more discomfort for areas known to be reachable by enemy fire so that low-health droids will avoid them, etc... (TODO)

  1. Some possible different solution:
  • "Reciprocal N-body collision avoidance" / "Relative Velocity Obstacles" / "ClearPath". Some provide a C++ library. Not tested. Useless for "activity zones" because those are potential fields. Also, not clear to me how it integrates with global Pathfinder.
  1. Some definitely I-dont-believe-are-possible solutions:
  • Steering behaviors. This is way too basic, and plus it requires a new physics engine, and doesn't seem like a good fit for WZ2100

If someone knows this stuff better, and/or sees some incoherence: please do leave a comment, I am not a bloody expert in robotics 💯

@gantsevdenis gantsevdenis force-pushed the flowfield branch 3 times, most recently from e16f113 to b49ff83 Compare January 7, 2023 22:52
@gantsevdenis gantsevdenis changed the title Flowfield again Flowfield & collision avoidance Apr 12, 2023
@dkargin
Copy link
Contributor

dkargin commented Jun 2, 2023

Calculation of reciprocal N-body collision becomes pretty complicated for large number of units. Steering (boids) behaviors are very simple to implement but pretty painful to tweak. I've spent a ton of time for both during my small gamedev career.

I would like to try continuum crowds. Maybe it will need some mixture with more "modern" tricks from D*/lifelong A* to keep only a part of flow/continuum field updated.

Generally, I came here to try flowfield things, but surprisingly found your MR with most work already done.

@dkargin
Copy link
Contributor

dkargin commented Jun 2, 2023

  1. Flow field should be used only in areas, where density of units is very high. In low density/low dynamics area continuum field will be an overkill and good old A* will be a better solution.
  2. Flow fields can be "linked" to commanders. It will effectively reduce amount of fields to maintain. And maybe provide some tangible benefits from using commanders in multiplayer games.

@gantsevdenis
Copy link
Contributor Author

@dkargin I still have much work not pushed here, because I wasn't sure I am moving in right direction/ using right approach; and since you seem to have some real gamedev experience (which I don't), maybe worth get in touch? Sometimes it helps just to talk in order to clarify ideas. Obviously we ll post here every valuable conclusion.
Plenty of options (Discord, google meet, zoom, etc...), whatever you feel like

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants