Generated reference › Eclipse Shadow Model — Robotics/Celestial Phenomena
kind: generated#block#robotics-celestial-phenomena

Eclipse Shadow Model — Robotics/Celestial Phenomena

Robotics/Celestial_Phenomena/Eclipse_Shadow_Model · 2 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.

Eclipse Shadow Model

Robotics / Celestial Phenomena

How much of the Sun's disc a spacecraft can see past the body it orbits. With r the spacecraft's position and s the Sun's, both measured from the centre of the shadowing body, R that body's radius and Rs the Sun's, the block answers the visible fraction of the solar disc and the shadow region by one of two models:

  • Cylindrical – the shadow is a cylinder of radius R pointing away from the Sun. With u = s/|s|, d = r·u and p = |r − d·u|, the spacecraft is in umbra (fraction 0) when d < 0 and p < R, and in sunlight (fraction 1) otherwise. There is no penumbra.
  • Dual cone – the Sun and the body are two discs as seen from the spacecraft, of apparent radii a = asin(Rs/|s − r|) and b = asin(R/|r|), whose centres are c = acos((−r)·(s − r) / (|r|·|s − r|)) apart. Sunlight when c ≥ a + b; umbra when c < b − a; antumbra, fraction 1 − b²/a², when c < a − b; otherwise penumbra, fraction 1 − A/(πa²) with A the exact area in which the two discs overlap, A = a²acos(x/a) + b²acos((c − x)/b) − c·y, x = (c² + a² − b²)/(2c), y = √(a² − x²).

Ports

  • r_sc – the spacecraft's position r, one [3,1] column [x; y; z] from the centre of the shadowing body, in any inertial frame.
  • r_sun – the Sun's position s, one [3,1] in the same frame, from the same centre, in the same length unit as r_sc and both radii.
  • fraction – the visible fraction of the solar disc, [1,1], from 0 (none) to 1 (all). The cylindrical model only ever answers 0 or 1.
  • region – the shadow region, [1,1]: 0 umbra, 1 sunlight, 2 penumbra, 3 antumbra – the Aerospace Blockset's own numbering. The cylindrical model only ever answers 0 or 1.

Parameters

  • Shadow Model – which geometry runs. This selects the arithmetic, not just a value:
    • Cylindrical – the cheap approximation: a sharp shadow with no penumbra, the Sun taken as infinitely far away.
    • Dual cone – umbra, penumbra and antumbra, with the Sun's real size and distance. The default.
  • Central Body Radius – R, the radius of the body casting the shadow, a positive scalar in the positions' unit. Defaults to 6378137, Earth's equatorial radius in metres.
  • Sun Radius – Rs, a positive scalar in the same unit; read only by the dual-cone model. Defaults to 695700000, the Sun's nominal radius in metres.
  • 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 chosen model is fixed at export time – a core exported as Cylindrical contains no dual-cone arithmetic – and both radii are baked into the emitted code rather than published as tunable parameters.

The three hardware targets are simulation-only: two arcsines, three arccosines and up to five square roots do not belong in a Q16.16 datapath, so the arithmetic runs in real inside a function and only the ports are fixed point. Those ports hold nothing beyond about ±32767, and the Sun is 1.496×108 km from the Earth, so a hardware export needs its positions and radii in a unit that brings the Sun inside that range – Earth radii work (the Sun is then about 23455 away and one Q16.16 step is about 97 m); metres and kilometres do not, and the fixed-point conversion wraps rather than saturating. The same step means a sample within about 10−5 of a shadow boundary can land on the other side of it in hardware than in software.

Simulink bridge

None, deliberately. The Aerospace Blockset's Eclipse Shadow Model (aerolibcelestial, both its Cylindrical and its Dual Cone entry) takes only the spacecraft's position on its one input and computes the Sun's itself, from a JPL DE ephemeris against a Julian date. This block takes the Sun on a port instead, so the two port lists cannot match and no parameter mapping could turn one into the other; wire an ephemeris in front of this block to reproduce the Simulink one. The geometry was checked against MathWorks' own implementation rather than against the block (see Notes). The per-block Sampling Time (s) → SampleTime pair that every other block carries has nothing to cross to here.

Notes

  • Algebraic and stateless: the outputs depend only on this sample's inputs.
  • Not linear, so the block carries no state space and model reduction correctly reports it as unmergeable.
  • A spacecraft inside the body (|r| < R) is in umbra, fraction 0, in both models. The Simulink block stops the run with an error there by default.
  • A spacecraft at or inside the Sun (|s − r| ≤ Rs) is in sunlight, and a Sun at the body's centre makes the cylindrical model answer sunlight everywhere outside the body.
  • Verified against R2026a: over 59997 points in four geometries this block's arithmetic agrees with the Aerospace Toolbox's own cylindrical and dual-cone estimators on every cylindrical answer and every dual-cone region, and on the dual-cone fraction to within 4.4×10−11 (bit for bit on 94.5 % of the points). Every length and dot product sums its three terms from z to x, because MATLAB's do; summed from x to z the cylindrical model disagreed on 729 points at the shadow's edge.
  • Only one body casts a shadow. The Simulink block can also count the Moon when the central body is the Earth; here a second copy of this block, with the Moon as its central body, gives that separately.

Code facts#

FactValue
registered typeRobotics/Celestial_Phenomena/Eclipse_Shadow_Model
familyRobotics/Celestial_Phenomena
solver environment classICoreBlock_0_Robotics_1_Celestial_Phenomena_2_Eclipse_Shadow_Model
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Celestial_Phenomena/Eclipse_Shadow_Model/ICoreBlock_0_Robotics_1_Celestial_Phenomena_2_Eclipse_Shadow_Model.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Celestial_Phenomena/Eclipse_Shadow_Model/ICoreBlock_0_Robotics_1_Celestial_Phenomena_2_Eclipse_Shadow_Model.h
default size on canvas170 × 90 px
ports at insert2 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubler_sc
2inICoreDoubler_sun
3outICoreDoublefraction
4outICoreDoubleregion

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 variableDefaultSimulink parameter
Shadow Modelstd::string(MODEL_CYLINDRICAL)%~%MODEL_DUAL_CONE~~MODEL_D…—
Central Body RadiuscFmt(EARTH_RADIUS)—
Sun RadiuscFmt(SUN_RADIUS)—

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.

supportSupport::None
Simulink path—
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): the Aerospace Blockset's Eclipse Shadow Model (aerolibcelestial, both its Cylindrical and its Dual Cone entry -- one block type) takes only the spacecraft's position on its single input and computes the Sun's itself from a JPL DE ephemeris and a Julian date. This block takes the Sun's position on a second port instead, so the port lists cannot match and no parameter mapping turns one into the other. Put an ephemeris in front of this block to reproduce the Simulink one

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).

Eclipse Shadow Model -- how much of the Sun a spacecraft sees past the body it orbits r = the spacecraft's position, s = the Sun's, both from the centre of the shadowing body; R = that body's radius, Rs = the Sun's. Two models, chosen by Shadow Model:

Cylindrical u = s/|s|, d = r.u, p = |r - d*u| fraction 0 and region 0 (umbra) when d < 0 and p < R, else 1 and 1 Dual cone a = asin(Rs/|s - r|), b = asin(R/|r|), c = acos((-r).(s - r)/(|r||s - r|)) c >= a + b sunlight 1 region 1 c < b - a umbra 0 region 0 c < a - b antumbra 1 - b^2/a^2 region 3 otherwise penumbra 1 - A/(pi*a^2) region 2 A = a^2*acos(x/a) + b^2*acos((c - x)/b) - c*y, x = (c^2 + a^2 - b^2)/(2c), y = sqrt(a^2 - x^2)

The arithmetic, its measurement against MathWorks' implementation and its four guards are documented once, in ICoreEclipseShadowSupport.cpp; this block's simulation calls that file and its ten generators emit the same statements in the same order.

⚠ ONE BLOCK, TWO LIBRARY ENTRIES. The Aerospace Blockset lists "Eclipse Shadow Model (Cylindrical)" and "Eclipse Shadow Model (Dual Cone)" separately, but they are one block type, EclipseShadowModel, differing only in the shadowModel parameter -- measured with get_param on both in R2026a. So here they are one block with a Shadow Model choice, and the choice is a MODE: the two run entirely different arithmetic and each has a rig of its own.

⚠ WHY THERE IS NO SIMULINK BRIDGE. The Simulink block takes ONE input, the spacecraft's position, and computes the Sun's (and optionally the Moon's) from a JPL DE ephemeris against a Julian date -- ephemerisModel DE405/421/423/430/432t, a start date, a time source. This block takes the Sun's position on its second port instead, so the two cannot share a port list and no parameter mapping can make one into the other. An ephemeris is its own row of work (the Planetary Ephemeris block), and a user wires one in front of this block.

⚠ AND THE SIMULINK BLOCK CANNOT BE RUN HERE AT ALL. Every set_param on it, and every simulation, loads the "Ephemeris Data for Aerospace Toolbox" support package, which is not installed on the machine this was measured on -- so the reference is the pair of estimator functions the Aerospace Toolbox's satellite scenario uses, which take the same inputs as the block's compiled cylindrical and dual-cone routines and answer in the same region codes.

⚠ THE HARDWARE TARGETS ARE SIMULATION-ONLY, and a Q16.16 port changes what a user must feed them. Two arcsines, three arccosines and five square roots do not belong in a fixed-point datapath, so the three HDL bodies compute in real and quantize only at the ports. But the

Sample results#

Eclipse Shadow Model — Sine Wave, [3,1]: amplitudes 1/2/3 at 2 rad/s (tried only because every scalar stimulus was refused)Eclipse Shadow Model — Sine Wave, [3,1]: amplitudes 1/2/3 at 2 rad/s (tried only because every scalar stimulus was refused)-1-0.500.51012345t (s)in ICoreDouble-Out-0 [3x1] entry 0in ICoreDouble-Out-0 [3x1] entry 0out ICoreDouble-Out-0out ICoreDouble-Out-1

Plotted: vector — Sine Wave, [3,1]: amplitudes 1/2/3 at 2 rad/s (tried only because every scalar stimulus was refused)

Category dynamic · sample time 0.1 · 60 steps · commit 6280f52f3 · produced by docsSample --out <folder> --blocks Rational_Resample,Three_Axis_Accelerometer,Three_Axis_Gyroscope,Three_Axis_Inertial_Measurement_Unit,Eclipse_Shadow_Model,To_String,String_To_ASCII,ASCII_To_String,Substring,String_Constant,String_Concatenate,String_Compare,String_Length --steps 60 · data docs/generated/samples/Robotics__Celestial_Phenomena__Eclipse_Shadow_Model.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).