In Ian Millington's (excellent) book "Artificial Intelligence for Games", pages 87-88, he describes an algorithm to predict if two (or more) dynamic vehicles will collide, and if so, he applies a force to steer them out of collision. I found a similar source here http://www.imada.sdu.dk/~marco/Teaching/AY2014-2015/DM842/Slides/dm842-p2-lec2.pdf (Slides 36-37).
I don't understand the algorithm's calculations; It was stated in the book that time to collision equals to - (dp . dv) / |dv|^2, but the pseudo code omit the minus sign.
Second, I'm not sure I understand what's minSeparation stands for. If that's the minimum distance between the vehicles at the estimated "collision time", then it should be |dp+dv*tcollision| and not |dp| - |dv| * tcollision - unless I'm missing something (and the sign is again exactly the opposite of what I would expect). Then at the end, if we anticipate a collision, I would expect to apply a repulsion force proportional to the direction of the hit at the estimated time - that is: -1 * [dp + dv * tcollision], but what's actually been applied is |dp + dv * tcollision] (again the -1).
Clearly, I've got something in my calculations wrong and I would appreciate if someone can explain the math (and semantics of minSeparation) in more detail.
Thanks!
Dynamic object avoidance steering behavior calculation
There are two usual suspects for the differences you are noticing. The negation usually comes from setting up the variables involved. A very common item is that the equations will show, for example, "target-source" and some parts of the surrounding code will want the opposite "source-target", the programmer just uses the most common case and corrects the given equations by dropping or adding the negation. This is not usually a bug, it is just refactoring the equation to fit with the surrounding available data.
The second problem, and why the math does not always match up with the proper equations, is that the equations return an instantaneous force which needs to be applied. When you start factoring in other things such as a given bodies mass so they don't look mechanical, standard delta time application of forces rather than instantaneous, you are effectively breaking the equations. It is actually quite difficult to factor things like mass all the way back to the initial equations of motion, as such many implementations tweak the post motion equation to simply 'look good' rather than be correct. Unfortunately these forms of tweaks are use case specific usually and black magic tweaks that are not 'correct' in the math terms but get the job done for the game in question. Additionally, such hackery works great with some of the equations or are not actually needed in others, but variations of 'arrive', such as intercept, are extremely sensitive to such things. Tweaking the 'arrive' behavior is problematic since it almost always ends up underestimating the amount of deceleration required to stop at the target, the math gets pretty hairy to integrate this correctly so lots of folks just hack around till it is close enough.
Thank you for the explanation. I also tried to substitute 'source - target' instead of 'target - source' and understand that hackery might be involved to make things "feel right".
Any idea of what the minSeparation var stands for?
Looking at the code in that presentation it seems that the minSeparation is a measurement of how close two entities will be at their closest point. Using this value it then says that if the separation is more than some value (2*radius in the code) don't bother building an avoidance force since the entities never come close enough to need adjustment. That would be my guess from briefly looking at the code. Hope this helps.
Yes! Thank you for looking into this. Calculating |dp| - |dv| * tcollision doesn't take into account the direction. That means that dv can drive the agents away from each other but when applying - |dv| it's like accounting that the entire velocity's magnitude is taken into reducing the distance between the agents (which again doesn't account for the direction of the vectors). That's why this calculation is not clear to me.