skyfielders / python-skyfield

Elegant astronomy for Python
MIT License
1.38k stars 208 forks source link

Add LVLH frame and geoid intersection method #839

Open jamesgrimmett opened 1 year ago

jamesgrimmett commented 1 year ago

Hi @brandon-rhodes, I made these modifications for a project that I was working on with skyfield, and thought that they might be more widely useful for others in the community.

Changes include;

It seems there are a few different conventions for defining an LVLH frame, but I've gone with z-axis anti-aligned with the position vector, and y-axis anti-aligned with the orbital momentum vector.

For the intersection method I've borrowed heavily from here. In short, a "distortion map" is defined to transform the ellipsoid into a unit sphere, and applied to both ellipsoid and vector. Then, the intersection problem is much easier to solve, and the inverse distortion can be applied to the solution.

I'd be interested to hear with you think! If you are in principle keen to add this functionality but have other ideas for the implementation, I'd be interested to discuss that also.

brandon-rhodes commented 1 year ago

I just wanted to leave a quick note to say that I'm planning to look over this by maybe mid-week this week, and respond with some feedback! I'll be interested to see how the code looks.

jamesgrimmett commented 1 year ago

Thanks! No hurry, by the looks of the tests, I still have some tidying up to do. Also, I thought it might be better if I move 4ca0a99 into a separate PR, so I'll aim to get to that today or tomorrow.

jamesgrimmett commented 1 year ago

Hi @brandon-rhodes, just thought I would ping you again for your thoughts/feedback on this PR. No hurry at all; I'm keen to hear what you think whenever you have the time.

brandon-rhodes commented 1 year ago

Ah, is your tidying-up now complete? Then I'll schedule some time this week to take a look—I'll try to take a look tomorrow morning.

jamesgrimmett commented 1 year ago

Ah yes, sorry about that, I should have dropped you a note to let you know I have tidied up and ran the tests locally to ensure they are passing.

Ly0n commented 11 months ago

This is really a helpful pull request. Thank you so much. I implemented my own LVLH reference frame in the past into skyfield and will compare this results with your implementation. Some feedback here from my side:

  1. I would not call it "Looking Vector" but "Line-of-Sight" (LOS).
  2. I'm working in Atmospheric Science with limb sounder. Such instruments need a yaw, pitch and roll rotation. The current implantation just has pitch and roll.

In about 2 months I will have a little bit more time working on this. Then I will also be able to open source my implementation to show more practical applications.

jamesgrimmett commented 11 months ago

This is really a helpful pull request. Thank you so much. I implemented my own LVLH reference frame in the past into skyfield and will compare this results with your implementation. Some feedback here from my side:

  1. I would not call it "Looking Vector" but "Line-of-Sight" (LOS).

  2. I'm working in Atmospheric Science with limb sounder. Such instruments need a yaw, pitch and roll rotation. The current implantation just has pitch and roll.

In about 2 months I will have a little bit more time working on this. Then I will also be able to open source my implementation to show more practical applications.

Thanks! I'm really glad to hear that you have found it useful.

You raise two very good points. I agree with both suggestions, thanks for pointing that out. I was fortunate to only need pitch and roll for the instrument I was working with, so I took a shortcut there. But, completely forgot to go back and add yaw.

I would be very keen to see your implementation/results once they are ready.

I also need to apologise to @brandon-rhodes for making several commits since marking this as ready for review - sorry! I hope it hasn't inconvenienced you. I will aim to make the two changes mentioned above in the next few days, add will add a comment to let you know once I have done that.

brandon-rhodes commented 11 months ago

I also need to apologise to @brandon-rhodes for making several commits since marking this as ready for review - sorry! I hope it hasn't inconvenienced you. I will aim to make the two changes mentioned above in the next few days, add will add a comment to let you know once I have done that.

On the contrary, I need to apologize, for having gotten busy back in June and never coming back to give feedback! I'll try to take a look today, so that you can make adjustments while you're in the code to look at the suggested name improvements.

brandon-rhodes commented 11 months ago

(I did look at the code later that day, by the way, but have not yet grabbed a pad and paper to work through exactly why osculating_elements_of() is being called, and whether there might be a simpler and faster way in Skyfield to get the same vectors. Hopefully later this week!)

jamesgrimmett commented 11 months ago

(I did look at the code later that day, by the way, but have not yet grabbed a pad and paper to work through exactly why osculating_elements_of() is being called, and whether there might be a simpler and faster way in Skyfield to get the same vectors. Hopefully later this week!)

Simpler and faster sounds appealing! I guess somehow we could just use the position and velocity vectors to calculate the frame rotation? Anyway, I won't get ahead of myself, keen to see what you have whenever you have the time.

brandon-rhodes commented 11 months ago

In case I don’t get a chance to go over the math today or tomorrow, I can at least share a few early thoughts about the API rather than making you wait!

I’ll keep thinking and later this week I’ll hope to make more comments. Thanks for having the PR include tests — that brings it much closer to completion and will make it much easier to merge!

jamesgrimmett commented 11 months ago

It almost feels like we need an object here that represents a vector direction from a specified xyz center. That single object could be returned by a satellite when it’s asked about a given pitch and roll; and then that single object could be consumed by intersection_of()

~Perhaps the looking_vector could be refactored as an attitude or line_of_sight function of EarthSatellite, returning an object for intersection_of()? Or perhaps it's better to keep this functionality separate from EarthSatellite? I'll put some thought into this and try put together a more specific description of how this could work.~ EDIT: scratch that - maybe it's not a bad idea overall, but I think I'd best just focus on representing looking_vector as some kind of vector object for now.

Also, while looking into adding a yaw rotation alongside pitch and roll, I've realised I think I need to be a bit more careful with the way the looking_vector is constructed (i.e., the order that the rotations are applied).

Thanks for the other tips and suggestions - very useful. I will address them and chip away at getting this into a mergeable state.

jamesgrimmett commented 10 months ago

I've had a bit more of a think about your initial feedback, and made some progress (I think..) in the right direction.

Interested to hear whether these changes are a step in the right direction, whenever you have some time @brandon-rhodes.

I'll track the progress/remaining to do's in a list here;

jamesgrimmett commented 7 months ago

I've made a set of changes to tick off those remaining items in the to-do list in this comment above. A few points to note/follow up questions;

I also rebased this branch to bring in the latest updates to master (i.e., the fixes for the Python 2 tests).

brandon-rhodes commented 7 months ago

@jamesgrimmett — Thank you for the updates! I just this morning have given a conference talk about Skyfield, which will encourage me to now return to the code and look over open issues and pull requests, so you have perfect timing. (It will also help that my spare hours won't be busy with writing the talk!) Hopefully I'll either be able to respond from here on the road, or else next week when I'm home. Feel free to ping me with another comment on the issue if you haven't heard back by the end of next week.

jamesgrimmett commented 7 months ago

Hi @brandon-rhodes - how coincidental! I hope your talk and travel went well. This morning I was reassuring myself that I had coded the attitude rotation correctly, by comparing results with some existing packages for transforming Euler angles to rotation matrices (e.g., this Matlab package). Initially I was quite concerned to be getting different results, before I discovered that other packages typically apply intrinsic rotations (reference axes rotate with the body), whereas I have implemented extrinsic rotations (relative to a fixed set of axes). With this is mind, I was then glad to see these results are identical to existing packages. I also learned that applying the same set of rotations intrinsically is as simple as reversing the order of multiplication of the rotation matrices, so that would be simple to implement, if desired.

I have updated the _attitude function docstring to make the extrinsic rotation more explicit, and also removed my usage of the deprecated positionlib.Geometric class. I believe that the testing pipeline should pass since you added a Python 2 fix to jplephem v2.21 (thanks!).

karatemir commented 2 months ago

@brandon-rhodes are you planning to merge this? what is the final status?