All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.simulator.leospacecraft.LEOSpacecraftSimulator Maven / Gradle / Ivy

package org.yamcs.simulator.leospacecraft;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.simulator.CCSDSPacket;
import org.yamcs.simulator.SimulationConfiguration;
import org.yamcs.simulator.SimulationData;
import org.yamcs.simulator.Simulator;
import org.yamcs.simulator.launchland.AckHandler;

/**
 * Discrete 1Hz time-stepped simulation of a generic LEO spacecraft.
 */
public class LEOSpacecraftSimulator extends Simulator {
    
    private static final Logger log = LoggerFactory.getLogger(LEOSpacecraftSimulator.class);
    private static final int OFF = 0;
    private static final int ON = 1;
    
    final private DataFeeder packetFeeder;
    private LEOSpacecraftModel model = new LEOSpacecraftModel();
    private long t = 0;
    
    private AckHandler ackDataHandler = new AckHandler();
    private boolean engageHoldOneCycle = false;
    private boolean unengageHoldOneCycle = false;
    private int waitToEngage;
    private int waitToUnengage;
    private boolean engaged = false;
    private boolean unengaged = true;
    private boolean exeTransmitted = true;
    private int battOneCommand;
    private int battTwoCommand;
    
    public LEOSpacecraftSimulator(SimulationConfiguration simConfig) {
        super(simConfig);
        packetFeeder = new DataFeeder(simConfig, true);
    }
    
    @Override
    public void run() {
        super.run();
        try {
            SimulationData data;
            while ((data = packetFeeder.readNext()) != null) {
                model.step(t++, data);
                
                // Hmm :-/
                if (waitToEngage == 2 || engaged) {
                    applyModifications(model); // 2
                    
                    CCSDSPacket packet = model.toCCSDSPacket();
                    transmitTM(packet);
                    
                    engageHoldOneCycle = false;
                    waitToEngage = 0;
                } else if (waitToUnengage == 2 || unengaged) {
                    CCSDSPacket packet = model.toCCSDSPacket();
                    transmitTM(packet);
                    
                    unengaged = true;
                    unengageHoldOneCycle = false;
                    waitToUnengage = 0;
                }
                
                // hold the command for 1 cycle after the command Ack received
                if (engageHoldOneCycle) {
                    waitToEngage += 1;
                }

                if (unengageHoldOneCycle) {
                    waitToUnengage += 1;
                }
                
                executePendingCommands(); // 1
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * Hmm, this feels like it could be done better
     */
    private void applyModifications(LEOSpacecraftModel model) {
        engaged = true;
        //unengaged = false;

        CCSDSPacket exeCompPacket = new CCSDSPacket(3, 2, 8);
        switch (battOneCommand) {
        case 1:
            model.forceBatteryOneOff(true);
            ackDataHandler.fillExeCompPacket(exeCompPacket, 1, OFF);
            if (!exeTransmitted) {
                transmitTM(exeCompPacket);
                exeTransmitted = true;
            }
            break;

        case 2:
            model.forceBatteryOneOff(false);
            ackDataHandler.fillExeCompPacket(exeCompPacket, 1, ON);
            if (!exeTransmitted) {
                transmitTM(exeCompPacket);
                exeTransmitted = true;
            }
            break;
        }
        
        switch (battTwoCommand) {
        case 1:
            model.forceBatteryTwoOff(true);
            ackDataHandler.fillExeCompPacket(exeCompPacket, 2, OFF);
            if (!exeTransmitted) {
                transmitTM(exeCompPacket);
                exeTransmitted = true;
            }
            break;

        case 2:
            model.forceBatteryTwoOff(false);
            ackDataHandler.fillExeCompPacket(exeCompPacket, 2, ON);
            if (!exeTransmitted) {
                transmitTM(exeCompPacket);
                exeTransmitted = true;
            }
            break;
        }
    }
    
    private void executePendingCommands() {
        while(pendingCommands.size()>0) {
            CCSDSPacket commandPacket = pendingCommands.poll();
            if (commandPacket.getPacketType() == 10) {
                log.debug("BATT COMMAND: " + commandPacket.getPacketId()+" batNum: "+commandPacket.getUserDataBuffer().get(0));

                switch(commandPacket.getPacketId()) {
                case 1:
                    switchBatteryOn(commandPacket);
                    break;
                case 2:
                    switchBatteryOff(commandPacket);
                    break;
                }
            }
        }
    }
    
    private void switchBatteryOn(CCSDSPacket commandPacket) {
        commandPacket.setPacketId(1);
        int batNum = commandPacket.getUserDataBuffer().get(0);
        CCSDSPacket ackPacket;
        switch(batNum) {
        case 1:
            unengageHoldOneCycle = true;
            //engaged = false;
            exeTransmitted = false;
            battOneCommand = 2;
            ackPacket = new CCSDSPacket(1, 2, 7);
            ackDataHandler.fillAckPacket(ackPacket, 1);
            transmitTM(ackPacket);
            break;
        case 2:
            unengageHoldOneCycle = true;
            //engaged = false;
            exeTransmitted = false;
            battTwoCommand = 2;
            ackPacket = new CCSDSPacket(1, 2, 7);
            ackDataHandler.fillAckPacket(ackPacket, 1);
            transmitTM(ackPacket);
            break;
        }
    }
    
    private void switchBatteryOff(CCSDSPacket commandPacket) {
        commandPacket.setPacketId(2);
        int batNum = commandPacket.getUserDataBuffer().get(0);
        CCSDSPacket ackPacket;
        switch(batNum) {
        case 1:
            engageHoldOneCycle = true;
            exeTransmitted = false;
            battOneCommand = 1;
            ackPacket = new CCSDSPacket(1, 2, 7);
            ackDataHandler.fillAckPacket(ackPacket, 1);
            transmitTM(ackPacket);
            break;
        case 2:
            engageHoldOneCycle = true;
            exeTransmitted = false;
            battTwoCommand = 1;
            ackPacket = new CCSDSPacket(1, 2, 7);
            ackDataHandler.fillAckPacket(ackPacket, 1);
            transmitTM(ackPacket);
            break;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy