Skip to content
Alex Omar edited this page Jan 4, 2017 · 18 revisions

Flight Computer

Single producer, multi-consumer model. Everything in parallel. Nice because no thread will move faster than the producer and no thread is slowed down by another thread because they are all independent of each other.

System Architecture

Producer

Responsible for polling flight instrumentation sensors, moving those values into memory locations shared between itself and the consumers (one memloc per consumer), and notifying each consumer that new data is available.

Pseudo code

sensor_data = get_data()

for c in consumers:
    if( c.shared_mem.is_avail() ):
        c.lock_shared_mem()
        c.update_shared_mem(sensor_data)
        c.unlock_shared_mem()
        c.notify()

State Machine

Producer State Machine

Notes

The notification mechanism is a binary semaphore signifying that data is "fresh" or "stale". The producer will overwrite fresh data if it is moving faster than the consumer.

Queued Consumer

Like an ordinary Consumer but this one also has a message queue it can read from. Has an internal thread-safe queue.

Psuedo code

while True:
    if( notified() ):
        if !msg_queue.is_empty():
            msg_queue.pop()
            logic()

            if !msg_queue.is_empty():
                self.notify()

        else:
            lock_shared_mem()
            local_data = shared_mem; //copy data
            unlock_shared_mem()

            logic()

State Machine

Queued Consumer

Consumer

Reads data from shared memory and then operates on it. Controls consumer crunches the meco algorithm. Logging consumer writes to a file, Comms consumer does communication stuff.

Pseudo code

while True:
    if( notified() ):
        lock_shared_mem()
        local_data = shared_mem; //copy data
        unlock_shared_mem()
        
        logic()
        if logic.is_important():
            radio_queue.enqueue(message);
            //or
            log_queue.enqueue(message);

State Machine

Consumer State Machine

Notes

If a consumer is slow enough, the producer will update the shared memory with fresh data multiple times before the consumer can read. This means dropped data, but it is also means that we will never run a consumer on stale data.

Inter-Thread Communication

Some data, like flight instrumentation, can get dropped and there's no problem, but some data, like "ignition", "MECO activation", and "fuel valve X actuated" must not be dropped.

Enter message queues! These are linked lists where any consumer can push data into the queue and it's respective consumer will read it. No message queue messages are dropped, ever. They take precedent over instrumentation always.

Queues are slower to write to, slower to read from, and consume memory every time another message is pushed. Because of this, only critical data should use these.

Clone this wiki locally