Show HN: Elodin – A better framework for physics simulation (github.com)
Have you ever wondered what happens when a satellite is first placed into orbit? It turns out that often, they tumble out of control, end over end, in a miraculous fight against stability. Check out our demo here of a control system attempting to rectify this: https://app.elodin.systems/sandbox/hn/cube-sat
The spacecraft does not appreciate tumbling: deploying solar panels and antennas might not work, and doing anything worthwhile is out of the picture. So what are you to do about this? You'll equip your satellite with reaction wheels (or magnetorquers), but now you have a second problem. What commands do you send to the reaction wheels?
We created Elodin to help solve problems like this. These problems are firmly in the realm of GNC (guidance, navigation, and control) engineers; they are traditionally solved with MatLab / Simulink, a bunch of Python scripts, and/or a tool like Gazebo or Basilisk. While building the flight software for a deep-space mission, I tried all of these tools and didn’t like them. In particular, I found that running Monte Carlo simulations in the cloud was painful.
So we set out to build a better framework for physics simulation. You might call it "Tensorflow for Physics." The name fits for two reasons: we use XLA to accelerate your math, and we've built an extensible framework for creating new physics engines. Most physics engines are fixed-function. For example, something like MuJoCo (https://mujoco.readthedocs.io/en/stable/overview.html) is great for traditional robotics, but GMAT (https://gmat.atlassian.net/wiki/spaces/GW/overview) is far better for orbital analysis. No single physics engine can solve all problems, and it’s hard to integrate multiple engines. Our framework allows you to easily compose different physics algorithms.
Space is hard enough—let’s not have software make it harder than it needs to be! We are still early in building our stack, so we’d be grateful to hear any feedback that you have.
51 comments
[ 5.2 ms ] story [ 105 ms ] thread(odin means one in some languages)
If it's all just code, and we can compute some (multi-)objective function from each simulation run, then we can turn a metaheuristic loose on it ;)
EDIT: answered in a cousin comment.
To my mind any software that calls itself a generic physics engine is not doing "real" physics, more like "Blender physics".
Of course this can still be super useful! But the field of numerical physics is super broad and deep, and different sub-fields require dramatically different data structures and algorithms.
Also just in case you were unaware, the name 'nox' refers to a popular Python testing framework... so if you were to release 'nox-py' on PyPi it would be a bit confusing. Maybe "nox-ecs"? Sorry to be a bummer!
Curious, why reimplementing jax in rust (nox)?
A fun side-effect of this architecture is that when we run your simulation we aren't actually running your code, Python or Rust in the loop. We compile down the whole thing to HLO at runtime, then run that HLO. So we could theoretically support lots of other languages.
Is there a crate in the works? I would start using it (and contributing if needed) instantly.
Anyway, to each their own, it's fine for people who somehow think because there are wrapper methods everywhere a code is "cleaner". I just submit that this really is a aesthetic preference, and that instead of trying to "fix" other professions, understand there are often reasons why things are that way when everyone in a field works that way.
Of course, I once was that physicist! Now I prefer working with arrays and functions that receive arrays and return arrays, even in the top-level, user-facing script.
But who knows, maybe there will be a next stage in the journey!
I used to work at a company that wrote an atomic scale simulation package. Every dev was a physics/chemistry PhD turned coder. We didn't quite hit one comment for _every_ line of code, but we were close! At first I really hated this style; one comment every few lines. However, I eventually learned to kind of like it, even though it was a bit redundant.
I don't really have a point here, but I just wanted to echo your statement that the physicists-turned-coder style is real!
(a) is the calculation itself the end goal--e.g. am I trying to draw a plot which shows the motions of the three bodies?
or
(b) am I trying to use the code which describes the motion of the 3 bodies as a modular part of a system to answer other questions, perhaps interactively.
If everything is a one-off, and you're working on a very small team, of course excessive abstractions make little sense. But that's not how engineering is done. Abstractions are really important, because they allow us to collaborate.
As a computer scientist this sounds odd to me, but if you are the sole consumer of your own API, you do you!
From the little I can see of it, it looks like you don't allow writes to data and instead prefer to return a new thing based on a query? Based entirely on the below.
``` @system def control( sensor: Query[WorldPos, WorldVel, Goal], rw: Query[RWAxis, RWForce] ) -> Query[RWForce]: ```
I assume this is due to the distributed nature of your simulation framework?
Either way, neat. Very interested in this though for more terrestrial applications.
EDIT: One thing I forgot to add is that we actually use Bevy for our 3D viewer. IMO, its the perfect framework for developing 3d applications that aren't quite games. Most games engines make you carry around a ton of features you will never use, but Bevy is really good at being flexible, lightweight, and easy to use