Beispiel #1
0
    def __init__(self):
        super().__init__()
        logger.info("Initializing...")
        self.init_parameters()
        self.command_queue = Queue()
        self.downlink_queue = Queue()
        self.FMQueue = Queue()
        self.commands_to_execute = []
        self.downlinks_to_execute = []
        self.telemetry = Telemetry(self)
        self.burn_queue = Queue()
        self.reorientation_queue = Queue()
        self.reorientation_list = []
        self.maneuver_queue = Queue()  # maneuver queue
        # self.init_comms()
        self.command_handler = CommandHandler()
        self.downlink_handler = DownlinkHandler()
        self.command_counter = 0
        self.downlink_counter = 0
        self.command_definitions = CommandDefinitions(self)
        self.init_sensors()
        self.last_opnav_run = datetime.now()  # Figure out what to set to for first opnav run
        self.log_dir = LOG_DIR
        self.logger = get_log()
        self.attach_sigint_handler()  # FIXME

        if os.path.isdir(self.log_dir):
            self.flight_mode = RestartMode(self)
        else:
            os.makedirs(CISLUNAR_BASE_DIR)
            os.mkdir(LOG_DIR)
            self.flight_mode = BootUpMode(self)
        self.create_session = create_sensor_tables_from_path(DB_FILE)
def test_config2_command():
    config2 = ps.eps_config2_t()
    config2.batt_maxvoltage = 8300
    config2.batt_normalvoltage = 7600
    config2.batt_safevoltage = 7200
    config2.batt_criticalvoltage = 6800

    config2_dict = dict_from_eps_config2(config2)

    COUNTER = 0

    ch = CommandHandler()

    command_bytes = ch.pack_command(COUNTER, FMEnum.Normal.value,
                                    NormalCommandEnum.GomConf2Set.value,
                                    **config2_dict)
    mac, counter, mode, command_id, kwargs = ch.unpack_command(command_bytes)

    assert mac == MAC
    assert counter == COUNTER
    assert mode == FMEnum.Normal.value
    assert command_id == NormalCommandEnum.GomConf2Set.value

    unpacked_config2 = eps_config2_from_dict(kwargs)

    assert config2._fields_ == unpacked_config2._fields_
    # ps.displayConfig2(config2)
    # ps.displayConfig2(unpacked_config2)

    assert config2.batt_maxvoltage == unpacked_config2.batt_maxvoltage
    assert config2.batt_normalvoltage == unpacked_config2.batt_normalvoltage
    assert config2.batt_safevoltage == unpacked_config2.batt_safevoltage
    assert config2.batt_criticalvoltage == unpacked_config2.batt_criticalvoltage
    def __init__(self):
        super().__init__()
        logger.info("Initializing...")
        self.init_parameters()
        self.command_queue = Queue()
        self.downlink_queue = Queue()
        self.FMQueue = Queue()
        self.commands_to_execute = []
        self.downlinks_to_execute = []
        self.burn_queue = Queue()
        self.reorientation_queue = Queue()
        self.reorientation_list = []
        self.maneuver_queue = Queue()  # maneuver queue
        self.opnav_queue = Queue()  # determine state of opnav success
        # self.init_comms()
        logger.info("Initializing commands and downlinks")
        self.command_handler = CommandHandler()
        self.downlink_handler = DownlinkHandler()
        self.command_counter = 0
        self.downlink_counter = 0
        self.command_definitions = CommandDefinitions(self)
        self.last_opnav_run = datetime.now()  # Figure out what to set to for first opnav run
        self.log_dir = LOG_DIR
        self.logger = get_log()
        self.attach_sigint_handler()  # FIXME
        self.file_block_bank = {}
        self.need_to_reboot = False
        self.gom: Gomspace
        self.gyro: GyroSensor
        self.adc: ADC
        self.rtc: RTC
        self.radio: Radio
        self.mux: camera.CameraMux
        self.camera: camera.Camera
        self.nemo_manager: NemoManager
        self.init_sensors()

        # Opnav subprocess variables
        self.opnav_proc_queue = Queue()
        self.opnav_process = Process()  # define the subprocess

        if os.path.isdir(self.log_dir):
            logger.info("We are in Restart Mode")
            self.flight_mode = RestartMode(self)
        else:
            logger.info("We are in Bootup Mode")
            os.makedirs(CISLUNAR_BASE_DIR, exist_ok=True)
            os.mkdir(LOG_DIR)
            self.flight_mode = BootUpMode(self)
        self.create_session = create_sensor_tables_from_path(DB_FILE)
        logger.info("Initializing Telemetry")
        self.telemetry = Telemetry(self)
        logger.info("Done intializing")
Beispiel #4
0
    def __init__(self):
        super().__init__()
        logger.info("Initializing...")
        self.init_parameters()
        self.command_queue = Queue()
        self.downlink_queue = Queue()
        self.FMQueue = Queue()
        self.commands_to_execute = []
        self.downlinks_to_execute = []
        self.telemetry = Telemetry(self)
        self.burn_queue = Queue()
        self.reorientation_queue = Queue()
        self.reorientation_list = []
        self.maneuver_queue = Queue()  # maneuver queue
        self.opnav_queue = Queue()   # determine state of opnav success
        # self.init_comms()
        self.command_handler = CommandHandler()
        self.downlink_handler = DownlinkHandler()
        self.command_counter = 0
        self.downlink_counter = 0
        self.command_definitions = CommandDefinitions(self)
        self.last_opnav_run = datetime.now()  # Figure out what to set to for first opnav run
        self.log_dir = LOG_DIR
        self.logger = get_log()
        self.attach_sigint_handler()  # FIXME
        self.need_to_reboot = False

        self.gom = None
        self.gyro = None
        self.adc = None
        self.rtc = None
        self.radio = None
        self.mux = None
        self.camera = None
        self.init_sensors()

        # Telemetry
        self.tlm = Telemetry(self)

        # Opnav subprocess variables
        self.opnav_proc_queue = Queue()
        self.opnav_process = Process()  # define the subprocess

        if os.path.isdir(self.log_dir):
            self.flight_mode = RestartMode(self)
        else:
            os.makedirs(CISLUNAR_BASE_DIR, exist_ok=True)
            os.mkdir(LOG_DIR)
            self.flight_mode = BootUpMode(self)
        self.create_session = create_sensor_tables_from_path(DB_FILE)
    def test_command_serialization(self):
        # Both are doubles
        arg1 = "arg1"
        arg2 = "arg2"
        ch = CommandHandler()
        print(f"Packers: {ch.packers}")
        command_args = [arg1, arg2]
        command_data_tuple = (command_args, 16)
        application_id = 78
        command_dict = {application_id: command_data_tuple}
        mode_id = 255

        kwargs = {
            arg1: 78.1,
            arg2: 99.5,
        }
        command_counter = 1
        ch.register_new_command(mode_id, application_id, **kwargs)
        command_buffer = ch.pack_command(command_counter, mode_id, application_id, **kwargs)

        assert len(command_buffer) == ch.get_command_size(mode_id, application_id)

        unpacked_mac, unpacked_counter, unpacked_mode, unpacked_app, unpacked_args = ch.unpack_command(command_buffer)

        print(unpacked_args)
        assert unpacked_mode == mode_id
        assert unpacked_app == application_id
        assert unpacked_args[arg1] == kwargs[arg1]
        assert unpacked_args[arg2] == kwargs[arg2]
        assert unpacked_counter == command_counter
        assert unpacked_mac == MAC
    def test_register_new_codec(self):
        arg = "testarg"
        ch = CommandHandler()
        ch.register_new_codec(arg, pack_double, unpack_double)
        assert arg in ch.unpackers and arg in ch.packers

        with raises(SerializationException):
            ch.register_new_codec(arg, pack_double, unpack_double)
Beispiel #7
0
import communications.groundstation as gs
from communications.commands import CommandHandler
import board
import busio
import time
from adafruit_bus_device.spi_device import SPIDevice
from communications.ax5043_manager.ax5043_driver import Ax5043
from communications.ax5043_manager.ax5043_manager import Manager

#Radio setup
driver = Ax5043(SPIDevice(busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)))
mgr = Manager(driver)
ch = CommandHandler()

#Pack command into a bytearray
gs.registerCommand(ch,1,2,number1=7, number2=4)
command = ch.pack_command(1,2,number1=7, number2=4)

#Send the command to the satellite
gs.transmitCommand(mgr, command)

print('Transmitted')
print('Entering Receiving Mode')

cycleNumber = 1

#Enter listening mode
while True:

    print('Cycle: ' + str(cycleNumber))
def test_config_command():
    config = ps.eps_config_t()
    config.ppt_mode = randint(1, 2)
    config.battheater_mode = randint(0, 1)
    config.battheater_low = randint(0, 5)
    config.battheater_high = randint(6, 20)
    config.output_normal_value[0] = randint(0, 1)
    config.output_normal_value[1] = randint(0, 1)
    config.output_normal_value[2] = randint(0, 1)
    config.output_normal_value[3] = randint(0, 1)
    config.output_normal_value[4] = randint(0, 1)
    config.output_normal_value[5] = randint(0, 1)
    config.output_normal_value[6] = randint(0, 1)
    config.output_normal_value[7] = randint(0, 1)

    config.output_safe_value[0] = randint(0, 1)
    config.output_safe_value[1] = randint(0, 1)
    config.output_safe_value[2] = randint(0, 1)
    config.output_safe_value[3] = randint(0, 1)
    config.output_safe_value[4] = randint(0, 1)
    config.output_safe_value[5] = randint(0, 1)
    config.output_safe_value[6] = randint(0, 1)
    config.output_safe_value[7] = randint(0, 1)

    initial_on = randint(0, 65535)
    config.output_initial_on_delay[0] = initial_on
    config.output_initial_on_delay[1] = initial_on
    config.output_initial_on_delay[2] = initial_on
    config.output_initial_on_delay[3] = initial_on
    config.output_initial_on_delay[4] = initial_on
    config.output_initial_on_delay[5] = initial_on
    config.output_initial_on_delay[6] = initial_on
    config.output_initial_on_delay[7] = initial_on

    initial_off = randint(0, 65535)
    config.output_initial_off_delay[0] = initial_off
    config.output_initial_off_delay[1] = initial_off
    config.output_initial_off_delay[2] = initial_off
    config.output_initial_off_delay[3] = initial_off
    config.output_initial_off_delay[4] = initial_off
    config.output_initial_off_delay[5] = initial_off
    config.output_initial_off_delay[6] = initial_off
    config.output_initial_off_delay[7] = initial_off

    config.vboost[0] = randint(1000, 4000)
    config.vboost[1] = randint(1000, 4000)
    config.vboost[2] = randint(1000, 4000)

    config_dict = dict_from_eps_config(config)

    COUNTER = 0

    ch = CommandHandler()

    command_bytes = ch.pack_command(COUNTER, FMEnum.Normal.value,
                                    NormalCommandEnum.GomConf1Set.value,
                                    **config_dict)
    mac, counter, mode, command_id, kwargs = ch.unpack_command(command_bytes)

    assert mac == MAC
    assert counter == COUNTER
    assert mode == FMEnum.Normal.value
    assert command_id == NormalCommandEnum.GomConf1Set.value

    unpacked_config = eps_config_from_dict(**kwargs)

    # ps.displayConfig(config)
    # ps.displayConfig(unpacked_config)
    assert config.ppt_mode == unpacked_config.ppt_mode
    assert config.battheater_mode == unpacked_config.battheater_mode
    assert config.battheater_low == unpacked_config.battheater_low
    assert config.battheater_high == unpacked_config.battheater_high

    assert config.output_normal_value[
        0] == unpacked_config.output_normal_value[0]
    assert config.output_normal_value[
        1] == unpacked_config.output_normal_value[1]
    assert config.output_normal_value[
        2] == unpacked_config.output_normal_value[2]
    assert config.output_normal_value[
        3] == unpacked_config.output_normal_value[3]
    assert config.output_normal_value[
        4] == unpacked_config.output_normal_value[4]
    assert config.output_normal_value[
        5] == unpacked_config.output_normal_value[5]
    assert config.output_normal_value[
        6] == unpacked_config.output_normal_value[6]
    assert config.output_normal_value[
        7] == unpacked_config.output_normal_value[7]

    assert config.output_safe_value[0] == unpacked_config.output_safe_value[0]
    assert config.output_safe_value[1] == unpacked_config.output_safe_value[1]
    assert config.output_safe_value[2] == unpacked_config.output_safe_value[2]
    assert config.output_safe_value[3] == unpacked_config.output_safe_value[3]
    assert config.output_safe_value[4] == unpacked_config.output_safe_value[4]
    assert config.output_safe_value[5] == unpacked_config.output_safe_value[5]
    assert config.output_safe_value[6] == unpacked_config.output_safe_value[6]
    assert config.output_safe_value[7] == unpacked_config.output_safe_value[7]

    assert config.output_initial_on_delay[
        0] == unpacked_config.output_initial_on_delay[0]
    assert config.output_initial_off_delay[
        0] == unpacked_config.output_initial_off_delay[0]

    assert config.vboost[0] == unpacked_config.vboost[0]
    assert config.vboost[1] == unpacked_config.vboost[1]
    assert config.vboost[2] == unpacked_config.vboost[2]
Beispiel #9
0
from communications.satellite_radio import Radio
from communications.commands import CommandHandler
from communications.downlink import DownlinkHandler
import time

# Setup
ch = CommandHandler()
dh = DownlinkHandler()
groundstation = Radio()

# Send command to get gyro/mag/acc data
gmaCommand = ch.pack_command(1, 8, 7)
groundstation.transmit(gmaCommand)
print('GMA Command Transmitted')

# Listen for response
print('Receiving...')
cycle = 1

while True:
    print('Receiving Cycle: ' + str(cycle))

    downlink = groundstation.receiveSignal()

    if downlink is not None:
        print('Downlink Received:')
        data = dh.unpack_downlink(downlink)[-1]
        print('Gyro: ' + str(data['gyro1']) + ', ' + str(data['gyro2']) +
              ', ' + str(data['gyro3']))
        break
Beispiel #10
0
class MainSatelliteThread(Thread):
    def __init__(self):
        super().__init__()
        logger.info("Initializing...")
        self.init_parameters()
        self.command_queue = Queue()
        self.downlink_queue = Queue()
        self.FMQueue = Queue()
        self.commands_to_execute = []
        self.downlinks_to_execute = []
        self.telemetry = Telemetry(self)
        self.burn_queue = Queue()
        self.reorientation_queue = Queue()
        self.reorientation_list = []
        self.maneuver_queue = Queue()  # maneuver queue
        self.opnav_queue = Queue()   # determine state of opnav success
        # self.init_comms()
        self.command_handler = CommandHandler()
        self.downlink_handler = DownlinkHandler()
        self.command_counter = 0
        self.downlink_counter = 0
        self.command_definitions = CommandDefinitions(self)
        self.last_opnav_run = datetime.now()  # Figure out what to set to for first opnav run
        self.log_dir = LOG_DIR
        self.logger = get_log()
        self.attach_sigint_handler()  # FIXME
        self.need_to_reboot = False

        self.gom = None
        self.gyro = None
        self.adc = None
        self.rtc = None
        self.radio = None
        self.mux = None
        self.camera = None
        self.init_sensors()

        # Telemetry
        self.tlm = Telemetry(self)

        # Opnav subprocess variables
        self.opnav_proc_queue = Queue()
        self.opnav_process = Process()  # define the subprocess

        if os.path.isdir(self.log_dir):
            self.flight_mode = RestartMode(self)
        else:
            os.makedirs(CISLUNAR_BASE_DIR, exist_ok=True)
            os.mkdir(LOG_DIR)
            self.flight_mode = BootUpMode(self)
        self.create_session = create_sensor_tables_from_path(DB_FILE)

    def init_comms(self):
        self.comms = CommunicationsSystem(
            queue=self.command_queue, use_ax5043=False
        )
        self.comms.listen()

    def init_parameters(self):
        with open(PARAMETERS_JSON_PATH) as f:
            json_parameter_dict = load(f)

        try:
            for parameter in utils.parameters.__dir__():
                if parameter[0] != '_':
                    utils.parameters.__setattr__(parameter, json_parameter_dict[parameter])
        except:
            raise Exception(
                'Attempted to set parameter ' + str(parameter) +
                ', which could not be found in parameters.json'
            )

    def init_sensors(self):
        try:
            self.gom = Gomspace()
        except:
            self.gom = None
            logger.error("GOM initialization failed")
        else:
            logger.info("Gom initialized")

        try:
            self.gyro = GyroSensor()
        except:
            self.gyro = None
            logger.error("GYRO initialization failed")
        else:
            logger.info("Gyro initialized")

        try:
            self.adc = ADC(self.gyro)
            self.adc.read_temperature()
        except:
            self.adc = None
            logger.error("ADC initialization failed")
        else:
            logger.info("ADC initialized")

        try:
            self.rtc = RTC()
        except:
            self.rtc = None
            logger.error("RTC initialization failed")
        else:
            logger.info("RTC initialized")

        try:
            self.nemo_manager = NemoManager(data_dir=NEMO_DIR, reset_gpio_ch=16)
        except:
            self.nemo_manager = None
            logger.error("NEMO initialization failed")
        else:
            logger.info("NEMO initialized")

        try:
            self.radio = Radio()
        except:
            self.radio = None
            logger.error("RADIO initialization failed")
        else:
            logger.info("Radio initialized")

        # initialize the Mux, select a camera
        try:
            self.mux = camera.CameraMux()
            self.mux.selectCamera(1)
        except:
            self.mux = None
            logger.error("MUX initialization failed")
        else:
            logger.info("Mux initialized")

        cameras_list = [0, 0, 0]

        # initialize cameras only if not a hard boot (or first boot)
        if not hard_boot() and os.path.isdir(self.log_dir):
            try:
                self.camera = camera.Camera()
                for i in [1, 2, 3]:
                    try:
                        self.mux.selectCamera(i)
                        f, t = self.camera.rawObservation(f"initialization-{i}-{int(time())}")
                    except Exception as e:
                        logger.error(f"CAM{i} initialization failed")
                        cameras_list[i - 1] = 0
                    else:
                        logger.info(f"Cam{i} initialized")
                        cameras_list[i - 1] = 1

                if 0 in cameras_list:
                    raise e
            except:
                self.camera = None
                logger.error(f"Cameras initialization failed")
            else:
                logger.info("Cameras initialized")
        else:
            self.need_to_reboot = True

        # make a bitmask of the initialized sensors for downlinking
        sensors = [self.gom, self.radio, self.gyro, self.adc, self.rtc, self.mux, self.camera]
        sensor_functioning_list = [int(bool(sensor)) for sensor in sensors]
        sensor_functioning_list.extend(cameras_list)
        sensor_bitmask = ''.join(map(str, sensor_functioning_list))
        logger.debug(f"Sensors: {sensor_bitmask}")
        return int(sensor_bitmask, 2)

    def handle_sigint(self, signal, frame):
        self.shutdown()
        sys.exit(0)

    def attach_sigint_handler(self):
        signal.signal(signal.SIGINT, self.handle_sigint)

    def poll_inputs(self):

        self.flight_mode.poll_inputs()

        #Telemetry downlink
        if (datetime.today() - self.radio.last_telemetry_time).total_seconds()/60 >= params.TELEM_DOWNLINK_TIME:
            telemetry = self.command_definitions.gather_basic_telem()
            telem_downlink = (
                self.downlink_handler.pack_downlink(self.downlink_counter, FMEnum.Normal.value,
                                                    NormalCommandEnum.BasicTelem.value, **telemetry))
            self.downlink_queue.put(telem_downlink)
            self.radio.last_telemetry_time = datetime.today()

        # Listening for new commands
        newCommand = self.radio.receiveSignal()
        if newCommand is not None:
            try:
                unpackedCommand = self.command_handler.unpack_command(newCommand)

                if unpackedCommand[0] == MAC:
                    if unpackedCommand[1] == self.command_counter + 1:
                        self.command_queue.put(bytes(newCommand))
                        self.command_counter += 1
                    else:
                        logger.warning('Command with Invalid Counter Received. Counter: ' + str(unpackedCommand[1]))
                else:
                    logger.warning('Unauthenticated Command Received')
            except:
                logger.error('Invalid Command Received')
        else:
            logger.debug('Not Received')

    def replace_flight_mode_by_id(self, new_flight_mode_id):
        self.replace_flight_mode(build_flight_mode(self, new_flight_mode_id))

    def replace_flight_mode(self, new_flight_mode):
        self.flight_mode = new_flight_mode
        self.logger.info(f"Changed to FM#{self.flight_mode.flight_mode_id}")

    def update_state(self):
        fm_to_update_to = self.flight_mode.update_state()

        # only replace the current flight mode if it needs to change (i.e. dont fix it if it aint broken!)
        if fm_to_update_to is None:
            pass
        elif fm_to_update_to != NO_FM_CHANGE and fm_to_update_to != self.flight_mode.flight_mode_id:
            self.replace_flight_mode_by_id(fm_to_update_to)

    def clear_command_queue(self):
        while not self.command_queue.empty():
            command = self.command_queue.get()
            logger.debug(f"Throwing away command: {command}")

    def reset_commands_to_execute(self):
        self.commands_to_execute = []

    # Execute received commands
    def execute_commands(self):
        assert (
                len(self.commands_to_execute) == 0
        ), "Didn't finish executing previous commands"
        while not self.command_queue.empty():
            self.commands_to_execute.append(self.command_queue.get())
        self.flight_mode.execute_commands()

    def read_command_queue_from_file(self, filename="communications/command_queue.txt"):
        """A temporary workaround to not having radio board access"""
        # check if file exists
        if os.path.isfile(filename):
            text_file = open(filename, "r")
            for hex_line in text_file:
                self.command_queue.put(bytes.fromhex(hex_line))

            text_file.close()
            # delete file
            os.remove(filename)

    # Run the current flight mode
    def run_mode(self):
        with self.flight_mode:
            self.flight_mode.run_mode()

    # Wrap in try finally block to ensure it stays live
    def run(self):
        """This is the main loop of the Cislunar Explorers and runs constantly during flight."""
        try:
            while True:
                sleep(5)  # TODO remove when flight modes execute real tasks
                self.poll_inputs()
                self.update_state()
                self.read_command_queue_from_file()
                self.execute_commands()  # Set goal or execute command immediately
                self.run_mode()

                # Opnav subprocess management
                # TODO: This all needs to be moved to the OpNav Flight mode, and should not be in main!!!


        finally:
            # TODO handle failure gracefully
            if FOR_FLIGHT is True:
                self.replace_flight_mode_by_id(FMEnum.Safety.value)
                self.run()
            else:
                self.shutdown()

    def shutdown(self):
        if self.gom is not None:
            self.gom.all_off()
        if self.nemo_manager is not None:
            self.nemo_manager.close()
        logger.critical("Shutting down flight software")
Beispiel #11
0
from communications.satellite_radio import Radio
from communications.commands import CommandHandler
from flight_modes.flight_mode_factory import FLIGHT_MODE_DICT
import time

ch = CommandHandler()
groundstation = Radio()
commandCounter = 1
transmitInterval = 3

while True:
    commandInput = input('Enter command in the form "Mode ID,Command ID, Keyword Arguments" (e.g 2,3,delay=3,state=True):')

    commandArguments = commandInput.split(',')
    mode_id = int(commandArguments[0])
    command_id = int(commandArguments[1])
    kwargs = {}

    if len(commandArguments) > 2:
        argsList = commandArguments[2:]
        for i in range(len(argsList)):
            
            signIndex = argsList[i].index('=')
            argName = argsList[i][:signIndex]
            argValue = argsList[i][signIndex +1:]

            arg_type = FLIGHT_MODE_DICT[mode_id].command_arg_types[argName]
            if arg_type == 'int' or arg_type == 'short':
                argValue = int(argValue)
            elif arg_type == 'float' or arg_type == 'double':
                argValue = float(argValue)
Beispiel #12
0
from communications.satellite_radio import Radio
from communications.commands import CommandHandler
from communications.downlink import DownlinkHandler
from flight_modes.flight_mode_factory import FLIGHT_MODE_DICT
import time
from utils.log import get_log

logger = get_log()

ch = CommandHandler()
dh = DownlinkHandler()
groundstation = Radio()
commandCounter = 1
transmitInterval = 3
rx_wait_time = 20  # seconds

while True:
    commandInput = input(
        'Enter command in the form "Mode ID,Command ID, Keyword Arguments" (e.g 2,3,delay=3,state=True):'
    )

    commandArguments = commandInput.split(',')
    mode_id = int(commandArguments[0])
    command_id = int(commandArguments[1])
    kwargs = {}

    if len(commandArguments) > 2:
        argsList = commandArguments[2:]
        for i in range(len(argsList)):

            signIndex = argsList[i].index('=')
    def test_packers_unpackers_match(self):
        ch = CommandHandler()

        assert set(ch.packers.keys()) == set(ch.unpackers.keys())
Beispiel #14
0
"""command_queue_writer.py: a temporary workaround to not having functioning radio drivers. Instead of sending
commands to the EDU/HITL through the radio board, use this to write commands to a txt file, which is then read by
main.py's read_command_queue_from_file method """

from communications.commands import CommandHandler
from utils.log import get_log

logger = get_log()

ch = CommandHandler()

fm_num = int(0)
filename = "command_queue.txt"
command_counter = 1

while fm_num > -1:
    fm_num = int(input("What flight mode would you like to command in?\n"))
    if fm_num > -1:
        command_num = int(input("What command ID would you like to send?\n"))
        if command_num > -1:
            kwarg_str = input(
                "Please input any arguments as a valid python dictionary:\n")
            kwarg_dict = eval(kwarg_str)
            packed = ch.pack_command(command_counter, fm_num, command_num,
                                     **kwarg_dict)
            file = open(filename, "a")
            file.write(str(packed.hex()) + "\n")
            file.close()
            logger.info(f"Wrote hex bytes {str(packed.hex())}")
Beispiel #15
0
class MainSatelliteThread(Thread):
    def __init__(self):
        super().__init__()
        logger.info("Initializing...")
        self.init_parameters()
        self.command_queue = Queue()
        self.downlink_queue = Queue()
        self.FMQueue = Queue()
        self.commands_to_execute = []
        self.downlinks_to_execute = []
        self.telemetry = Telemetry(self)
        self.burn_queue = Queue()
        self.reorientation_queue = Queue()
        self.reorientation_list = []
        self.maneuver_queue = Queue()  # maneuver queue
        # self.init_comms()
        self.command_handler = CommandHandler()
        self.downlink_handler = DownlinkHandler()
        self.command_counter = 0
        self.downlink_counter = 0
        self.command_definitions = CommandDefinitions(self)
        self.init_sensors()
        self.last_opnav_run = datetime.now()  # Figure out what to set to for first opnav run
        self.log_dir = LOG_DIR
        self.logger = get_log()
        self.attach_sigint_handler()  # FIXME

        if os.path.isdir(self.log_dir):
            self.flight_mode = RestartMode(self)
        else:
            os.makedirs(CISLUNAR_BASE_DIR)
            os.mkdir(LOG_DIR)
            self.flight_mode = BootUpMode(self)
        self.create_session = create_sensor_tables_from_path(DB_FILE)

    def init_comms(self):
        self.comms = CommunicationsSystem(
            queue=self.command_queue, use_ax5043=False
        )
        self.comms.listen()

    def init_parameters(self):
        with open(PARAMETERS_JSON_PATH) as f:
            json_parameter_dict = load(f)
        self.parameters = json_parameter_dict

        # try:
        #     for parameter in self.parameters.__dir__():
        #         if parameter[0] != '_':
        #             self.parameters[parameter] = json_parameter_dict[parameter]
        # except:
        #     raise Exception(
        #         'Attempted to set parameter ' + str(parameter) +
        #         ', which could not be found in parameters.json'
        #     )

    def init_sensors(self):
        self.radio = Radio()
        self.gom = Gomspace(self.parameters)
        self.gyro = GyroSensor()
        self.adc = ADC(self.gyro)
        self.rtc = RTC()
        # self.pressure_sensor = PressureSensor() # pass through self so need_to_burn boolean function
        # in pressure_sensor (to be made) can access burn queue"""

        # initialize the cameras, select a camera
        logger.info("Creating camera mux...")
        self.mux = camera.CameraMux()
        self.camera = camera.Camera()
        logger.info("Selecting a camera...")
        # select camera before reboot so that we will detect cam on reboot
        self.mux.selectCamera(random.choice([1, 2, 3]))

    def handle_sigint(self, signal, frame):
        self.shutdown()
        sys.exit(0)

    def attach_sigint_handler(self):
        signal.signal(signal.SIGINT, self.handle_sigint)

    def poll_inputs(self):
        # self.tlm.poll()
        self.flight_mode.poll_inputs()

        # Telemetry downlink
        if (datetime.today() - self.radio.last_telemetry_time).total_seconds() / 60 >= self.parameters[
            "TELEM_DOWNLINK_TIME"]:
            self.enter_transmit_safe_mode()
            telemetry = self.command_definitions.gather_basic_telem()
            telem_downlink = (
                self.downlink_handler.pack_downlink(self.downlink_counter, FMEnum.Normal.value,
                                                    NormalCommandEnum.BasicTelem.value, **telemetry))
            self.downlink_queue.put(telem_downlink)

        # Listening for new commands
        newCommand = self.radio.receiveSignal()
        if newCommand is not None:
            try:
                unpackedCommand = self.command_handler.unpack_command(newCommand)

                if unpackedCommand[0] == MAC:
                    if unpackedCommand[1] == self.command_counter + 1:
                        print('hello')
                        self.command_queue.put(bytes(newCommand))
                        self.command_counter += 1
                    else:
                        print('Command with Invalid Counter Received. '
                        + 'Counter: ' + str(unpackedCommand[1]))
                else:
                    print('Unauthenticated Command Received')

            except:
                print('Invalid Command Received')
        else:
            print('Not Received')

    def enter_transmit_safe_mode(self):
        # TODO: Make sure that everything else is turned off before transmitting
        pass

    def replace_flight_mode_by_id(self, new_flight_mode_id):
        self.replace_flight_mode(build_flight_mode(self, new_flight_mode_id))

    def replace_flight_mode(self, new_flight_mode):
        self.flight_mode = new_flight_mode
        self.logger.info(f"Changed to FM#{self.flight_mode.flight_mode_id}")

    def update_state(self):
        fm_to_update_to = self.flight_mode.update_state()

        # only replace the current flight mode if it needs to change (i.e. dont fix it if it aint broken!)
        if fm_to_update_to is None:
            pass
        elif fm_to_update_to != NO_FM_CHANGE and fm_to_update_to != self.flight_mode.flight_mode_id:
            self.replace_flight_mode_by_id(fm_to_update_to)

    def clear_command_queue(self):
        while not self.command_queue.empty():
            command = self.command_queue.get()
            print(f"Throwing away command: {command}")

    def reset_commands_to_execute(self):
        self.commands_to_execute = []

    # Execute received commands
    def execute_commands(self):
        assert (
                len(self.commands_to_execute) == 0
        ), "Didn't finish executing previous commands"
        while not self.command_queue.empty():
            self.commands_to_execute.append(self.command_queue.get())
        self.flight_mode.execute_commands()

    def execute_downlinks(self):
        self.enter_transmit_safe_mode()
        while not self.downlink_queue.empty():
            self.radio.transmit(self.downlink_queue.get())
            self.downlink_counter += 1
            sleep(self.parameters["DOWNLINK_BUFFER_TIME"])

    def read_command_queue_from_file(self, filename="communications/command_queue.txt"):
        """A temporary workaround to not having radio board access"""
        # check if file exists
        if os.path.isfile(filename):
            text_file = open(filename, "r")
            for hex_line in text_file:
                self.command_queue.put(bytes.fromhex(hex_line))

            text_file.close()
            # delete file
            os.remove(filename)

    # Run the current flight mode
    def run_mode(self):
        with self.flight_mode:
            self.flight_mode.run_mode()

    # Wrap in try finally block to ensure it stays live
    def run(self):
        """This is the main loop of the Cislunar Explorers and runs constantly during flight."""
        try:
            while True:
                sleep(5)  # TODO remove when flight modes execute real tasks
                self.poll_inputs()
                self.update_state()
                self.read_command_queue_from_file()
                self.execute_commands()  # Set goal or execute command immediately
                self.execute_downlinks()
                self.run_mode()
        finally:
            self.replace_flight_mode_by_id(FMEnum.Safety.value)
            # TODO handle failure gracefully
            if FOR_FLIGHT is True:
                self.run()
            else:
                self.gom.all_off()

    def shutdown(self):
        self.gom.all_off()
        logger.critical("Shutting down...")