Generated reference › CubeSat Vehicle Custom Pointing — Robotics/Spacecraft Dynamics
kind: generated#block#robotics-spacecraft-dynamics

CubeSat Vehicle Custom Pointing — Robotics/Spacecraft Dynamics

Robotics/Spacecraft_Dynamics/CubeSat_Vehicle_Custom_Pointing · 3 input / 4 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++

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.

CubeSat Vehicle (Custom Pointing)

Robotics / Spacecraft Dynamics

Flies a CubeSat: its orbit and its attitude together, with the attitude controlled to point a body axis at a direction of your own, the Primary Constraint input r expressed in the constraint frame: t1 = Cc·r. Each sample is one RK4 step of the Simulink block's own equations, with the Earth's orientation re-evaluated at every stage:

r′ = v,  v′ = RwoPMT(ωE × (ωE × rp) + 2ωE × vp + RpmTaecef)
q′ = ½Ω(w − CbfωE) q/|q|,  w′ = M

r and v are the ICRF state, q the ECEF-to-body quaternion and w the inertial body rate; RwoPM is the IAU-2000/2006 ECI-to-ECEF rotation without polar motion and Rpm the polar motion, both from the IERS table at the date; ωE = [0 0 7.2921158553×10−5] rad/s. The torque M is a discrete PID (P 10−5, I 10−10, D 0.01, no derivative filter) on the XYZ Euler angles of the alignment quaternion, which points the body primary alignment a1 along the target t1 and turns the secondary alignment a2 as close as it can to the secondary constraint t2 = Cc·(Secondary Constraint). The body inertia is the identity, as in the Simulink block, so the torque is the angular acceleration.

Ports

  • a_ecef – the vehicle's acceleration relative to the rotating Earth, in ECEF axes, [3,1], m/s². Not a force and not gravity: see Notes.
  • firstAlign – the body primary alignment vector a1, [3,1], any nonzero length; read every sample.
  • firstRef – the primary constraint r, [3,1], in the frame Constraint Coordinates names; read every sample.
  • X_ecef – position in ECEF (ITRF), [3,1], metres.
  • V_ecef – velocity relative to ECEF, [3,1], m/s.
  • q_eci2b – the ICRF-to-body quaternion, [4,1], scalar first.
  • q_ecef2b – the ECEF-to-body quaternion, [4,1], scalar first.

Parameters

  • Start Date – the UTC Julian date of t = 0 (default 2458488, which is juliandate(2019, 1, 4, 12, 0, 0)). It dates the Earth's orientation every sample.
  • Input Method – how the initial orbit is given:
    • Keplerian Orbital Elements – Semi-major Axis (m), Eccentricity, Inclination, RAAN, Argument of Periapsis and True Anomaly (degrees), with μ = 3.986004418×1014 m³/s². A circular orbit (eccentricity below 1e-12) reads Argument of Latitude, a circular equatorial one True Longitude and an elliptical equatorial one Longitude of Periapsis in place of the angles they replace. Then rotated by the IAU-1976 precession from the ECI Epoch.
    • ECI Position and Velocity – ECI Position (m) and ECI Velocity (m/s) at the ECI Epoch, rotated by the same precession.
    • ECEF Position and Velocity – ECEF Position (m) and ECEF Velocity (m/s) at the Start Date.
    • Geodetic LatLonAlt and Velocity in NED – Geodetic Position (latitude and longitude in degrees, WGS84 altitude in metres) and NED Velocity (m/s) at the Start Date.
  • ECI Epoch – the Julian date of the ECI frame the first two methods are given in (default 2451545, J2000).
  • Semi-major Axis (m), Eccentricity, Inclination (deg), RAAN (deg), Argument of Periapsis (deg), True Anomaly (deg), True Longitude (deg), Argument of Latitude (deg), Longitude of Periapsis (deg) – the Keplerian elements above, one number each. The orbit must be elliptical (eccentricity at least 0 and below 1).
  • ECI Position (m), ECI Velocity (m/s), ECEF Position (m), ECEF Velocity (m/s), Geodetic Position, NED Velocity (m/s) – three numbers each, read by the method that names them.
  • Euler Angles (deg) – roll, pitch and yaw of the body relative to the NED frame of the starting point, at t = 0.
  • Body Angular Rates (deg/s) – the body rate relative to that NED frame at t = 0, in body axes (default [0 0 -0.05168]).
  • Secondary Alignment – the body vector a2 that is turned as close as it can come to the secondary constraint (default [0 1 0]).
  • Secondary Constraint – the direction t2 for a2, in the constraint frame (default [0 0 1]).
  • Constraint Coordinates – the frame the constraints are given in: ECI Axes, ECEF Axes, NED Axes (the local north-east-down frame under the spacecraft) or Body-Fixed Axes.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

Python, MATLAB, Java, Rust, C and C++, from one program spelled six ways, so every target runs the simulation's arithmetic in the same order: the full 2941-term IAU-2000/2006 series at each RK4 stage, the IERS rows of the days the run covers, from the Start Date to the model's stop time. A sample past the stop time reads no IERS row and answers NaN. The initial state is computed at export and written as twenty constants. The other four are not offered and refuse the export by name: VHDL, Verilog, SystemVerilog and PLC Structured Text – a Julian date (2.4 million) and an orbit (7 million metres) do not fit a Q16.16 port, and the series alone is eighteen thousand constants.

Simulink bridge

Import and export, mapped to Aerospace Blockset's aerolibcubesatveh/CubeSat Vehicle (Custom Pointing), one for one: Start Date → sim_t0, Input Method → method, ECI Epoch → epoch, Semi-major Axis (m) → a, Eccentricity → ecc, Inclination (deg) → incl, RAAN (deg) → omega, Argument of Periapsis (deg) → argp, True Anomaly (deg) → nu, True Longitude (deg) → truelon, Argument of Latitude (deg) → arglat, Longitude of Periapsis (deg) → lonper, ECI Position (m) → r_eci, ECI Velocity (m/s) → v_eci, ECEF Position (m) → r_ecef, ECEF Velocity (m/s) → v_ecef, Geodetic Position → lla, NED Velocity (m/s) → v_ned, Euler Angles (deg) → euler, Body Angular Rates (deg/s) → pqr, Secondary Alignment → secondAlign, Secondary Constraint → secondRef, Constraint Coordinates → constraintCoord. Input Method and Constraint Coordinates use Simulink's own option spellings, so they cross losslessly. Always written: pointingMode Custom Pointing and firstAlignExt and firstRefExt Input port, secondAlignExt and secondRefExt Dialog, which fix this block's ports. The mission-analysis parameters (missionRT and the rest) do not cross: they only feed the Simulink block's report button, and change nothing it computes (measured, bit for bit). The Simulink block has no SampleTime: its PID runs at the model's base rate, which is this block's Sampling Time.

Notes

  • ⚠ There is no gravity in it. a_ecef is the acceleration relative to the rotating Earth, and the block adds the Coriolis and centrifugal terms itself, so with a_ecef = 0 it flies a straight line in ECEF. To fly an orbit, feed back a_ecef = g − 2ωE×Vecef − ωE×(ωE×Xecef), with g from a gravity block. That is the Simulink block's own contract.
  • The outputs are re-derived from the state every sample: X and V through the frames at that instant, and both quaternions through dcm2quat, so either may come out with a negative scalar part.
  • The PID's derivative has no filter, so the first sample carries a derivative kick of D·e/Ts – the Simulink block's own, and the reason its first second is lively.
  • The ECI-to-ECEF rotation the dynamics use takes ΔAT = 0, while the ECEF and geodetic initialisation takes ΔAT = 37 s; both are the Simulink block's, kept rather than corrected.
  • The Simulink block can also take the secondary vectors from ports, and the first ones from the dialog; this block carries the library preset's ports only, so a model that moves a vector between port and dialog does not import as this block.
  • Discrete: twenty states (the orbit, the attitude, the PID and a sample count), advanced once per sample. No direct feedthrough: the outputs come from the state.

Code facts#

FactValue
registered typeRobotics/Spacecraft_Dynamics/CubeSat_Vehicle_Custom_Pointing
familyRobotics/Spacecraft_Dynamics
solver environment classICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_CubeSat_Vehicle_Custom_Pointing
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Spacecraft_Dynamics/CubeSat_Vehicle_Custom_Pointing/ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_CubeSat_Vehicle_Custom_Pointing.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Spacecraft_Dynamics/CubeSat_Vehicle_Custom_Pointing/ICoreBlock_0_Robotics_1_Spacecraft_Dynamics_2_CubeSat_Vehicle_Custom_Pointing.h
default size on canvas190 × 120 px
ports at insert3 in, 4 out
code generators implementedPython, MATLAB, Java, Rust, C, C++

Ports#

#DirectionSignal typeDescription label
1inICoreDoublea_ecef
2inICoreDoublefirstAlign
3inICoreDoublefirstRef
4outICoreDoubleX_ecef
5outICoreDoubleV_ecef
6outICoreDoubleq_eci2b
7outICoreDoubleq_ecef2b

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
Start Date2458488sim_t0
Input MethodKeplerian Orbital Elements%~%ECI Position and Velocity%~%…method
ECI Epoch2451545epoch
Semi-major Axis (m)6878137a
Eccentricity0ecc
Inclination (deg)0incl
RAAN (deg)0omega
Argument of Periapsis (deg)0argp
True Anomaly (deg)0nu
True Longitude (deg)0truelon
Argument of Latitude (deg)0arglat
Longitude of Periapsis (deg)0lonper
ECI Position (m)[0 0 0]r_eci
ECI Velocity (m/s)[0 0 0]v_eci
ECEF Position (m)[0 0 0]r_ecef
ECEF Velocity (m/s)[0 0 0]v_ecef
Geodetic Position[0 0 0]lla
NED Velocity (m/s)[0 0 0]v_ned
Euler Angles (deg)[0 0 0]euler
Body Angular Rates (deg/s)[0 0 -0.05168]pqr
Secondary Alignment[0 1 0]secondAlign
Secondary Constraint[0 0 1]secondRef
Constraint CoordinatesECI Axes%~%ECEF Axes%~%NED Axes%~%Body-Fixed Axes~~ECI AxesconstraintCoord

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::Both
Simulink pathaerolibcubesatveh/CubeSat Vehicle\n(Custom Pointing)
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
always setpointingMode = Custom Pointing, firstAlignExt = Input port, secondAlignExt = Dialog, firstRefExt = Input port, secondRefExt = Dialog
ICore configSimulink parameterValue translation
Start Datesim_t0passes through
Input MethodmethodKeplerian Orbital Elements → Keplerian Orbital Elements, ECI Position and Velocity → ECI Position and Velocity, ECEF Position and Velocity → ECEF Position and Velocity, Geodetic LatLonAlt and Velocity in NED → Geodetic LatLonAlt and Velocity in NED
ECI Epochepochpasses through
Semi-major Axis (m)apasses through
Eccentricityeccpasses through
Inclination (deg)inclpasses through
RAAN (deg)omegapasses through
Argument of Periapsis (deg)argppasses through
True Anomaly (deg)nupasses through
True Longitude (deg)truelonpasses through
Argument of Latitude (deg)arglatpasses through
Longitude of Periapsis (deg)lonperpasses through
ECI Position (m)r_ecipasses through
ECI Velocity (m/s)v_ecipasses through
ECEF Position (m)r_ecefpasses through
ECEF Velocity (m/s)v_ecefpasses through
Geodetic Positionllapasses through
NED Velocity (m/s)v_nedpasses through
Euler Angles (deg)eulerpasses through
Body Angular Rates (deg/s)pqrpasses through
Secondary AlignmentsecondAlignpasses through
Secondary ConstraintsecondRefpasses through
Constraint CoordinatesconstraintCoordECI Axes → ECI Axes, ECEF Axes → ECEF Axes, NED Axes → NED Axes, Body-Fixed Axes → Body-Fixed Axes

Caveat (shown to the user): the library preset's shape: pointingMode Custom Pointing, firstAlignExt and firstRefExt Input port, secondAlignExt and secondRefExt Dialog -- which is what fixes this block's ports. The mission-analysis parameters only feed the Simulink block's report button and change nothing it computes (measured bit for bit), so they do not cross. The block has no SampleTime: its PID runs at the model's base rate.

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

CubeSat Vehicle (Custom Pointing) -- a CubeSat's orbit and attitude, flown together under its own pointing law Aerospace Blockset's aerolibcubesatveh holds three blocks that are ONE masked subsystem (MaskType "CubeSat Vehicle") with three presets: identical wiring, different mask values. This is the Custom Pointing preset: its primary alignment vector and its primary constraint arrive on PORTS, every other vector from the dialog. The arithmetic, its measurement against R2026a and the six export targets are in ICoreCubeSatVehicleSupport, which the three blocks share; this file is the preset's ports, description and Simulink entry.

MEASURED, NOT INFERRED (2026-10-02, BLOCKS_TO_ADD_TOOLBOXES.md aerolibcubesatveh, opened by FEATURES_TO_ADD.md BF6): every one of the subsystem's 2894 blocks' wiring was read, and a plain re-implementation of exactly the support's arithmetic followed the real block to 3e-16 relative in position and 2.8e-15 in every quaternion over 600 s of flight, nadir, Sun, custom and with gravity fed back.

Sample results#

CubeSat Vehicle Custom Pointing — Sine Wave, [3,1]: amplitudes 1/2/3 at 2 rad/s (tried only because every scalar stimulus was refused)CubeSat Vehicle Custom Pointing — Sine Wave, [3,1]: amplitudes 1/2/3 at 2 rad/s (tried only because every scalar stimulus was refused)05e51e61.5e6012345t (s)in ICoreDouble-Out-0 [3x1] entry 0in ICoreDouble-Out-0 [3x1] entry 0in ICoreDouble-Out-0 [3x1] entry 0out ICoreDouble-Out-0 [3x1] entry 0out ICoreDouble-Out-1 [3x1] entry 0out ICoreDouble-Out-2 [4x1] entry 0

59 sample(s) were non-finite (nan/inf) and are absent from the plot; they are in the table below and in the JSON.

tin ICoreDouble-Out-0 [3x1] entry 0in ICoreDouble-Out-0 [3x1] entry 0in ICoreDouble-Out-0 [3x1] entry 0out ICoreDouble-Out-0 [3x1] entry 0out ICoreDouble-Out-1 [3x1] entry 0out ICoreDouble-Out-2 [4x1] entry 0
0[0, 0, 0][0, 0, 0][0, 0, 0][1.613e6, 6.686e6, 1.251e4][-6913, 1668, -0.2005][0.7071, 9.296e-6, -0.7071, -9.295e-6]
0.4[0.7174, 1.435, 2.152][0.7174, 1.435, 2.152][0.7174, 1.435, 2.152][1.611e6, 6.687e6, 1.251e4][-6913, 1668, 0.1453][nan, nan, nan, nan]
0.8[0.9996, 1.999, 2.999][0.9996, 1.999, 2.999][0.9996, 1.999, 2.999][1.608e6, 6.688e6, 1.251e4][-6912, 1669, 1.188][nan, nan, nan, nan]
1.2[0.6755, 1.351, 2.026][0.6755, 1.351, 2.026][0.6755, 1.351, 2.026][1.605e6, 6.688e6, 1.251e4][-6912, 1670, 2.296][nan, nan, nan, nan]
1.6[-0.05837, -0.1167, -0.1751][-0.05837, -0.1167, -0.1751][-0.05837, -0.1167, -0.1751][1.602e6, 6.689e6, 1.252e4][-6912, 1670, 2.796][nan, nan, nan, nan]
2[-0.7568, -1.514, -2.27][-0.7568, -1.514, -2.27][-0.7568, -1.514, -2.27][1.6e6, 6.69e6, 1.252e4][-6912, 1670, 2.385][nan, nan, nan, nan]
2.4[-0.9962, -1.992, -2.988][-0.9962, -1.992, -2.988][-0.9962, -1.992, -2.988][1.597e6, 6.69e6, 1.252e4][-6912, 1669, 1.313][nan, nan, nan, nan]
2.8[-0.6313, -1.263, -1.894][-0.6313, -1.263, -1.894][-0.6313, -1.263, -1.894][1.594e6, 6.691e6, 1.252e4][-6912, 1668, 0.2297][nan, nan, nan, nan]
3.2[0.1165, 0.2331, 0.3496][0.1165, 0.2331, 0.3496][0.1165, 0.2331, 0.3496][1.591e6, 6.692e6, 1.252e4][-6913, 1668, -0.2078][nan, nan, nan, nan]
3.6[0.7937, 1.587, 2.381][0.7937, 1.587, 2.381][0.7937, 1.587, 2.381][1.589e6, 6.692e6, 1.252e4][-6912, 1668, 0.266][nan, nan, nan, nan]
4[0.9894, 1.979, 2.968][0.9894, 1.979, 2.968][0.9894, 1.979, 2.968][1.586e6, 6.693e6, 1.252e4][-6912, 1669, 1.364][nan, nan, nan, nan]
4.4[0.5849, 1.17, 1.755][0.5849, 1.17, 1.755][0.5849, 1.17, 1.755][1.583e6, 6.694e6, 1.252e4][-6912, 1670, 2.419][nan, nan, nan, nan]
4.8[-0.1743, -0.3487, -0.523][-0.1743, -0.3487, -0.523][-0.1743, -0.3487, -0.523][1.58e6, 6.694e6, 1.252e4][-6912, 1670, 2.793][nan, nan, nan, nan]
5.2[-0.8278, -1.656, -2.483][-0.8278, -1.656, -2.483][-0.8278, -1.656, -2.483][1.577e6, 6.695e6, 1.252e4][-6912, 1670, 2.257][nan, nan, nan, nan]

Every 4th of 60 samples, from the vector stimulus.

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 a3549d241 · produced by docsSample --out <folder> --blocks CubeSat_Vehicle_Nadir_Pointing CubeSat_Vehicle_Sun_Tracking CubeSat_Vehicle_Custom_Pointing --steps 60 · data docs/generated/samples/Robotics__Spacecraft_Dynamics__CubeSat_Vehicle_Custom_Pointing.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).