-
Notifications
You must be signed in to change notification settings - Fork 24
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
Angle hiccups when rotation wraps +-PI, and other rotational musings. #331
Comments
I think i found the problem. Some serious gdb foo brought me to GetPosition, the one that interpolates Positions. Take a look at this:
Output:
See that -1.52 in there? That can't be right. |
Angular encoding is complicated by decreasing precision with increasingly large values due to the way IEEE floating point arithmetic works. I've previously at least with one issue & related effort tried unsuccessfully to address that. Something to factor into this bug you've identified. Ideally we need a way to wrap-around angles so that:
|
I think the PR #332 referenced above should satisfy those two conditions. It does however limit possible rotation to +/- PI - meaning one cannot use the angle to determine the number of full rotations something has made. Which would kind of clash with 1. in any way. The code compiles down quite well, and is a lot faster than the other method (sin/cos unit-vector thingy) i could think of. I am not sure if it compiles using Fixed reals. Another minor issue would be that commonly radians use a range of [-PI,PI) (or was it (-PI,PI]? nvm) but this will clip to [-PI,PI]. |
Oh wow! I hadn't realized Looking at things more closely on Godbolt reveals that it's divisions by floating point values that can't exactly be expressed reciprocally which are done via the Good news is this means there's places in the code that can be rewritten to be faster then. Bad news is that I don't recall all the places in the code where this will be. |
How is -1.52 wrong? That is 0.2580 of the way from -3.1354 to 3.1258 with precision of 4: I do believe that you found a problem though. I don't think that the problem is where PR #332 is currently changing however; it's not in that I recall there being some code which sometimes normalizes angles though not as regularly as doing what you've shown in this PR. I suspect that's where the bug, that's causing angle hiccups, really is -- though allowing angles to grow arbitrarily large as the current |
Ofc, however only if one allows angle interpolation to take the "long way" between angles. Interpolating over the shorter angle should give Allowing to interpolate over the long angle would mean that like in my example a rotating body would jump from rotation -3.1 on frame 0 to rotation -1.5 on frame 1 and to rotation 3.1 on frame 2. With that in mind, another example might be that with the code as is, a pendulum swinging from -3 to 3 over +-PI, imagining +-PI as lowest point, might suddenly point upwards for a frame, just to return to its hanging position on the next. I noticed that because my sprites would sometimes "flip" for a very brief moment while rolling around, as the sprites are rendered using a body's rotation. |
Thinking more about the pendulum example, i realized that my solution might not even suffice. The way i wrote it, interpolation would always be along the shorter of the two possible distances between two angles. But while it might in reality not happen, there is the theoretical edge case that interpolation would have to happen along the long side. Should there be a pendulum swinging from -3 to 3 over 0, 0 being the lowest point - swinging so fast that getPosition would be called with the pendulums extreme angles - the pendulum would flip. Say when interpolating -3 to 3 with r=.5, would give +-PI the way i wrote it, but depending on the direction of rotation, would have to be 0. |
@ninnghazad What are your thoughts about the |
Hm, it seems ok. Maybe not fastest, but solid. Did a quick bruteforce-ish test on it and compared it to the method i use. Both passed the same tests and returned reasonably similar results. (Used the core of the trunc-mod version). Apart from that the only way i could see the method not doing what one would expect would be to feed it degrees or something weird. I compared it to:
Oh, and i think we might be talking about multiple issues about angles by now. I'm pretty sure that the way angles get interpolated is wrong, then there is the giant-angles thing, and maybe stuff that went right past me in the discussion. Hm, and none of that has anything to do anymore with custom joints. I'ma rename this issue a bit. |
Thinking more about it i remembered there being a maximum rotation per step limit. Finding a few sentences about it in the docs there was this:
And the default seems to be .5 Pi. So my fears of ambiguous angles in sweep interpolation are unfounded - the limit would make it so interpolation along the short side is always ok. So the PR is ok for preventing the 'close-to-PI-flip' cause of the interpolation, but it does not limit bodies angles in general it seems. Did a quick spinning body test against the PR and i get large angles from |
Experimenting with a call to
to:
I think I prefer normalization here, since it seems like point in the code where Changing the setting of |
Code like It's my desire to enable the use of strongly typed quantities by default (like for angles, lengths, etc.) but so far in testing with boost units, it hasn't been "zero overhead", performance drops significantly, and so I've made it a compile time option instead. See The Physical Units Interface document for more information about enabling strongly typed quantities/units. |
Do angle hiccups also occur in any code that's currently available in the PlayRho library? I ask because I've only seen angle hiccups when I've tried to add angle normalization to the library code. My interest in angle normalization is particularly to do with the body sweep angles and keeping them from otherwise being able to grow unbounded from say something just under constant rotation in a single direction. This seems akin to the linear problem As for what might be going wrong in the |
Hey @louis-langholtz ,
i have a problem with spurious hiccups in rotation when the angle goes from/to +PI / -PI.
Wrote a GravityJoint, which pulls bodies together. Now i want to rotate the second body to be upright wrt the direction of gravity towards the first body.
In a test a small and a big disk are connected using this joint, and the small disk slides around the surface of the big disk. (see code below)
This seemingly works, however on some rotations, when the small disk passes the point where it's angle flips from +PI to -PI the body has wrong angle values for a frame or two.
The location is not affected, only the rotation. This does not happen every time, but very often.
Console output, see how when the angle wraps, even if the joint sets 3.1258, after Step() the body has a rotation of -1.5201 instead of 3.1258 for a single step, and then continues with the correct values set by the joint in the next step:
A test using said joint:
Setting rotation in joint solver:
Do you have any idea what i am doing wrong here?
This has me clueless.
The full source for the GravityJoint can be found here https://github.com/ninnghazad/PlayRho/tree/gravity_joint .
The text was updated successfully, but these errors were encountered: