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

Gimbal lock issue #194

Closed
diogoscf opened this issue Apr 10, 2020 · 12 comments
Closed

Gimbal lock issue #194

diogoscf opened this issue Apr 10, 2020 · 12 comments

Comments

@diogoscf
Copy link

diogoscf commented Apr 10, 2020

d3-geo uses Euler rotation angles, which means Gimbal locks can occur. This means that, depending on the rotation of the globe visualization, the rotation will start being weird. In the case of an orthographic projection, this happens at either pole of the globe. An example of this issue can be seen here, on a globe that uses d3 geo.

I would personally suggest using unit quaternions (versors) instead of Euler angles, as they would solve this issue.

@mbostock
Copy link
Member

d3-geo doesn’t implement interactive rotation, so the concept of gimbal lock doesn’t really apply. Please see these examples of dragging using versors:

https://observablehq.com/@d3/versor-dragging
https://observablehq.com/@d3/versor-zooming

@diogoscf
Copy link
Author

diogoscf commented Apr 10, 2020

The mentioned issue happens in the examples you mentioned. Add a line of code projection.rotate([0,90,0]), click on the globe to refresh, and try to rotate the globe through the outside of the projection. Here's a GIF demonstrating it:

weird behaviour

I'm almost certain this is due to a Gimbal lock, as two axes are aligned and therefore the mouse input rotates both axes, in opposite ways, at the same time, causing the weird behaviour

@mbostock
Copy link
Member

Suggestions are welcome on the notebook!

@diogoscf
Copy link
Author

diogoscf commented Apr 10, 2020

And where might that be?

@mbostock
Copy link
Member

@Fil
Copy link
Member

Fil commented Apr 10, 2020

The instability comes from the computation of Euler angles from the versor:
https://github.com/Fil/versor/blob/a3ed3a2e2d963eba56aa398a57c9143e0a1e2574/src/versor.js#L32
this formula isn't stable when |q[0] * q[1] + q[2] * q[3]| and the like are close to 0, a situation which happens at both poles.

We can fix it by switching to [q[1], (Math.sign(q[2]) * Math.PI) / 2, q[3]] in that case.

I'll push the changes tomorrow—a complication is that we have 3 versions floating around (versor 0.0.3, 0.1, and attitude). The issue in any case belongs to those projects not to d3-geo.

@diogoscf
Copy link
Author

Ok thank you very much

@mbostock
Copy link
Member

@Fil Would you mind moving that repo into the D3 org so I can contribute?

@Fil
Copy link
Member

Fil commented Apr 11, 2020

The fix I proposed earlier was not exact, it only stops the jumps but doesn't return the correct angles.

Now I think I've managed to fix the North Pole rotations, but for the South Pole there is another issue—it looks like the versor we create from the angles is wrong. So I'm not sure I'll be able to solve this today!

(Note: I work on the attitude code base rather than versor.)

Fil added a commit to Fil/attitude that referenced this issue Apr 11, 2020
@Fil
Copy link
Member

Fil commented Apr 11, 2020

I've just fixed it in the attitude module, as you can verify at
https://observablehq.com/d/7a912fba32fbe641
by setting a rotate of [0,±90]
=> attitude@0.1.2 is jumpy, attitude@0.1.3 is smooth.

Surprisingly, the issue was different for the north polar and south polar rotations! In one case it was the way we transformed euler angles into a versor that was buggy; in the other it was the way around.

@jrus
Copy link
Contributor

jrus commented Apr 17, 2020

It is inevitable that there are some singularities in the values of Euler angles for certain rotations. Shuster’s 1993 review of attitude representations has a nice discussion:

https://scholar.google.com/scholar?cluster=7745064288898196753

(scroll down to the bottom half of page 460)


Of course, for the purpose of just drawing a globe, as long as the rotations are nearby and accurately converted to some Euler angle representation, then the output images should also be nearby, even if there are sometimes discontinuous jumps in the intermediate parameters.

Has there been any consideration of adding an ability to d3-geo to rotate points by passing in a quaternion or similar rotation representation, instead of only the z-x-y flavor of Euler angles?

@mbostock
Copy link
Member

I’d be opening to changing the internal representation as long as it’s backwards-compatible.

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

No branches or pull requests

4 participants