def check_gom():
    try:
        gom = Gomspace()
        hk = gom.get_health_data(level="eps")
    except Exception as e:
        log_error(e)
        logger.error(
            f"GOM init failed. Is it charged above 7.0V? Check SDA/SCL (with an oscilloscope if need be)"
        )
    else:
        logger.info(
            f"GOM initialization successful. Battery voltage: {hk.vbatt}")
Example #2
0
    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]))
Example #3
0
from drivers.gom import Gomspace
import drivers.power.power_structs as ps
from time import sleep
from utils.log import get_log

logger = get_log()

gom = Gomspace()

while True:
    choice = int(
        input("Choose an option:\n"
              "0: Display Housekeeping Data"
              "1: Receiving Amplifier (LNA)\n"
              "2: Glowplug 1\n"
              "3: Glowplug 2\n"
              "4: Burnwire\n"
              "5: Solenoid\n"
              "6: Electrolyzer\n"
              "7: Transmitting Amplifier (PA)\n"
              "999: Turn OFF all controllable outputs\n"))
    if choice == 999:
        gom.all_off()
        ps.displayHk2(gom.get_health_data(level="eps"))

    if choice == 0:
        ps.displayHk2(gom.get_health_data(level='eps'))

    if choice in [1, 4, 6, 7]:
        duration = int(input("Duration (integer seconds):\n"))
        assert 0 < duration < 15
Example #4
0
from communications.satellite_radio import Radio
from drivers.gom import Gomspace
import utils.parameters as params
from time import sleep

radio = Radio()
gom = Gomspace()
electrolyzing = False

interval = 3  # Number of seconds between each transmission
repetitions = 5  # Number of total times you want to transmit the pattern

downlink = bytes(
    input("Enter signal you want to downlink (e.g '\\x08\\x07\\x00\\x00)':"),
    encoding='utf-8')
downlink = downlink.decode('unicode-escape').encode('ISO-8859-1')
#–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
# Enter Transmit Mode

#Stop electrolyzing
if gom.is_electrolyzing():
    electrolyzing = True
    gom.set_electrolysis(False)
    print('Electrolyzers turned off')

#Set RF receiving side to low
gom.rf_receiving_switch(receive=False)
print('RF Receiving set to low')

#Turn off LNA
gom.lna(False)
Example #5
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")
Example #6
0
    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)
Example #7
0
# from utils.constants import BURNWIRE_DURATION


def gyro_thread(gyro_freq: int):
    gyro_data = []
    logger.info("Reading Gyro data (rad/s)")
    for i in range(2000):
        gyro_reading = gyro.get_gyro()
        gyro_time = time()
        gyro_list = list(gyro_reading)
        gyro_list.append(gyro_time)
        gyro_data.append(gyro_list)
        sleep(1.0 / gyro_freq)

    # writes gyro data to gyro_data.txt. Caution, this file will be overwritten with every successive test
    logger.info("Writing gyro data to file")
    with open('gyro_data.txt', 'w') as filehandle:
        filehandle.writelines("%s\n" % line for line in gyro_data)


if __name__ == '__main__':
    logger = get_log()
    gyro = GyroSensor()
    gom_controller = Gomspace()

    # start new thread to log gyro data
    gyro_threader = threading.Thread(target=gyro_thread)
    gyro_threader.start()
    gom_controller.burnwire2(2)
Example #8
0
# Testing all untested and new Gom-related commands

from drivers.gom import Gomspace, logger
from drivers.power.power_structs import displayHK, displayHk2, displayStruct
from time import sleep

test = Gomspace()

# testing all HK functions
hkdata = test.get_health_data()
displayStruct(hkdata)
sleep(2)

hkdata = test.get_health_data(level="eps")
displayStruct(hkdata)
sleep(2)

hkdata = test.get_health_data(level="vi")
displayStruct(hkdata)
sleep(2)

hkdata = test.get_health_data(level="out")
displayStruct(hkdata)
sleep(2)

hkdata = test.get_health_data(level="wdt")
displayStruct(hkdata)
sleep(2)

hkdata = test.get_health_data(level="basic")
displayStruct(hkdata)
Example #9
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...")