-
-
Notifications
You must be signed in to change notification settings - Fork 208
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
Add a function to Geocentric to produce velocity in earth-fixed ITRF #476
Comments
That sounds like a useful addition! It might take me a couple of weeks for me to answer in detail, as I'm currently working on Skyfield's handling of polar motion corrections, but I'll go ahead and mark this as a feature request and say that, yes, I think we should work out how this should fit into Skyfield. Meanwhile: have you worked out how to produce this value yourself, so your project is unblocked? Or is one of the rotations not quite producing the output you need? If there's any snag, let me know, so at least you have the numbers you need quickly whether or not they come from inside of Skyfield! |
Great, and yes. I'm basically implementing the function I descried in my own module. It isn't pretty, but it's a heck of a lot better than manually interfacing with SGP4 myself like I was doing before.
|
It always makes me pause for a moment that we never account for the rate at which t.M rotates — which really ought to make it into the velocity too — but I suppose it's such a small effect that it might even be below machine precision and something the vectors can't represent. I'm glad you have a local implementation, and I'll return to this when I get the chance — at the latest, by mid-December, when I return from a trip. |
This eliminates two instances of duplicated code. Also, we tweak a method name to better reflect its idiosyncratic return value (“twist”). Like several recent commits, this works toward #476.
There! Per the commit shown above, the next version of Skyfield should allow positions to be turned into ITRS positions and velocities. Instead of adding yet another method — which eventually would have required dozens of methods, if we continued down the dark path of two methods (position and velocity) per reference frame (of which we have at the moment at least a half-dozen) — I have pivoted to a general mechanism that should let us support as many frames as we want. This will be released with the next version of Skyfield, probably in about two weeks, but you can try it out ahead of time with:
Enjoy! |
Ah, that's a much cleaner way to do it, and it seems to work splendidly. Thank you for implementing this so quickly! I do find the choice of name |
Thanks for trying it out ahead of time! I’m glad it seems to produce useful numbers. “Twist” is, yes, distinct from rate, and is a private term of my own since I can’t find an official term for the matrix that method produces. A toolkit like SPICE offers routines that handle a 6×6 matrix
You can then multiply a 6-element vector But that approach seems to require a little bit of extra work. If I have, say, an Earth location, and an Which is different from the But you can also avoid the matrix × matrix multiply to bring the “twist” all the way into the GCRS, by doing two matrix multiplies in a row instead of trying to cleverly fit it all into a single 6×6, as you can see from the code in the commit referenced above: if you apply the twist before then doing the final rotation into the target reference frame, then both the ITRS-relative velocity and the velocity due to the reference frame itself are naturally rotated together as a single quantity. So for this first operation version of reference frame conversion, I decided to try to be clever and avoid the expense and rounding of an extra matrix × matrix multiply. We’ll see how it goes; there might be reference frames where that ‘twist’ matrix is not as easy to build as it is for the ITRS? And let me know if you are aware of any official name for it; one argument against its use in the code might be simply how difficult it is to explain! |
So looking through The biggest challenge I see with trying to use the derivative of the rotation matrix is estimating that derivative. Unless I'm missing something, that would have to be a finite estimate of the derivative, which may introduce more error than the existing solution. Keep in mind that the approximation All that said, if this idea gets extended to arbitrary rotating reference frames which may not have an approximately constant rotation rate, the derivative method may be more extensible. Thanks for the thorough answer on this. |
The SPICE library seems to calculate the derivative of the rotation matrix by getting the skew-symmetric angular velocity matrix, and multiplying it by the rotation matrix R that rotates GCRS → ITRS. I think that result is what it plugs into the lower-left corner of its 6×6 state-transformation matrix. Would that produce the matrix you are thinking of, without incurring the need to perform a finite estimate? |
That's exactly what I'm thinking. I've included the relevant equation from "Principles of GNSS, Inertial and Multisensor Integrated Navigation Systems" by Paul D. Groves. In this case |
Thanks for providing that additional background! Instead of |
I think calling it To that end, I believe the current implementation may have a sign error. All the skew-symmetric matrices we're dealing with here are a special type which encodes a vector cross product. For some vector
So in the specific case of the earth angular velocity in ITRS (or in GCRS for that matter), the angular velocity is in the positive
This means that in |
Thanks for the detailed suggestions! You have sent me back into the SPICE library for my morning reading, to work out what they call this matrix, and to learn about its proper sign — since my goal here is for Skyfield to follow their approach fairly closely. Here is their Required Reading document on rotations: https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/FORTRAN/req/rotation.html And here are the docs to two specific routines whose source code I have just reviewed:
The second source file defines a crucial subroutine called in the first source file — which happens to be
To imagine our simple earth-angular-velocity case, I believe we can take
Thus, in the case Here’s their source file, so you don’t have to download their whole Fortran distribution yourself if you want to follow their derivation and see where a sign difference might have crept in between their approach, which uses rotation matrices, and your own approach that instead considers a matrix cross product directly — they do note that:
— so that might provide a starting point for comparing your cross product with theirs. The file: Let me know if you work out why there’s a difference in sign! |
1. Instead of my invented name “twist”, use a method name that more closely resembles the name `DRDTRT` that SPICES uses for the matrix. 2. Since the angular matrix should be skew-symmetric, try subtracting instead of inverting the matrix in the reverse transform.
I think the discrepancy arises from how
If I'm reading that right, they're defining their skew-symmetric matrix in this case to correspond to a negative cross product (or, equivalently, a cross product taken from the right). Referring to the resulting matrix as Note that the angular velocity here is A bit further down they expand a bit on the skew-symmetry of
Assuming those indices are row-major (I vaguely recall matrices sometimes being column-major in FORTRAN [?]), this agrees with my earlier sign convention for denoting skew-symmetry as a cross product. I think the sign convention subtleties get a little lost in the Ultimately I think you're right to want to stay in agreement with an established implementation like SPICE, but an explanation in the docs about exactly which reference/resolving frame is being used for what is currently called Thanks again for unpacking all this with me. Chasing sign conventions I'm sure isn't the most thrilling use of your efforts here. Edit: Just saw that commit from this morning after posting this. 1 I'm not sure I ever fully explained the notation here. An angular velocity |
For the moment I will see if the renaming helps me keep it straight; happily, I still have a
Yes, I think that puts it well. To compare with my way of thinking about it — my governing principle in preferring the current sign is, I suspect, this code from
Since R gets applied in a "forward" direction (without a sign change and without transposition), I like that V gets applied the same way (without sign change, without transposition). But what, then, does V physically mean? Matrix V must mean "how a vector r rotated into the target reference frame, that's stationary in the inertial frame, will move in that new frame." So if the vector r is, say, a point on the equator out in the direction of the vernal equinox and thus roughly Moving from the GCRS into the ITRS, then, means that everything in the universe starts rotating in the opposite direction from the Earth’s rotation: New York is heading east around the axis, so the Sun does the opposite and rises in the east and sets in the west. Thus, exactly as you say: its sign is reversed with respect to the direction of rotation of the frame itself.
It’s surprisingly helpful to discuss points of Skyfield’s design with other folks familiar with the math (often, more familiar with the math than I am!), and small things like sign conventions can wind up being terribly inconvenient later in a project’s lifetime if chosen poorly. So thanks for the discussion, it’s been helpful, and better grounded me in the math. |
When working with satellites, it is often necessary to have the velocity of a given satellite expressed in ECEF coordinates. Such a function would essentially mirror
Geocentric.itrf_xyz()
, but would produce aVelocity
object. The process for transforming the velocity in this manner are identical to those for position, so the existing rotation matrixTime.M
andTime.gast
are sufficient.I can submit a PR implementing this, but I'd like feedback on if there is a better place for this functionality to live (and if this feature is welcome in the first place). My first thought is to add an additional function called
Geocentric.itrf_xyz_velocity()
, but I'm brand new to this tool, so there may be a better place.The text was updated successfully, but these errors were encountered: