Keplerian Elements To Cartesian — Robotics/Spacecraft Dynamics
Robotics/Spacecraft_Dynamics/Keplerian_Elements_To_Cartesian · 0 input / 0 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.
Keplerian Elements To Cartesian
Robotics / Spacecraft Dynamics
The six classical orbital elements turned into a position and velocity in a planet-centred equatorial frame:
- p = a·(1 − e²) on an ellipse, 2·a on a parabola, a·(e² − 1) on a hyperbola
- rpqw = p/(1 + e·cos ν)·[cos ν; sin ν; 0], vpqw = √(μ/p)·[−sin ν; e + cos ν; 0]
- r = R3(RAAN)·R1(incl)·R3(argp)·rpqw, and the same rotation for v
Ports
- a – the semi-major axis, [1,1], in the length unit. On a hyperbola (ecc > 1) the distance from periapsis to the hyperbola's centre; on a parabola the periapsis radius.
- ecc – the eccentricity, [1,1]. Within 1e-10 of 1 it is parabolic.
- incl – the inclination, [1,1], in the angle unit.
- RAAN – the right ascension of the ascending node, [1,1].
- argp – the argument of periapsis, [1,1].
- nu – the true anomaly, [1,1].
- Position – r, a [3,1] column in the length unit.
- Velocity – v, a [3,1] column in the speed unit.
RAAN, argp and nu are wrapped into [0, 2π) first (x − 2π·floor(x/2π)); incl is used as given. A negative a or a negative ecc makes both outputs NaN, as in Simulink.
Parameters
- Units – the length and speed units of a, r and v:
- Metric (m/s) – metres, metres per second
- Metric (km/s) – kilometres, kilometres per second
- Metric (km/h) – kilometres, kilometres per hour
- English (ft/s) – feet, feet per second
- English (kts) – nautical miles, knots
- Angle Units – Degrees or Radians, for the four angle inputs.
- Central Body – Earth, Moon, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Sun or Custom. Each named body carries its gravitational parameter μ, the same double the Simulink block uses (Earth 3.986004418e14 m³/s²).
- Gravitational Parameter – μ, used only when Central Body is Custom, in the Units' own length cubed per second squared: m³/s² for Metric (m/s), km³/s² for both Metric (km/s) and Metric (km/h), and ft³/s² for both English units – so under English (kts) it is in feet while positions are in nautical miles. Measured; the Simulink dialog relabels its prompt the same way. Default 42828314258067, the Simulink dialog's own.
- Open Or Undefined Orbit Action – None, Warning or Error, for a negative a or ecc, a parabolic or hyperbolic orbit, and an angle outside Simulink's documented range (incl in [0, π], the other three in [0, 2π]). Warning reports each kind once per run; Error stops the run.
- 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. Every parameter is baked into the arithmetic at export.
The three HDL targets are simulation-only: trigonometry, a square root and
a division by p do not belong in a Q16.16 datapath, so they compute in real and
quantize only at the ports – which also bounds what can cross a port, ±32768, so
model an HDL export in kilometres or nautical miles. HDL and PLC Structured Text have no NaN:
an invalid element set writes 0.0 there, and the action config does not travel into any
export. MATLAB multiplies the three rotation matrices exactly as the Simulink block does; the
other nine write the product out entry by entry, which agrees to a few units in the last
place.
Simulink bridge
Import and export, mapped to Aerospace Blockset's aerolibsatdyn/Keplerian Orbital
Elements to Cartesian State Vectors (its library path carries an embedded newline before
Cartesian). Units → units, Angle Units →
angleUnits, Central Body → centralBody, Gravitational Parameter
→ customMu and Open Or Undefined Orbit Action → action; every
combo is Simulink's own list, so the mapping is lossless. orbitType is always
written as Keplerian: Simulink's Elliptical equatorial, Circular inclined and
Circular equatorial types take 4, 4 and 2 inputs (a, ecc, nu, lonper / a, incl, RAAN, arglat /
a, truelon – measured) and do not cross. The Simulink block has no SampleTime
(measured), so the rate stays on the ICore side.
Notes
- Algebraic and stateless; nonlinear, so no state space.
- Measured, and bit-exact against R2026a on about 2300 element sets over all five units, both angle units, all eleven bodies, circular, equatorial, retrograde, parabolic, hyperbolic, negative and multi-lap inputs.
- A circular or equatorial orbit needs no other orbit type here: at ecc = 0 the result depends on argp + nu only, and at incl = 0 on RAAN + argp only, so feed the combined angle in either and 0 in the other.
- The parabolic band is 1e-10, found by bisection against the block: an ecc of 1 − 9.99e-11 is parabolic (p = 2a) and 1 − 1.0000000827e-10 is not – where p = a·(1 − e²) collapses the orbit to a point.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Spacecraft_Dynamics/Keplerian_Elements_To_Cartesian |
| family | Robotics/Spacecraft_Dynamics |
| solver environment class | ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_Keplerian_Elements_To_Cartesian |
| source | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Spacecraft_Dynamics/Keplerian_Elements_To_Cartesian/ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_Keplerian_Elements_To_Cartesian.cpp |
| header | src/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Spacecraft_Dynamics/Keplerian_Elements_To_Cartesian/ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_Keplerian_Elements_To_Cartesian.h |
| default size on canvas | 170 × 150 px |
| ports at insert | ? in, ? out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | a |
| 2 | in | ICoreDouble | ecc |
| 3 | in | ICoreDouble | incl |
| 4 | in | ICoreDouble | RAAN |
| 5 | in | ICoreDouble | argp |
| 6 | in | ICoreDouble | nu |
| 7 | out | ICoreDouble | Position |
| 8 | out | ICoreDouble | Velocity |
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 |
|---|---|---|
Units | OE::comboValue(OE::unitOptions(), "Metric (m/s)") | units |
Angle Units | OE::comboValue(OE::angleUnitOptions(), "Degrees") | angleUnits |
Central Body | OE::comboValue(OE::centralBodyOptions(), "Earth") | centralBody |
Gravitational Parameter | OE::DEFAULT_CUSTOM_MU_TEXT | customMu |
Open Or Undefined Orbit Action | OE::comboValue(OE::actionOptions(), "Warning") | action |
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/Keplerian Orbital Elements to\nCartesian State Vectors |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| always set | orbitType = Keplerian |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
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 |
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 |
Gravitational Parameter | customMu | passes through |
Open Or Undefined Orbit Action | action | None → None, Warning → Warning, Error → Error |
Caveat (shown to the user): orbitType is always written as Keplerian: the other three orbit types take 4, 4 and 2 inputs (measured) and a fixed port list cannot follow them. The library path carries an embedded newline before 'Cartesian'. The 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).
Keplerian Orbital Elements to Cartesian State Vectors The six classical elements (a, ecc, incl, RAAN, argp, nu) to a position and velocity in a planet-centred equatorial frame: Vallado's coe2rv,
p = a(1 - e^2) (ellipse), 2a (parabola), a(e^2 - 1) (hyperbola) r_pqw = p/(1 + e cos nu) [cos nu; sin nu; 0], v_pqw = sqrt(mu/p) [-sin nu; e + cos nu; 0] r = R3(RAAN) R1(incl) R3(argp) r_pqw, and the same rotation for v.
MEASURED against R2026a's aerolibsatdyn block, a built-in block type whose source does not ship, and BIT-EXACT against it on every captured sample; the rules are in ICoreOrbitalElementsSupport.h and the user-visible ones on the description below.
⚠ ONLY THE "Keplerian" ORBIT TYPE. Simulink's other three orbit types take 4, 4 and 2 inputs, which a fixed port list cannot follow; the export pins orbitType = Keplerian.
⚠ THE THREE HDL TARGETS ARE SIMULATION-ONLY real arithmetic, quantized only at the ports, and HDL and PLC Structured Text write 0.0 where the other targets write NaN.
Sample results#
56 sample(s) were non-finite (nan/inf) and are absent from the plot; they are in the table below and in the JSON.
| t | in ICoreDouble-Out-0 | in ICoreDouble-Out-0 | in ICoreDouble-Out-0 | out ICoreDouble-Out-0 [3x1] entry 0 | out ICoreDouble-Out-1 [3x1] entry 0 |
|---|---|---|---|---|---|
| 0 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 0.4 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
| 0.8 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 1.2 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
| 1.6 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 2 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
| 2.4 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 2.8 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
| 3.2 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 3.6 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
| 4 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 4.4 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
| 4.8 | -2 | -2 | -2 | [nan, nan, nan] | [nan, nan, nan] |
| 5.2 | 0.5 | 0.5 | 0.5 | [0.2499, 0.006544, 3.808e-5] | [-1.138e6, 4.889e7, 4.267e5] |
Every 4th of 60 samples, from the table stimulus.
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 0.9987 |
ramp | Ramp: slope 1 from t = 0 | 0 … 27.67 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 0 … 0.2499 |
step | Step: 0 -> 1 at t = 1 s | 0 … 0.9987 |
Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample
Category static · sample time 0.1 · 60 steps · commit 383c0ecf1501cf1d43d89b8f688fc2fcad5e9b52 · produced by docsSample --out <folder> --blocks Ideal_Airspeed_Correction WGS84_Gravity_Model Linear_Regression_Predictor Linear_Classifier_Predictor Crossover_Pilot_Model Precision_Pilot_Model Tustin_Pilot_Model FIR_Least_Squares_Design FIR_Equiripple_Design Cartesian_To_Keplerian_Elements Keplerian_Elements_To_Cartesian --steps 60 · data docs/generated/samples/Robotics__Spacecraft_Dynamics__Keplerian_Elements_To_Cartesian.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).