Keplerian Orbit Simulator

Keplerian Orbit Simulator Used AI

40 devlogs
84h 19m
Created by NOT_A_ROBOT

A Keplerian orbit simulator library. If you're a Kerbal Space Program player, you'll recognize this as the "On-Rails" physics mode that kicks in during time warp or when a vessel is out of physics range/unloaded.

Written in Rust.

Devlog is "incomplete"; this project started before Summer of Making.

AI used, but not primarily for code generation. AI was used for:
- API design discussion, such as function signatures
- Finding external sources for equations. Most of my equations have citations to external sites.
- Finding hard-to-catch bugs. All code that it generates is manually reviewed, and there are numerous unit tests for core functionality.
- Reviewing code. Sometimes I make mistakes that AI finds, and all its suggestions are manually reviewed.

Timeline

Improved UI:
- Grouped time controls into popup when the window is too small
- Use min instead of m for minutes
- Format time using scientific notation

Improved time controls:
- Increased slider touch target to 48dp
- Added draggable (not demonstrated) textbox for time value
- Added time speed unit selectors + automatic picking
- Improved FPS display

I added time controls to the simulation! You can now view the time since epoch, change how it's displayed, and change the current time speed!

I added pausing and removed the unused debug menu

I switched the camera to make the Z axis point up

Update attachment

Fixing the transparency issue was a two-step process for me. First, I turned on blend so that transparency pixels would mix properly. Second, I sorted the points by the distance from the camera, so that the furthest points would be drawn first and the closer points can get layered on top of it properly.

Update attachment

I made the little square dots in the trajectory path into circular dots! Unfortunately, there seem to be a few issues with transparency. I guess that's what I'll work on next.

Update attachment

It indeed was not too hard to attach it to the actual orbit.
Next up: I need to make the dots actually dots by using a circle texture.

At last, orbit trajectory lines are now implemented! Or, I guess, a prototype of one. Currently it skips the main orbital mechanics code and just follows a circle, but it shouldn't be too hard to attach it to the actual orbit.

Update attachment

The autoscaling sprites worked, but there seems to be a depth buffer issue, sadly. I'll have to investigate why this happens.

Update attachment

Autoscaling sprites are working! Or at least, in the basic dev test it does. Time to integrate it into the demo!

I'm having trouble implementing a good way to display the orbital trajectory lines, so I started a minimal Rust project to hopefully develop it with less distractions.

Update attachment

I've made a banner image for this project!
I used Visual Studio Code to make it since many other drawing tools (e.g. GIMP) didn't have Hackatime support.

Update attachment

After refactoring the scene code, we finally got a basic demo of orbits working!!

Refactoring, refactoring, refactoring! Oh boy!
I'm refactoring my demo code to make it more modular, but it seems I'm struggling with Rust's strict type checking system. This is going to be a pain.

Update attachment

Got basic GUI and interactivity working! Also added an FPS counter.

Update attachment

Now that I've finished the harness for the web version and errors will almost certainly get displayed, I decided on a good stack for the visualization:
- Trunk for running the web server with auto refresh
- three-d for rendering in 3D
- egui for rendering the GUI

After following the guide I managed to render a basic sphere! How exciting.

Update attachment

I finished the panic handler and the heartbeat/watchdog mechanism so that if the WASM thing suddenly stops, JavaScript can notify the user about it.

Update attachment

I've been working more on the web demo's panic handler and found a compiler bug. I'll work on a minimum reproducible example for the rust team to handle.

Update attachment

I added a level of redundancy for the panic handler: in case if it somehow fails to create the dialog element, it falls back into just using alert()s.

Update attachment

Starting work on the demo!
Panics in WASM don't really tell the user what happened and only logs some cryptic messages in the console, so first and foremost I'm writing a custom panic handler which should be nearly infallible.

Update attachment

I'm done with the mu setter, and PR #24 has been merged!
Now I think I want to do some miscellaneous improvements to the codebase.

Update attachment

Things are looking up for the mu setter! I've made a draft PR: #24

Progress for mu setter:

- [X] Implement all mu setter modes

- [X] Write tests for mu setters

- [ ] Write documentation examples for mu setters

- [ ] Resolve TODOs

- [ ] Remove usage warnings and #[doc(hidden)]s

Update attachment

I take that back, I missed some untested edge cases! Whoops.
It thankfully didn't take too long to fix up. Hopefully next devlog will be about the mu setter? We'll see.

Update attachment

The experimental-sv2kep branch has been merged!
Next up: Implementing the extra modes for the mu setter.
Then I can start working on making the demo and ship the project!

Update attachment

The persistence and determination paid off. I have fixed the flaws, and now the test passes!
I am very ecstatic right now. I might be able to merge the PR soon!

Update attachment

I've been quiet these past seven days, but trust me, I've been chipping away at the problem for a while. First I found more equations for those edge cases (shoutouts to Space StackExchange!), then when that didn't fully work, I added more debug info to see what's going on. Sadly, I don't seem to have fully fixed this problem. I'm not all out of hope, however. There's definitely a way to fix it that I haven't found yet; there always is, and I'm not going to give up yet.

Update attachment

Upon further testing, it seems that I've overlooked some testcases... Some of the values returned NaNs, caused by the longitude of ascending node and argument of periapsis being undefined in circular and equatorial orbits. I have yet to find a solution on how to mitigate this problem. I think I might be able to use the longitude of periapsis instead of the argument of periapsis, but I have yet to find the proper equation to derive the longitude of periapsis.

But hey, at least I found the problem before the PR got merged!

Update attachment

Tests created and all tests pass! Now that functionality is tested and working, next up is just documentation fixes and then I think it should be good to merge.

https://github.com/Not-A-Normal-Robot/keplerian-sim/pull/21 checklist:

[X] Basic functionality
[X] Hyperbolic support
[X] Unit tests
[ ] Docstring examples
[ ] Review docstrings and remove TODOs
Update attachment

Second iteration: I switched to another source for the equations: https://orbital-mechanics.space/classical-orbital-elements/orbital-elements-and-the-state-vector.html

This has better hyperbolic orbit support. Another thing checked in the checklist for this PR!

https://github.com/Not-A-Normal-Robot/keplerian-sim/pull/21

  • [X] Basic functionality
  • [X] Hyperbolic support
  • [ ] Unit tests
  • [ ] Docstring examples
  • [ ] Review docstrings and remove TODOs
Update attachment

I've completed my first iteration on the state vector to orbit struct converter!
I've based my equations mostly from: https://downloads.rene-schwarz.com/download/M002-Cartesian_State_Vectors_to_Keplerian_Orbit_Elements.pdf
New PR: #21
New branch: experimental-sv2kep State Vectors to Keplerian (orbital elements)

Checklist:
- [X] Basic functionality
- [ ] Hyperbolic support
- [ ] Unit tests
- [ ] Docstring examples
- [ ] Review docstrings and remove TODOs

Update attachment

experimental-state-vector-getter has been merged! The next step should be to add an orbit constructor that takes in state vectors and a mu (gravitational parameter) value. And then after that we can borrow some code from that for the other mu setter modes. And after that is probably when I'll make the web/WASM demo and ship it. Or at least, that's my goal.

Update attachment

I've added the unit tests for the new state vectors getters! Now that I've confirmed the functionality of this and the new unchecked functions, hopefully I can migrate the existing functions to use the unchecked functions so that I can resolve this minor doctest failure and make the results exact.

Update attachment

State vector getter progress: I made most of the doctests pass, and the ones that didn't was very close to passing (only failed due to FP imprecision).
However, this isn't enough testing. I haven't made comprehensive unit tests for the new state vector getters. After that's done I might want to migrate some of the code to use the unchecked versions internally... but this might introduce trouble in citing sources for equations.

Either way, new draft PR! #20

Update attachment

I decided not to go for the mu setter first, but to make a more efficient state vector getter!

You see, if you call the position and velocity getter function separately, it ends up doing quite a few duplicate operations. Because of this, I'm creating more unchecked functions that take in multiple variables to allow redundant operations to be manually removed. And I'm using those unchecked functions in the state vector getter, so that API consumers can get the position and velocity more efficiently.

No commit just yet — I still haven't tested everything and written documentation.

Update attachment

I realized I didn't fully resolve merge conflicts from the first devlog correctly and some of the documentation was mismatched. Whoops!

Incorrect documentation is worse than no documentation so I have fixed it.

Next, I think I'll try adding the other setter modes for the gravitational parameter (mu), as well as conversion from state vectors to orbits.

Update attachment

Small improvements:
1. I added command line argument parsing to the dump-orbits example binary.
2. I removed some unnecessarily-cached values in the Orbit struct. Although this led to a 7% performance regression in the worst case, that is only in the benchmarking environment where there is nothing else happening. In practical usage scenarios, though, the reduced struct size should increase the chance of cache hits and therefore reduce the amount of time the CPU needs to wait for RAM. And besides, it saves on a little memory.

Update attachment

More CI work!
I added more checks to CI to ensure less problems with the code:
1. Check if cargo doc returns any errors
2. Check if code is formatted properly (cargo fmt)
3. Audit for security vulnerabilities (cargo audit)
4. Check for license mismatches etc. (cargo deny)

Update attachment

Previous update: I accidentally said experimental-tasks. The actual branch name was experimental-velocity-getter. I mixed it up with another project of mine, whoops!

Anyways, I've finished merging the experimental-velocity-getter branch to main. I also edited the CI to run Clippy as well so that I don't forget that. All tests pass and it seems like a go to release the next version to !

Update attachment

I'm currently trying to merge the experimental-tasks branch to main. I've dealt with the merge conflicts on the core part of the library and I was able to confirm that all tests pass. There's still quite a few benchmarks and example binaries I still have to resolve before the merge is complete.

Update attachment