Expand description

Kubos Service for interacting with an Adcole Maryland Aerospace MAI-400

Configuration

The service can be configured in the /etc/kubos-config.toml with the following fields:

[mai400-service.addr]
ip = "127.0.0.1"
port = 8120

Where ip specifies the service’s IP address, and port specifies the port which UDP requests should be sent to.

Starting the Service

The service should be started automatically by its init script, but may also be started manually:

$ mai400-service
Kubos MAI-400 service started
Listening on: 10.63.1.20:8120

Queries

Ping

Test query to verify service is running without attempting to communicate with the underlying subsystem

{
    ping: "pong"
}

ACK

Get the last run mutation

{
    ack: AckCommand
}

Errors

Get all errors encountered since the last time this field was queried

{
    errors: [String]
}

Power Status

Get the current power state and uptime of the system

{
    power {
        state: PowerState,
        uptime: Int
    }
}

Configuration

Get the current configuration of the system

{
    config: "Not Implemented"
}

Telemetry

Get current telemetry information for the system

{
    telemetry{
        nominal{
            gpsTime: i32,
            timeSubsec: i32,
            cmdValidCntr: i32,
            cmdInvalidCntr: i32,
            cmdInvalidChksumCntr: i32,
            lastCommand: i32,
            acsMode: i32,
            css: [i32; 6],
            eclipseFlag: i32,
            sunVecB: [i32; 3],
            iBFieldMeas: [i32; 3],
            bd: [f64; 3],
            rwsSpeedCmd: [i32; 3],
            rwsSpeedTach: [i32; 3],
            rwaTorqueCmd: [f64; 3],
            gcRwaTorqueCmd: [i32; 3],
            torqueCoilCmd: [f64; 3],
            gcTorqueCoilCmd: [i32; 3],
            qboCmd: [i32; 4],
            qboHat: [i32; 4],
            angleToGo: f64,
            qError: [i32; 4],
            omegaB: [f64; 3],
            nb: [i32; 3],
            neci: [i32; 3],
        },
        debug{
            irehs{
                thermopilesA: [i32; 4],
                thermopilesB: [i32; 4],
                tempA: [i32; 4],
                tempB: [i32; 4],
                dipAngleA: i32,
                dipAngleB: i32,
                solutionDegraded: [Vec<String>; 8],
                thermopileStructA{
                    dipAngle: i32,
                    earthLimb: {
                        adc: i32,
                          temp: i32,
                          errors: bool,
                          flags: Vec<String>,
                       },
                    earthRef: {...},
                    spaceRef: {...},
                    wideFov: {...},
                thermopileStructB{...}
            },
            rawImu{
                accel: [i32; 3],
                gyro: [i32; 3],
                gyroTemp: i32,
            },
            rotating{
                bFieldIgrf: [f64; 3],
                sunVecEph: [f64; 3],
                scPosEci: [f64; 3],
                scVelEci: [f64; 3],
                keplerElem{
                    semiMajorAxis: f32,
                    eccentricity: f32,
                    inclination: f32,
                    raan: f32,
                    argParigee: f32,
                    trueAnomoly: f32,
                },
                kBdot: [f64; 3],
                kp: [f64; 3],
                kd: [f64; 3],
                kUnload: [f64; 3],
                cssBias: [i32; 6],
                magBias: [i32; 3],
                rwsVolt: i32,
                rwsPress: i32,
                attDetMode: i32,
                rwsResetCntr: [i32; 3],
                sunMagAligned: i32,
                minorVersion: i32,
                maiSn: i32,
                orbitPropMode: i32,
                acsOpMode: i32,
                procResetCntr: i32,
                majorVersion: i32,
                adsOpMode: i32,
                cssGain: [f64; 6],
                magGain: [f64; 3],
                orbitEpoch: i32,
                trueAnomolyEpoch: f64,
                orbitEpochNext: i32,
                scPosEciEpoch: [f64; 3],
                scVelEciEpoch: [f64; 3],
                qbXWheelSpeed: i32,
                qbXFilterGain: f64,
                qbXDipoleGain: f64,
                dipoleGain: [f64; 3],
                wheelSpeedBias: [i32; 3],
                cosSunMagAlignThresh: f64,
                unloadAngThresh: f64,
                qSat: f64,
                rwaTrqMax: f64,
                rwsMotorCurrent: [i32; 3],
                rwsMotorTemp: i32,
            }
        }
    }
}

Test Results

Get the test results of the last run test

Note: For this service, this actually just fetches the nominal and debug telemetry of the system, since there is no actual built-in test

{
    testResults{
        success,
        telemetryNominal{...},
        telemetryDebug{...}
    }
}

System Mode

Get the current mode of the system

{
    mode: Mode
}

System Orientation

Get the last reported orientation of the system

{
    orientation: "Not Implemented"
}

System Spin

Get the last reported spin values of the system Note: The spin values are automatically updated every six seconds

{
    spin{
        x: f64,
        y: f64,
        z: f64
    }
}

Mutations

Errors

Get all errors encountered while processing this GraphQL request

Note: This will only return errors thrown by fields which have already been processed, so it is recommended that this field be specified last.

mutation {
    errors: [String]
}

No-Op

Execute a trivial command against the system

mutation {
    noop {
        errors: String,
        success: Boolean
   }
}

Set Power State

Control the power state of the system

  • state: Power state the system should be changed to Note: The only valid input for this service is RESET
mutation {
    controlPower(state: PowerState) {
        errors: String,
        success: Boolean,
        power: PowerState
    }
}

Configuration

Configure the system

mutation {
    configureHardware: "Not Implemented"
}

System Self-Test

Run a system self-test

  • test: Type of self-test to perform
mutation {
    testHardware(test: TestType) {
        ... on IntegrationTestRsults {
            errors: String,
            success: Boolean,
            telemetryNominal{...},
            telemetryDebug{...}
        }
        ... on HardwareTestResults {
            errors: "Not Implemented",
            success: true,
            data: Empty
        }
   }
}

Passthrough

Pass a custom command through to the system

  • command: String containing the hex values to be sent (ex. “C3”). It will be converted to a byte array before transfer.
mutation {
    issueRawCommand(command: String) {
        errors: String,
        success: Boolean,
        response: String
    }
}

Set ADC Mode

Set the attitude control mode

  • mode: Control mode to change to
  • qbiCmd: Optional array of four values needed for Qinertial and Qtable mode
  • sunAngleEnable: Optional. Specifies whether the sun rotating angle should be updated when using Normal-Sun or LatLong-Sun mode sunRotAngle: Optional. The sun rotating angle for use in Normal-Sun and LatLong-Sun mode
mutation {
    setMode(mode: Mode, qbiCmd: Vec<i32>, sunAngleEnable: bool, sunRotAngle: f64) {
        errors: String,
        success: Boolean,
        response: String
    }
}

Set System Values

Update system values

  • gpsTime: Optional. If specified, updates the system’s ADACS clock
  • rv: Optional. If specified, updates the orbital position and velocity at epoch. The argument has the following sub-fields: - eciPos: Vector containing the new X, Y, and Z ECI position values - eciVel: Vector containing the new X, Y, and Z ECI velocity values - timeEpoch: GPS time at which the eciPos and eciVel values will go into effect
mutation {
    update(gps_time: Option<i32>,
        rv: Option<{eciPos: [f64; 3], eciVel: [f64; 3], timeEpoch: i32}>) {
        errors: String,
        success: Boolean,
    }
}

Modules

model 🔒
objects 🔒
schema 🔒

Structs

Response fields for ‘configureHardware’ mutation

Response fields for ‘controlPower’ mutation

Common response fields structure for requests which don’t return any specific data

Response fields for ‘power’ query

Response fields for ‘testHardware(test: HARDWARE)’ mutation

IR Earth horizon sensor telemetry values

Response fields for ‘testHardware(test: INTEGRATION)’ mutation

Kepler element telemetry values

RV input fields for update mutation

Raw IMU telemetry values

Rotating telemetry values. These values aren’t updated with each returned telemetry packet. Instead, sections are updated each iteration. The full rotation is updated every six seconds.

Response fields for spin query

Response fields for ‘telemetry(telem: NOMINAL)’ query

Response fields for telemetry query

Response fields for ‘telemetry(telem: DEBUG)’ query

Thermopile sensor telemetry values

Thermopile telemetry values

Enums

Return field for ‘ack’ query

System mode

Input field for ‘controlPower’ mutation and response field for ‘power’ query

Enum for the ‘testHardware’ mutation response union

Input field for ‘testHardware’ mutation

Functions

main 🔒