Orbit Propagator Kepler — Robotics/Spacecraft Dynamics
Robotics/Spacecraft_Dynamics/Orbit_Propagator_Kepler · 0 input / 2 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text
Description#
The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.
Orbit Propagator Kepler (unperturbed)
Robotics / Spacecraft Dynamics
A source: the position and velocity of a spacecraft on an unperturbed two-body ellipse, t seconds after its initial state, in the central body's inertial frame. With semi-major axis a, eccentricity e, gravitational parameter μ and the perifocal unit vectors P and Q:
- M = M₀ + n·t, n = √(μ/a³), and Kepler's equation E − e·sin E = M solved by Newton's method (30 steps from E = M ± 0.85e);
- r = a(cos E − e)·P + a√(1−e²)·sin E·Q;
- v = √(μa) / (a(1 − e·cos E)) · (√(1−e²)·cos E·Q − sin E·P).
Whatever form the initial state is given in, it is turned into a, e, M₀, n, P and Q once, when the configuration loads.
Ports
- r – the position, [3,1] [x; y; z] in the inertial frame, from the body's centre, in the Units' length.
- v – the velocity, [3,1], in the Units' velocity.
Parameters
- Initial State Format – how the initial state is given:
- Orbital elements – by the Orbit Type's elements. The default.
- ICRF state vector – by ICRF Position and ICRF Velocity.
- Orbit Type – which elements describe the orbit (with Orbital
elements):
- Keplerian – Semi-major Axis, Eccentricity, Inclination, RAAN, Argument of Periapsis and True Anomaly. The default.
- Elliptical equatorial – Semi-major Axis, Eccentricity, Longitude of Periapsis and True Anomaly; the inclination is 0 whatever the Inclination field holds.
- Circular inclined – Semi-major Axis, Inclination, RAAN and Argument of Latitude; e = 0.
- Circular equatorial – Semi-major Axis and True Longitude; e = 0 and i = 0.
- Semi-major Axis – a, positive, in the Units' length. Default 6786000.
- Eccentricity – e, from 0 up to but not including 1. Default 0.01.
- Inclination – i, in the Angle Units. Default 50.
- RAAN – the right ascension of the ascending node. Default 95.
- Argument of Periapsis – ω. Default 93.
- True Anomaly – ν at t = 0. Default 203.
- True Longitude – for Circular equatorial. Default 0.
- Argument of Latitude – for Circular inclined. Default 0.
- Longitude of Periapsis – for Elliptical equatorial. Default 0.
- ICRF Position – the initial position as three numbers, for ICRF state vector. Default [3649700 3308200 −4676600].
- ICRF Velocity – the initial velocity, in the Units' velocity. Default [−2750.8 6666.4 2573.4].
- Central Body – sets μ: Earth (the default, 3.986004418×1014 m³/s²), Moon, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Sun, or Custom.
- Custom Gravitational Parameter – μ for a Custom body, in the Units' length cubed per second squared, used as given. Default 4.305×1013.
- Units – the length of every position, radius and axis, and
the velocity unit:
- Metric (m/s) – metres, m/s. The default.
- Metric (km/s) – kilometres, km/s.
- Metric (km/h) – kilometres, km/h.
- English (ft/s) – feet, ft/s.
- English (kts) – nautical miles, knots.
- Angle Units – Degrees (the default) or Radians, for every angle above.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. The fifteen folded constants are baked into the emitted code; no parameter is tunable on a generated core. The software targets keep their own sample clock; the three hardware targets and PLC Structured Text read the testbench's simulation time.
The hardware targets are simulation-only: the solve runs in
real inside a function, and only the two output ports are Q16.16.
Those ports hold nothing beyond about ±32767, so an Earth orbit needs
kilometres (Metric (km/s)) or nautical miles, never metres or feet.
Simulink bridge
Import and export, mapped to Aerospace Blockset's
aerolibsatdyn/Orbit Propagator Kepler (unperturbed) (the library
name breaks its line after "Propagator"). Every
parameter above crosses one for one: Initial State Format →
stateFormatKep, Orbit Type → orbitType,
Semi-major Axis → semiMajorAxis, Eccentricity →
eccentricity, Inclination → inclination, RAAN
→ raan, Argument of Periapsis →
argPeriapsis, True Anomaly → trueAnomaly, True
Longitude → trueLon, Argument of Latitude →
argLat, Longitude of Periapsis → lonPeriapsis,
ICRF Position → inertialPosition, ICRF Velocity →
inertialVelocity, Central Body → centralBody,
Custom Gravitational Parameter → customMu, Units →
units, Angle Units → angleUnits; every option
list is Simulink's own, so lossless. Always written: propagator
Kepler (unperturbed), dateOut off (there is no date output
here), outportFrame ICRF, accelIn off and
cbPoleSrc Dialog (which keeps a Custom body from adding a port).
The numerical propagator, the fixed-frame output and the Julian-date output do
not cross, and neither does a hyperbolic orbit – the Simulink block
accepts e = 1.2 and this one refuses e ≥ 1. The Simulink block defines
no SampleTime, so the rate stays on the ICore side.
Notes
- Stateless: the output is a closed-form function of time, so a dropped sample costs nothing and a long run accumulates no integration error.
- Not linear, so the block carries no state space.
- Refused with a reason: a semi-major axis that is not positive, an eccentricity outside 0, 1), a non-positive μ, and a state vector that is not a bound ellipse (at or above escape speed) or has no angular momentum.
- Verified against R2026a: over 500 samples of five configurations (each element form, the state vector, four bodies, three unit systems and both angle units) this block's arithmetic follows the Simulink block to 1.1×10−9 of each output's peak, and to about 10−14 on the circular orbits and the state vector. The gap on an eccentric orbit is the reference's: its eccentric anomaly strays from a 50-digit solution by up to 6.3×10−10 rad at e = 0.637, where this block's stays within 3×10−15.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Spacecraft_Dynamics/Orbit_Propagator_Kepler |
| family | Robotics/Spacecraft_Dynamics |
| solver environment class | ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_Orbit_Propagator_Kepler |
| source | [src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Spacecraft_Dynamics/Orbit_Propagator_Kepler/ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_Orbit_Propagator_Kepler.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Spacecraft_Dynamics/Orbit_Propagator_Kepler/ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_Orbit_Propagator_Kepler.h |
| default size on canvas | 170 × 80 px |
| ports at insert | 0 in, 2 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | out | ICoreDouble | r |
| 2 | out | ICoreDouble | v |
Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.
Configuration variables#
| Config variable | Default | Simulink parameter |
|---|---|---|
Initial State Format | std::string(FORMAT_ELEMENTS)%~%FORMAT_STATE~~FORMAT_ELEMENTS | stateFormatKep |
Orbit Type | std::string(ORBIT_KEPLERIAN)%~%ORBIT_ELL_EQ%~%ORBIT_CIRC_… | orbitType |
Semi-major Axis | 6786000 | semiMajorAxis |
Eccentricity | 0.01 | eccentricity |
Inclination | 50 | inclination |
RAAN | 95 | raan |
Argument of Periapsis | 93 | argPeriapsis |
True Anomaly | 203 | trueAnomaly |
True Longitude | 0 | trueLon |
Argument of Latitude | 0 | argLat |
Longitude of Periapsis | 0 | lonPeriapsis |
ICRF Position | [3649700.0 3308200.0 -4676600.0] | inertialPosition |
ICRF Velocity | [-2750.8 6666.4 2573.4] | inertialVelocity |
Central Body | bodies~~Earth | centralBody |
Custom Gravitational Parameter | 4.305e13 | customMu |
Units | units~~Metric (m/s) | units |
Angle Units | Degrees%~%Radians~~Degrees | angleUnits |
Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.
Simulink bridge#
| support | Support::Both |
| Simulink path | aerolibsatdyn/Orbit Propagator\nKepler (unperturbed) |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | propagator = Kepler (unperturbed), dateOut = off, outportFrame = ICRF, accelIn = off, cbPoleSrc = Dialog |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Initial State Format | stateFormatKep | Orbital elements → Orbital elements, ICRF state vector → ICRF state vector |
Orbit Type | orbitType | Keplerian → Keplerian, Elliptical equatorial → Elliptical equatorial, Circular inclined → Circular inclined, Circular equatorial → Circular equatorial |
Central Body | centralBody | Earth → Earth, Moon → Moon, Mercury → Mercury, Venus → Venus, Mars → Mars, Jupiter → Jupiter, Saturn → Saturn, Uranus → Uranus, Neptune → Neptune, Sun → Sun, Custom → Custom |
Units | units | Metric (m/s) → Metric (m/s), Metric (km/s) → Metric (km/s), Metric (km/h) → Metric (km/h), English (ft/s) → English (ft/s), English (kts) → English (kts) |
Angle Units | angleUnits | Degrees → Degrees, Radians → Radians |
Semi-major Axis | semiMajorAxis | passes through |
Eccentricity | eccentricity | passes through |
Inclination | inclination | passes through |
RAAN | raan | passes through |
Argument of Periapsis | argPeriapsis | passes through |
True Anomaly | trueAnomaly | passes through |
True Longitude | trueLon | passes through |
Argument of Latitude | argLat | passes through |
Longitude of Periapsis | lonPeriapsis | passes through |
ICRF Position | inertialPosition | passes through |
ICRF Velocity | inertialVelocity | passes through |
Custom Gravitational Parameter | customMu | passes through |
Caveat (shown to the user): the position and velocity cross as the block's two outputs in ICRF; the Julian-date output (dateOut), the fixed-frame output, the numerical propagator and an acceleration input do not exist here and are always written off. cbPoleSrc is written Dialog so a Custom body does not add a pole-orientation port. A hyperbolic orbit does not cross: Simulink accepts e = 1.2, this block refuses e >= 1. The Simulink block has no SampleTime, so the rate stays on the ICore side
Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.
The verdict above is
tools/docs/check_block_descriptions.py(P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.
File banner (developer view)#
The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).
Orbit Propagator Kepler (unperturbed) -- a two-body ellipse, in closed form A SOURCE. At time t (seconds from the start of the run):
M = M0 + n t, n = sqrt(mu/a^3) E - e sin E = M, by Newton: E0 = M +/- 0.85 e (the sign of sin M), then 30 steps r = a(cos E - e) P + a sqrt(1-e^2) sin E Q v = sqrt(mu a) / (a(1 - e cos E)) * (sqrt(1-e^2) cos E Q - sin E P) * (the unit's time scale)
P and Q are the perifocal unit vectors in the inertial frame. How the user gave the initial state -- four orbit-element forms, or an inertial state vector -- is folded into a, e, M0, n, P and Q ONCE, when the configuration loads, so the per-sample arithmetic is the same code whatever was typed, and the ten targets carry the same fifteen constants.
MEASURED AGAINST THE AEROSPACE BLOCKSET'S Orbit Propagator (propagator Kepler (unperturbed)), R2026a, 2026-09-11 -- the block simulates without the ephemeris data package, unlike the eclipse model:
⚠ mu FOR EACH BODY, read off the block's own output (|v0|^2 / (2/|r0| - 1/a) on its default elements, and again from a circular orbit, agreeing to about 1e-16 relative): Earth 3.986004418e14 m^3/s^2 (EGM2008), Moon 4.902801076e12, Mars 4.2828314258067e13, and the DE405 values for the rest. A textbook two-body propagator with Earth's 3.986004418e14 follows the block to 1.25e-7 m over 6000 s; with 3.986004415e14 it is 0.017 m out. ⚠ UNITS CHANGE THE LENGTH OF EVERYTHING, not just the output: in Metric (km/s) the block reads the 6786000 of its default semi-major axis as KILOMETRES and converts mu to km^3/s^2. Metric (km/h) is kilometres with velocity per hour; English (kts) is NAUTICAL miles with knots; English (ft/s) is feet. A Custom body's mu is taken in the chosen length unit cubed per second squared, as given -- measured, it is not converted. ⚠ THE FOUR ELEMENT FORMS, each measured against a reference built from the textbook elements (all within 1.1e-7 m over 6000 s): Keplerian a, e, i, RAAN, argument of periapsis, true anomaly Elliptical equatorial a, e, longitude of periapsis (as the argument of periapsis), true anomaly -- inclination 0 WHATEVER the inclination field says (measured: set to 50 it moves nothing) Circular inclined a, i, RAAN, argument of latitude (as the true anomaly), e = 0 Circular equatorial a, true longitude (as the true anomaly), e = 0, i = 0 and an ICRF state vector propagates from exactly the position and velocity given. ⚠ THE REFERENCE'S KEPLER SOLVER IS LOOSER THAN THIS ONE. At e = 0.637 the Simulink block's eccentric anomaly differs from a 50-digit solution by up to 6.3e-10 rad on 78 of 500 samples; this block's is within 3e-15 of it on every sample. No stopping rule of a Newton iteration reproduces the block's scatter (starters M, M + e sin M, pi, M +/- 0.85e; tolerances 1e-6 to
Sample results#
Plotted: free — No input: the block run alone
Category source · sample time 0.1 · 60 steps · commit 93133d604 · produced by docsSample --out <folder> --blocks Gain_Scheduled_Lead_Lag Controller_1D Controller_Blend_1D Controller_2D Controller_3D Observer_Form_1D Self_Conditioned_1D Line_Of_Sight_Access Orbit_Propagator_Kepler Attitude_Dynamics Attitude_Profile_Nadir_Pointing Attitude_Profile_Geographic_Pointing Multitaper_PSD Cross_Power_Spectral_Density Transfer_Function_Estimate Envelope_Spectrum Compose_String Scan_String --steps 60 · data docs/generated/samples/Robotics__Spacecraft_Dynamics__Orbit_Propagator_Kepler.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).