Voyager 1, from the inside.

An educational view of the spacecraft. Rotate it, separate its assemblies, and follow the connections. Geometry and power estimates are illustrative.

Selection, antenna signal, data packets and connectionsPower: RTG → distribution → baysControl and data: bays, instruments, thrustersSwitched off in the chosen yearEverything the panels say comes from voyager1.sysml: 31 parts (rtgs[3], thrusters[16]), 23 connections, requirements R-01 to R-03 and the dates each instrument was switched off, the two computers of each pair and the FDS fault of 2023-2024. The drawing adds the structure, shapes, positions and animation; the magnetometer boom (about 13 m) and the plasma antennas (about 10 m) are drawn cut short. Bus dimensions are approximate, the power curve is a fit to two NASA data points, and the thruster split, jets, packets and tape reels are schematic. NASA's 3D model (JPL/VTAD) was used only as a reference for proportions.

RTG power and switch-offs

Curve: exponential fit to the two verified data points (470 W in 1977, 225 W in 2023). NASA gives about −4 W per year; from 2026 it is a projection.

Instruments by year

    Requirements and checks

      Model data

      • mass launchMassKg 815 · dryMassKg 721.9 · propellantKg 93.1
      • light distanceAU 172.52 × 8.317 min/AU = 23.9 h one way, 47.8 h round trip (Oct 2026)
      • power watts2026 = 225 − 4 × 3 = 213 W (NASA straight line); the exponential curve gives 212 W
      • telecom downlink 160 bit/s, uplink 16 bit/s, X band 8.4 GHz and S band 2.3 GHz

      Mission: distance from the Sun

      Curve: straight lines between the milestones below (a few AU off between them; planet distances are approximate); the distance is from the Sun, Earth's orbit changes it by up to 1 AU. After Oct 2026 it is a projection at the last speed.

      Milestones (click to jump)

        Telecom

        • dish 3.7 m, one feed for both bands; transmit gain 47 dB at X band and 36 dB at S band; half-power half-width 0.32° (X) and 1.1° (S)
        • transmitters selectable output 12 or 22 W at X band, 9 or 26 W at S band (PDS); drawn as two modules on the radio bay top, schematically
        • low gain on the feed structure of the dish; covers the hemisphere the dish faces; used for manoeuvres and anomalies
        • record 30 cm gold-plated copper disc in an aluminum cover, with cartridge and needle; 16⅔ rpm, 53-54 min per side, played outside in
        Press “Send a command now”.

        Parts

        Model connections

        
         

        Model coverage: what is drawn and where

        • modelled and drawn gain, power options and beam widths in the Telecom panel · rtgs[3] · power · ccs · fds · aacs · dtr · radio · hga · tank · thrusters[16] · attitude1, attitude2, tcm · scanPlatform · record · iss · iris · uvs · pps · mag · pws · pls · lecp · crs · pra (shares antennas with pws) part, name, type, ports
        • modelled, drawn as a connection 23 connect (40 branches) top layer when selected or with “All connections”
        • modelled, only in the panels requirements R-01 to R-03 · 3 assert · verification checkAttitude · propellantKg, lightHours, roundTripHours · units, wordBits, memoryWords of CCS, FDS, AACS · FDS fault dates requirements and data panel
        • modelled as data of the year offYear of each instrument · launchWatts, watts2023 · pointingFrom and pointingTo of each thruster branch · faultFrom, engineeringFrom, scienceFrom of the FDS year control, switch-offs, power, thruster branches, FDS status
        • drawn, not modelled structure: bus, top deck, bays, booms, cradle · shapes, positions and sizes · scan platform sweep · antenna signal · thruster jets · data packets and tape reels · break marks on the long booms belongs to the drawing
        • neither modelled nor drawn RSS (radio science) · mass and power of each unit · content of each bay · which unit of each A/B pair is in use · hydrazine lines and wiring harness paths no verified source
        Full model (voyager1.sysml)
        // Voyager 1, modelled from public NASA/JPL sources and Gen-AI toosl provided by https://apricot.tools.
        // Facts with a source: launch 1977-09-05, 815 kg launch / 721.9 kg dry, ten-sided bus,
        // 3.7 m high-gain dish (X 8.4 GHz / S 2.3 GHz), 3 MHW-RTGs (470 W at launch, 225 W in 2023,
        // about -4 W/year), 16 hydrazine thrusters, eleven investigations, instrument shutdown dates.
        // Not modelled (no verified source): masses and powers of each unit, bay assignment.
        package Voyager1 {
            private import ScalarValues::*;
            private import RealFunctions::*;
        
            metadata def SafetyCritical;
        
            // ---- Structure ----------------------------------------------------
        
            port def PowerPort;
            port def DataPort;
            port def ControlPort;
            port def RadioPort;
        
            part def Unit {
                attribute offYear : Real = 0.0;     // calendar year the unit was switched off; 0 = still on
            }
        
            // Power
            part def Rtg :> Unit {
                attribute launchWatts : Real = 157.0;     // each of three; 470 W in total at launch
                port powerOut : PowerPort;
            }
        
            part def PowerDistribution :> Unit {
                port busIn : PowerPort;
                port busOut : PowerPort;
            }
        
            // Brains: each Voyager carries two of each computer (CCS, FDS, AACS). For most of the
            // mission the two CCS were used non-redundantly to add command capacity; which unit of the
            // FDS or AACS pair is in use is not public.
            part def CommandComputer :> Unit {
                attribute units : Integer = 2;
                attribute wordBits : Integer = 18;
                attribute memoryWords : Integer = 4096;   // plated-wire, non-volatile, per unit
                port powerIn : PowerPort;
                port command : ControlPort;
                port telemetry : DataPort;
            }
            part def FlightDataSystem :> Unit {
                attribute units : Integer = 2;
                attribute wordBits : Integer = 16;
                attribute memoryWords : Integer = 8198;   // per unit
                // Memory-chip fault: Nov 14 2023 all telemetry stopped, Apr 20 2024 engineering data
                // returned after code was relocated around the bad chip, science data came back from
                // May 2024 with full recovery of the powered instruments in June 2024.
                attribute faultFrom : Real = 2023.87;
                attribute engineeringFrom : Real = 2024.30;
                attribute scienceFrom : Real = 2024.50;
                port powerIn : PowerPort;
                port telemetry : DataPort;
                port storage : DataPort;
                port radio : DataPort;
            }
            part def AttitudeControl :> Unit {
                attribute units : Integer = 2;
                attribute wordBits : Integer = 18;
                attribute memoryWords : Integer = 4096;   // per unit
                port powerIn : PowerPort;
                port command : ControlPort;
                port thrust : ControlPort;
                port scan : ControlPort;
            }
            part def TapeRecorder :> Unit {
                attribute capacityMB : Real = 64.0;
                attribute tracks : Integer = 8;
                attribute records : String = "plasma wave high-rate data, played back about every six months";
                port record : DataPort;
            }
        
            // Telecom
            part def HighGainAntenna :> Unit {
                attribute diameter : Real = 3.7;           // m, Cassegrain
                attribute gainXdB : Real = 47.0;           // transmit boresight gain, PDS
                attribute gainSdB : Real = 36.0;
                attribute beamHalfWidthXDeg : Real = 0.32; // half-power half-width, PDS
                attribute beamHalfWidthSDeg : Real = 1.1;
                port feed : RadioPort;
            }
            part def RadioSubsystem :> Unit {
                attribute xBandGHz : Real = 8.4;
                attribute sBandGHz : Real = 2.3;
                attribute downlinkBps : Real = 160.0;      // normal telemetry
                attribute uplinkBps : Real = 16.0;
                attribute xBandWatts : String = "12 or 22";   // selectable transmitter output, PDS
                attribute sBandWatts : String = "9 or 26";
                port powerIn : PowerPort;
                port feed : RadioPort;
                port telemetry : DataPort;
            }
        
            // Propulsion
            part def HydrazineTank :> Unit {
                port feedLine : ControlPort;
            }
            part def Thruster :> Unit {
                port valve : ControlPort;
            }
            // One branch of thrusters. JPL: two attitude branches and one trajectory-correction (TCM) branch.
            part def ThrusterBranch :> Unit {
                attribute role : String;
                attribute pointingFrom : Real = 0.0;   // calendar year the branch took over pointing; 0 = never used for it
                attribute pointingTo : Real = 0.0;     // calendar year it handed pointing over; 0 = no end stated
            }
        
            // Science
            part def Instrument :> Unit {
                attribute acronym : String;
                attribute range : String;       // what it measures, as NASA publishes it
                port data : DataPort;
            }
            part def ScanPlatform :> Unit {
                port drive : ControlPort;
            }
            // Mission milestones: calendar year and distance from the Sun (AU). Planet distances are
            // approximate (the planet's orbit radius); 94 AU for the termination shock is not verified.
            part def MissionEvent {
                attribute atYear : Real;
                attribute sunAU : Real;
            }
        
            part def GoldenRecord :> Unit {
                attribute diameterCm : Real = 30.0;       // gold-plated copper disc in an aluminum cover
                attribute rpm : Real = 16.6667;           // 16 2/3 rpm, played outside in
                attribute minutesPerSide : Real = 53.5;   // 53 to 54 minutes
                attribute pulsarsOnCover : Integer = 14;
            }
        
            part def Spacecraft {
                part rtgs : Rtg[3];
                part power : PowerDistribution;
                part ccs : CommandComputer;
                part fds : FlightDataSystem;
                part aacs : AttitudeControl;
                part dtr : TapeRecorder;
                part radio : RadioSubsystem;
                part hga : HighGainAntenna;
                part tank : HydrazineTank;
                part thrusters : Thruster[16];
                part attitude1 : ThrusterBranch;
                part attitude2 : ThrusterBranch;
                part tcm : ThrusterBranch;
                part scanPlatform : ScanPlatform;
                part iss : Instrument;
                part iris : Instrument;
                part uvs : Instrument;
                part pps : Instrument;
                part mag : Instrument;
                part pws : Instrument;
                part pls : Instrument;
                part lecp : Instrument;
                part crs : Instrument;
                part pra : Instrument;
                part record : GoldenRecord;
                part liftoff : MissionEvent;
                part jupiter : MissionEvent;
                part saturn : MissionEvent;
                part paleBlueDot : MissionEvent;
                part shock : MissionEvent;
                part heliopause : MissionEvent;
        
                attribute launchMassKg : Real = 815.0;
                attribute dryMassKg : Real = 721.9;
                attribute launchYear : Real = 1977.68;     // 1977-09-05
                attribute launchWatts : Real = 470.0;
                attribute watts2023 : Real = 225.0;
                attribute wattsLostPerYear : Real = 4.0;
                attribute distanceAU : Real = 172.52;      // October 2026
                attribute lightMinutesPerAU : Real = 8.317;
        
                // Fuel burned over the mission (launch minus dry mass)
                attribute propellantKg : Real = launchMassKg - dryMassKg;
                // Light travel time to Earth, hours, one way
                attribute lightHours : Real = distanceAU * lightMinutesPerAU / 60.0;
                attribute roundTripHours : Real = 2.0 * lightHours;
                // Output after 2023: straight line at the quoted loss
                attribute watts2026 : Real = watts2023 - wattsLostPerYear * 3.0;
        
                connect rtgs.powerOut to power.busIn;
                connect power.busOut to ccs.powerIn;
                connect power.busOut to fds.powerIn;
                connect power.busOut to aacs.powerIn;
                connect power.busOut to radio.powerIn;
                connect ccs.command to aacs.command;
                connect ccs.telemetry to fds.telemetry;
                connect fds.storage to dtr.record;
                connect fds.radio to radio.telemetry;
                connect radio.feed to hga.feed;
                connect aacs.thrust to thrusters.valve;
                connect aacs.thrust to tank.feedLine;
                connect aacs.scan to scanPlatform.drive;
                connect iss.data to fds.telemetry;
                connect iris.data to fds.telemetry;
                connect uvs.data to fds.telemetry;
                connect pps.data to fds.telemetry;
                connect mag.data to fds.telemetry;
                connect pws.data to fds.telemetry;
                connect pls.data to fds.telemetry;
                connect lecp.data to fds.telemetry;
                connect crs.data to fds.telemetry;
                connect pra.data to fds.telemetry;
            }
        
            // The spacecraft, with the dates NASA publishes for each shutdown.
            part voyager1 : Spacecraft {
                part :>> rtgs { @SafetyCritical; }
                part :>> power { @SafetyCritical; }
                part :>> liftoff { attribute :>> atYear = 1977.68; attribute :>> sunAU = 1.0; }          // Sep 5 1977
                part :>> jupiter { attribute :>> atYear = 1979.18; attribute :>> sunAU = 5.2; }         // closest approach Mar 5 1979
                part :>> saturn { attribute :>> atYear = 1980.87; attribute :>> sunAU = 9.5; }          // closest approach Nov 12 1980
                part :>> paleBlueDot { attribute :>> atYear = 1990.12; attribute :>> sunAU = 40.0; }    // Feb 14 1990, about six billion km
                part :>> shock { attribute :>> atYear = 2004.96; attribute :>> sunAU = 94.0; }          // estimated Dec 15 2004
                part :>> heliopause { attribute :>> atYear = 2012.65; attribute :>> sunAU = 121.0; }    // announced Aug 25 2012
                part :>> attitude1 { attribute :>> role = "attitude"; attribute :>> pointingFrom = 1977.68; attribute :>> pointingTo = 2002.0; }   // first attitude branch until the 2002 switch
                part :>> attitude2 { attribute :>> role = "attitude"; attribute :>> pointingFrom = 2002.0; attribute :>> pointingTo = 2018.0; }   // second attitude branch, 2002 to the 2018 switch
                part :>> tcm { attribute :>> role = "trajectory correction"; attribute :>> pointingFrom = 2018.0; attribute :>> pointingTo = 2024.65; }   // pointing 2018 to Aug 27 2024 (swap back)
                part :>> aacs { @SafetyCritical; }
                part :>> hga { @SafetyCritical; }
                part :>> radio { @SafetyCritical; }
                part :>> iss  { attribute :>> acronym = "ISS"; attribute :>> range = "two cameras, 8 filters each: wide-angle 200 mm f/3, narrow-angle 1500 mm f/8.5";  attribute :>> offYear = 1990.12; }   // Feb 14 1990
                part :>> iris { attribute :>> acronym = "IRIS"; attribute :>> range = "2.5-50 um and 0.3-2.0 um"; attribute :>> offYear = 1998.42; }   // Jun 3 1998
                part :>> uvs  { attribute :>> acronym = "UVS"; attribute :>> range = "40-180 nm";  attribute :>> offYear = 2016.30; }   // Apr 19 2016
                part :>> pps  { attribute :>> acronym = "PPS"; attribute :>> range = "0.2 m telescope, 8 wavelengths 235-750 nm";  attribute :>> offYear = 1980.08; }   // Jan 29 1980
                part :>> mag  { attribute :>> acronym = "MAG"; attribute :>> range = "triaxial fluxgate, 4 sensors (2 high-field, 2 low-field)";  @SafetyCritical; }
                part :>> pws  { attribute :>> acronym = "PWS"; attribute :>> range = "10 Hz to 56 kHz";  @SafetyCritical; }
                part :>> pls  { attribute :>> acronym = "PLS"; attribute :>> range = "low-energy ions and electrons";  attribute :>> offYear = 2007.08; }   // Feb 1 2007
                part :>> lecp { attribute :>> acronym = "LECP"; attribute :>> range = "low-energy charged particles; its 0.5 W motor stays on"; attribute :>> offYear = 2026.29; }   // Apr 17 2026
                part :>> crs  { attribute :>> acronym = "CRS"; attribute :>> range = "electrons 3-110 MeV, nuclei 1-500 MeV/nucleon";  attribute :>> offYear = 2025.15; }   // Feb 25 2025
                part :>> pra  { attribute :>> acronym = "PRA"; attribute :>> range = "20.4-1300 kHz and 2.3-40.5 MHz";  attribute :>> offYear = 2008.04; }   // Jan 15 2008
        
                // Declared here rather than at package level (the editor's validator reads
                // a package-level satisfy as a second declaration of the requirement).
                satisfy pointing by voyager1;
                satisfy science by voyager1;
                satisfy talking by voyager1;
            }
        
            // ---- Requirements -------------------------------------------------
        
            requirement def KeepScience {
                subject craft : Spacecraft;
                attribute minInstruments : Real;
                attribute running : Real;
                doc /* At least minInstruments science investigations keep returning data. */
                require constraint enough { running >= minInstruments }
            }
        
            requirement def KeepTalking {
                subject craft : Spacecraft;
                attribute minBps : Real;
                doc /* The downlink keeps at least minBps through the high-gain dish. */
                require constraint fast { craft.radio.downlinkBps >= minBps }
            }
        
            requirement def KeepPointing {
                subject craft : Spacecraft;
                doc /* Attitude control keeps the dish on Earth: it is a safety-critical unit. */
            }
        
            requirement <'R-01'> pointing : KeepPointing;
            requirement <'R-02'> science : KeepScience {
                attribute :>> minInstruments = 1.0;
                attribute :>> running = 2.0;      // MAG and PWS after April 2026
            }
            requirement <'R-03'> talking : KeepTalking {
                attribute :>> minBps = 40.0;
            }
        
            assert constraint scienceCheck { 2.0 >= 1.0 }
            assert constraint downlinkCheck { voyager1.radio.downlinkBps >= 40.0 }
            assert constraint massBalance { voyager1.propellantKg >= 90.0 & voyager1.propellantKg <= 100.0 }
        
            // How the pointing requirement is verified: the telemetry carries the attitude error.
            verification def AttitudeTelemetry {
                subject craft : Spacecraft;
                VerificationCases::PassIf(craft.radio.downlinkBps >= 40.0)
            }
            verification checkAttitude : AttitudeTelemetry {
                subject craft = voyager1;
                objective {
                    verify pointing;
                }
            }
        }
        

        Download voyager1.sysml ↓