Initial commit

This commit is contained in:
Brett Williams
2022-03-27 14:56:35 -07:00
commit 6e6a5e946e
200 changed files with 1133 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/Source Audio/
/venv/
/src/video/

View File

@@ -0,0 +1,464 @@
// Mercury Control Panel Controller
// Brett Williams
// March 2017
#include <SerialCommand.h>
#include <Servo.h>
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
//Servo globe_servo;
//Define Pins
const int globeServo = 0;
const int globeMotor = 3;
const int ploadPin = 13;
const int switchLatchPin = 11;
const int ledLatchPin = 9;
const int clockPin = 12;
const int dataPin = 10;
//Shift Register Buffer
byte leds[3];
byte switches[3];
//Servo Data
Adafruit_PWMServoDriver servos = Adafruit_PWMServoDriver(0x65);
#define SERVOMIN 202 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 700 // this is the 'maximum' pulse length count (out of 4096)
int servo_pwm[16];
bool move_globe;
typedef struct {
bool ledState;
long onTime;
unsigned long startMillis;
} LED;
#define LED_COUNT 24
#define DEFAULT_LED_TIME 8000
LED led_list[LED_COUNT];
SerialCommand SCmd;
void setup()
{
pinMode(ploadPin, OUTPUT);
pinMode(switchLatchPin, OUTPUT);
pinMode(ledLatchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
digitalWrite(clockPin, LOW);
digitalWrite(ploadPin, HIGH);
all_leds_off();
servos.begin();
servos.setPWMFreq(60); // Analog servos run at ~60 Hz updates
serial_setup();
move_globe = false;
}
void loop()
{
// byte switchBuffer[3];
// readSwitches(switchBuffer);
update_leds();
advance_globe();
SCmd.readSerial();
delay(20);
}
/* ==== SERIAL METHODS ==== */
void serial_setup()
{
Serial.begin(9600);
SCmd.addDefaultHandler(unrecognized);
//LED Commands
SCmd.addCommand("led", process_led_command);
SCmd.addCommand("led_red", led_red);
SCmd.addCommand("led_all_on", cycle_all_leds);
SCmd.addCommand("led_all_off", all_leds_off);
SCmd.addCommand("led_cycle", cycle_all_leds);
//Servo Commands
SCmd.addCommand("servo_zero", zero_all_servos);
SCmd.addCommand("servo_min", zero_all_servos);
SCmd.addCommand("servo_center", center_all_servos);
SCmd.addCommand("servo_max", max_all_servos);
SCmd.addCommand("servo", process_servo_command);
//Globe Commands
SCmd.addCommand("globe", globe);
Serial.println(F("Mercury Control Ready"));
}
void unrecognized()
{
Serial.println(F("Unrecognized Command"));
}
void process_led_command()
{
int ledPin;
String ledStatusText;
bool ledStatus;
char *arg;
arg = SCmd.next();
if (arg != NULL)
{
ledPin = atoi(arg); // Converts a char string to an integer
}
else {
Serial.println("Error: No pin number");
return;
}
arg = SCmd.next();
if (arg != NULL)
{
ledStatusText = String(arg);
ledStatus = ledStatusText.equals("on");
}
else {
Serial.println("Error: No pin status");
return;
}
Serial.print(F("Turning LED #"));
Serial.print(ledPin);
if (ledStatus){
Serial.println(" on");
}else{
Serial.println(" off");
}
set_led_state(ledPin, ledStatus, DEFAULT_LED_TIME);
}
void process_servo_command()
{
int servo_num;
int percent;
int duration = 0;
char *arg;
arg = SCmd.next();
if (arg != NULL)
{
servo_num=atoi(arg); // Converts a char string to an integer
}
else {
Serial.println(F("Error: No servo number"));
return;
}
if (servo_num == globeServo){
Serial.println(F("Error: Cannot move globe"));
return;
}
arg = SCmd.next();
if (arg != NULL)
{
percent=atol(arg);
}
else {
Serial.println(F("Error: No servo move percent"));
return;
}
arg = SCmd.next();
if (arg != NULL)
{
duration=atol(arg);
}
Serial.print(F("Moving servo #"));
Serial.print(servo_num);
Serial.print(" to ");
Serial.print(percent);
Serial.println("%");
if (duration > 0){
move_servo_to_percent_timed(servo_num, percent, duration);
}
else{
move_servo_to_percent(servo_num, percent);
}
}
/* ==== SWITCH METHODS ==== */
void readSwitches(byte switchBuffer[])
{
pinMode(dataPin, INPUT);
//Collect Data
digitalWrite(switchLatchPin, HIGH);
digitalWrite(ploadPin, LOW);
delayMicroseconds(20);
digitalWrite(ploadPin, HIGH);
digitalWrite(switchLatchPin, LOW);
//Shift data in
switchBuffer[0] = shiftIn(dataPin, clockPin, MSBFIRST);
switchBuffer[1] = shiftIn(dataPin, clockPin, MSBFIRST);
switchBuffer[2] = shiftIn(dataPin, clockPin, MSBFIRST);
//Look for any changes
for (int x = 0; x < 3; x++) {
for (int i = 0; i < 8; i++)
{
if (bitRead(switchBuffer[x], i) != bitRead(switches[x], i)) {
int pin_number = (x * 8) + i;
//set_pin_status(pin_number, 1);
Serial.print("Pin - ");
Serial.print(pin_number);
if (bitRead(switchBuffer[x], i) > 0)
Serial.print("HIGH");
else
Serial.print("LOW");
Serial.print("\r\n");
}
}
switches[x] = switchBuffer[x];
}
}
/* ==== LED METHODS ==== */
void update_leds() {
for (int pin = 0; pin < LED_COUNT; pin++) {
if (led_list[pin].ledState == true) {
long timeDiff = millis() - led_list[pin].startMillis;
if (timeDiff > led_list[pin].onTime) {
led_list[pin].ledState = false;
led_list[pin].startMillis = 0;
set_pin_status(pin, false);
Serial.print("turning off led #");
Serial.println(pin);
}
}
}
}
void set_led_state(byte pin, bool onState, long duration) {
if (onState == led_list[pin].ledState) {
return;
} else if ((onState == true) && (duration > 0)) {
Serial.print("Turning on LED #");
Serial.print(pin);
Serial.print(" for ");
Serial.print(duration / 1000);
Serial.println(" seconds");
led_list[pin].startMillis = millis();
led_list[pin].onTime = duration;
Serial.println(duration);
set_pin_status(pin, true);
} else {
Serial.print("Turning off LED #");
Serial.println(pin);
led_list[pin].startMillis = 0;
set_pin_status(pin, false);
}
led_list[pin].ledState = onState;
}
void cycle_all_leds()
{
for (int x = 0; x < 3; x++)
{
for (int i = 0; i < 8; i++)
{
Serial.print("LED #");
int led_num = (x * 8) + i;
Serial.println(led_num);
bitSet(leds[x], i);
updateShiftRegister();
delay(2000);
bitClear(leds[x], i);
updateShiftRegister();
delay(20);
}
}
Serial.println("Ready");
}
void all_leds_off()
{
leds[0] = 0;
leds[1] = 0;
leds[2] = 0;
updateShiftRegister();
}
void led_red(){
set_led_state(2, true, DEFAULT_LED_TIME);
set_led_state(7, true, DEFAULT_LED_TIME);
set_led_state(8, true, DEFAULT_LED_TIME);
set_led_state(11, true, DEFAULT_LED_TIME);
set_led_state(13, true, DEFAULT_LED_TIME);
set_led_state(15, true, DEFAULT_LED_TIME);
set_led_state(16, true, DEFAULT_LED_TIME);
set_led_state(19, true, DEFAULT_LED_TIME);
set_led_state(21, true, DEFAULT_LED_TIME);
set_led_state(23, true, DEFAULT_LED_TIME);
}
void set_pin_status(int pinNumber, bool pinStatus) {
byte idx = 0;
while (pinNumber >= 8) {
pinNumber -= 8;
idx++;
}
if (pinStatus == true) {
//Serial.println("LED ON");
bitSet(leds[idx], pinNumber);
} else {
//Serial.println("LED OFF");
bitClear(leds[idx], pinNumber);
}
updateShiftRegister();
}
void updateShiftRegister()
{
pinMode(dataPin, OUTPUT);
digitalWrite(ledLatchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, leds[2]);
shiftOut(dataPin, clockPin, MSBFIRST, leds[1]);
shiftOut(dataPin, clockPin, MSBFIRST, leds[0]);
digitalWrite(ledLatchPin, HIGH);
}
/* ==== SERVO METHODS ==== */
void zero_all_servos() {
Serial.println("Setting all servos to zero");
for (int x = 1; x < 16; x++) {
servos.setPWM(x, 0, SERVOMAX);
servo_pwm[x] = SERVOMAX;
delay(200);
}
Serial.println("Ready");
}
void center_all_servos() {
Serial.println("Setting all servos to center");
for (int x = 1; x < 16; x++) {
move_servo_to_percent(x, 50);
delay(200);
}
Serial.println("Ready");
}
void max_all_servos() {
Serial.println("Setting all servos to maximum");
for (int x = 1; x < 16; x++) {
servos.setPWM(x, 0, SERVOMIN);
servo_pwm[x] = SERVOMIN;
delay(200);
}
Serial.println("Ready");
}
void move_servo_to_degree(byte servo_num, int degrees) {
int pulselength = map(degrees, 0, 180, SERVOMAX, SERVOMIN);
servos.setPWM(servo_num, 0, pulselength);
servo_pwm[servo_num] = pulselength;
}
void move_servo_to_percent(byte servo_num, int percentage) {
int pulselength = map(percentage, 0, 100, SERVOMAX, SERVOMIN);
servos.setPWM(servo_num, 0, pulselength);
servo_pwm[servo_num] = pulselength;
}
void move_servo_to_percent_timed(byte servo_num, int percentage, int duration){
int new_pulselength = map(percentage, 0, 100, SERVOMAX, SERVOMIN);
int old_pulselength = servo_pwm[servo_num];
int duration_millis = (duration * 1000) / 40; //200
int millis_interval = (new_pulselength - old_pulselength) / duration_millis;
Serial.println(new_pulselength);
Serial.println(old_pulselength);
for (int i=0; i <= duration_millis; i++){
int pulselength = old_pulselength + (i * millis_interval);
servos.setPWM(servo_num, 0, pulselength);
delay(40);
}
servos.setPWM(servo_num, 0, new_pulselength);
servo_pwm[servo_num] = new_pulselength;
Serial.println("Ready");
}
/* ==== SERVO METHODS ==== */
void globe(){
if (move_globe == true){
move_globe = false;
analogWrite(globeMotor, 0);
move_servo_to_percent(0, 50);
Serial.println("Globe movement off");
}else{
move_globe = true;
analogWrite(globeMotor, 50);
Serial.println("Globe movement on");
}
}
void advance_globe() {
// Orbital period 88.5 minutes - 5310 seconds
// 6283 time slices
// Updates every 845 milliseconds
if (move_globe == false){
return;
}
const int orbital_period = 5310;
const int inclination = 90;
const float sine_increment = 0.001;
const float two_pi = 6.283;
const float time_delta = (orbital_period / (two_pi / sine_increment)) * 1000;
static float x = 0;
static unsigned long last_update = 0;
unsigned long current_millis = millis();
// Update if time delta has passed or never updated
if ((current_millis - last_update) >= time_delta || last_update == 0) {
float val = sin(x) * inclination + inclination;
move_servo_to_degree(globeServo, int(val));
//HIGH_servo.write(int(val));
x += sine_increment;
// Rollover angle
if (x >= two_pi) {
x = 0;
}
last_update = current_millis;
}
}

16
src/MercuryController.py Normal file
View File

@@ -0,0 +1,16 @@
import serial
class MercuryController:
def __init__(self, port, baud):
self.serial = serial.Serial(port, baud)
self.serial.flushInput()
def led_on(self, pin):
self.serial.write("LED {} on".format(pin))
def led_off(self, pin):
self.serial.write("LED {} off".format(pin))
def set_servo_percent(self, servo, percent):
self.serial.write("servo {0} {1}".format(servo, percent))

491
src/SimController.py Normal file
View File

@@ -0,0 +1,491 @@
#! /usr/bin/env python
import datetime
import math
import sys
import os
import time
import subprocess
import random
import csv
import serial
import json
# import keyboard
import logging
from numpy import interp
from threading import Thread
from distutils.spawn import find_executable
from MercuryController import *
class MercurySim:
def __init__(self):
self.config = json.loads(open('config.json').read())
# Mission Time
self.running = False
self.launch_time = None
self.mission_time = None
self.running_thread = None
# Scenes
self.current_scene = 0
self.scenes = list(csv.DictReader(open('scenes.csv')))
# Mission Events
self.mission_events = list(csv.DictReader(open('events_launch.csv')))
self.retrograde_time = t_time_to_seconds([x for x in self.mission_events if x['name'] == "retrofire"][0]['time'])
self.event_history = []
# Window
# self.window = WindowDisplay()
# Displays
self.time_display = TimeDisplay()
self.time_display.set_retrograde_time(self.retrograde_time)
# Audio Devices
self.sfx_audio = AudioController("sfx", output=0, volume='100%')
self.capcom_audio = AudioController("capcom", output=1, volume='40%')
# LEDs
self.leds = {}
for x in csv.DictReader(open('led_mapping.csv')):
if x['name']:
self.leds[x['name']] = x['number']
# Servos
self.servos = {}
for x in csv.DictReader(open('servo_mapping.csv')):
if x['name']:
self.servos[x['name']] = x
# Draw default stars
subprocess.Popen('fbi -a stars.jpg -d /dev/fb0 -T 1 --noverbose', shell=True)
try:
self.controller = MercuryController(None, 9600)
except Exception as e:
logging.error("Unable to connect to Mercury Arduino: {}".format(e))
self.controller = None
def teardown(self):
logging.info('')
logging.info('{:-^40}'.format(' Teardown '))
AudioController.stop_all_audio()
subprocess.Popen(['sudo', 'killall', 'omxplayer.bin']) # stop video
# -- Mission Clock
def update_time(self):
time = time_from(self.launch_time)
updated_time = self.mission_time != time
self.mission_time = time
return updated_time
# -- Servos
def set_servo_value(self, val, servo):
x = interp(val,[float(servo['minval']),float(servo['maxval'])],[float(servo['minpercent']),float(servo['maxpercent'])])
logging.debug("Set servo {} value to {}".format(servo['name'], x))
if self.controller:
self.controller.set_servo_percent(servo['number'], x)
# -- Audio
def play_timed_audio(self):
# Play timed capcom files
if self.mission_time < 1:
timed_capcom = "capcom_{}.wav".format(abs(self.mission_time))
else:
timed_capcom = "capcom_p{}.wav".format(abs(self.mission_time))
if timed_capcom in self.capcom_audio.files:
self.capcom_audio.play_file(timed_capcom)
def update_time_display(self):
# Update time display
time_to_retrograde = max(self.retrograde_time - max(self.mission_time, 0), 0)
self.time_display.set_time_to_retrograde(time_to_retrograde)
self.time_display.set_time_from_launch(max(self.mission_time, 0))
def trigger_event(self, event_name, allow_failure=False):
# Don't trigger event if already done
if event_name in self.event_history:
logging.error("{} already triggered".format(event_name))
return
# Trigger videos first
if 'video' in event_name:
video_file = [x for x in os.listdir('video') if event_name.split('-')[-1] in x]
if video_file:
logging.info("Playing video file: {}".format(video_file))
play_video(video_file[0])
good_led = self.leds.get(event_name, None) or self.leds.get(event_name + "_green", None)
succeed = True if not allow_failure else not (random.randint(1, 10) == 5 and bool(good_led))
if succeed:
logging.info("Mission Event: " + event_name)
sfx_file = self.sfx_audio.file_with_name(event_name)
capcom_file = self.capcom_audio.file_with_name(event_name)
if sfx_file:
self.sfx_audio.play_file(sfx_file)
if capcom_file:
self.capcom_audio.play_file(capcom_file)
if good_led and self.controller:
self.controller.led_on(good_led)
self.event_history.append(event_name)
else:
logging.info("Mission Event (Failure): " + event_name)
bad_led = self.leds.get(event_name + "_red", None)
if bad_led and self.controller:
self.controller.led_on(bad_led)
def key_press(self, event):
key = event.name
if key in ['a', 'b', 'c', 'd']:
logging.info('Pressed {} key'.format(key))
self.running = False
if self.running_thread:
logging.info('-------Stopping thread-------')
self.running_thread.join()
if key == 'a': # start sim
self.running_thread = Thread(target=self.run_simulation)
else: # start scene
idx = ord(key) - 98 # convert char to int (i.e. b into 0, c into 1, etc)
self.running_thread = Thread(target=self.run_scene, args=(idx,))
self.running_thread.daemon = True
self.running_thread.start()
# elif key is not None:
# logging.error('Unknown key!')
def run_scene(self, scene_number):
logging.info('')
logging.info('{:-^40}'.format(' Starting Scene #{} '.format(scene_number)))
scene = self.scenes[scene_number]
play_video(scene['video'], loop=True, random_orientation=True)
# self.sfx_audio.play_file(scene['audio'], loop=True)
# Play ambient audio
self.sfx_audio.play_file("sfx_cabin_loop.wav", loop=True)
next_misc_capcom = 0
self.running = True
while self.running:
if not next_misc_capcom:
capcom_timings = self.config['capcom'][scene['mission_phase']]
next_misc_capcom = random.randint(capcom_timings['min'], capcom_timings['max'])
logging.info('next capcom in {}s'.format(t_time(next_misc_capcom)))
time.sleep(1)
next_misc_capcom -= 1
if not next_misc_capcom:
self.capcom_audio.play_random_file(scene['mission_phase'])
self.teardown()
def get_acceleration(self):
# Find Mission Events
old_events = [x for x in self.mission_events if t_time_to_seconds(x.get("time")) < self.mission_time and x.get('acceleration')]
next_events = [x for x in self.mission_events if t_time_to_seconds(x.get("time")) >= self.mission_time and x.get('acceleration')]
if old_events and next_events:
last_event = old_events[-1]
next_event = next_events[0]
if last_event['acceleration'] == next_event['acceleration']:
return float(next_event['acceleration'])
else:
x = interpolated_value(start_time=t_time_to_seconds(last_event["time"]), start_val=last_event['acceleration'],
end_time=t_time_to_seconds(next_event['time']), end_val=next_event['acceleration'],
current_time=self.mission_time, rate=2)
return x
elif old_events:
return float(old_events[-1].get('acceleration'))
elif next_events:
return float(next_events[0].get('acceleration'))
else:
logging.error('Get acceleration - Cannot find any events!')
def run_simulation(self):
logging.info('')
logging.info('{:-^40}'.format(' Starting Sim '))
# Setup launch time
self.launch_time = datetime.datetime.now() + datetime.timedelta(seconds=(self.config['prelaunch_time'] + 1))
orbit_time = [x for x in self.mission_events if 'orbit_phase' in x['name']][0]['time']
# Clear history
del self.event_history[:]
self.capcom_audio.clear_history()
self.sfx_audio.clear_history()
# Play video
play_video('launch.mp4', loop=False)
# Play ambient audio
self.sfx_audio.play_file("sfx_cabin_loop.wav", loop=True)
self.running = True
next_misc_capcom = None
while self.running:
# Don't kill CPU
time.sleep(0.1)
# Look for button updates
# self.controller.has_updates()
# Trigger automatic functions
if self.update_time():
# Mission Time
current_t_time = t_time(self.mission_time)
acceleration = self.get_acceleration()
logging.info("{} - Accel: {:.1f}g".format(current_t_time, acceleration))
self.play_timed_audio()
self.update_time_display()
# Update Servos
self.set_servo_value(acceleration, self.servos['acceleration'])
# logging.info("Acceleration - {}".format(self.get_acceleration()))
# Trigger mission events
now_events = [x for x in self.mission_events if x.get("time") == current_t_time]
for event in now_events:
self.trigger_event(event['name'], allow_failure=self.config['allow_failures'])
if self.mission_time < 0:
mission_phase = 'prelaunch'
elif self.mission_time < t_time_to_seconds(orbit_time):
mission_phase = 'launch'
else:
mission_phase = 'orbit'
# Play Capcom Random
if next_misc_capcom == self.mission_time:
self.capcom_audio.play_random_file(mission_phase)
next_misc_capcom = None
# Setup next random capcom
if not next_misc_capcom:
capcom_timings = self.config['capcom'][mission_phase]
next_misc_capcom = random.randint(capcom_timings['min'], capcom_timings['max']) + self.mission_time
while True:
next_ttime = t_time(next_misc_capcom)
next_ttime_plus = t_time(next_misc_capcom + 1) # 1s padding
collision = any(next_ttime in x['time'] or next_ttime_plus in x['time'] for x in self.mission_events)
timed_format = 'capcom_{}'.format(abs(next_misc_capcom)) if next_misc_capcom < 0 else 'capcom_p{}'.format(abs(next_misc_capcom))
collision = collision or any(timed_format in x for x in self.capcom_audio.files)
if collision:
# logging.info('possible capcom collision. adding 2')
# logging.info('was: {}'.format(next_misc_capcom))
next_misc_capcom += 2
# logging.info('now: {}'.format(next_misc_capcom))
else:
break
logging.info('Next misc capcom at {}'.format(next_misc_capcom))
self.teardown()
class AudioController:
def __init__(self, type, output, volume):
self.player = find_executable('afplay') or find_executable('aplay')
self.type = type
self.play_history = []
self.files = [f for f in os.listdir('audio') if self.type in f]
self.output = str(output)
# Set volume to 100% on Pi
if "aplay" in self.player:
subprocess.call(['amixer', '-c', self.output, 'set', 'PCM', '--', volume])
logging.info('Setting volume on output {0} to {1}'.format(self.output, volume))
def play_random_file(self, prefix):
prefix = '_' + prefix + '_misc'
misc_audio = [f for f in self.files if prefix in f]
unplayed_audio = [m for m in misc_audio if m not in self.play_history]
if not unplayed_audio:
logging.info('Used all available audio. Resetting history')
self.clear_history()
unplayed_audio = misc_audio
while True:
misc_file = random.choice(unplayed_audio)
if misc_file not in self.play_history:
break
self.play_file(misc_file)
def file_with_name(self, name):
found_file = None
files = [f for f in self.files if os.path.splitext(f)[0].endswith(name)]
if files:
found_file = files[0]
return found_file
def play_file(self, filename, loop=False):
logging.info("Playing {0} audio file: {1}".format(self.type, filename))
dir_path = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(dir_path, "audio", filename)
if self.output and "aplay" in self.player:
if loop:
# only omxplayer can loop
command = ['omxplayer', '--no-keys', '--no-osd', '--loop', filepath]
else:
# aplay for everything else
command = [self.player, '-D', 'default:{}'.format(self.output), '-c', '1', filepath]
else:
# macOS
command = [self.player, filepath]
subprocess.Popen(command)
self.play_history.append(filename)
def clear_history(self):
del self.play_history[:]
@classmethod
def stop_all_audio(cls):
logging.info("Stopping all audio")
player = find_executable('afplay') or find_executable('aplay')
subprocess.call(["killall", os.path.basename(player)])
class TimeDisplay:
def __init__(self):
try:
self.arduino = serial.Serial('COM1', 115200, timeout=.1)
except Exception as e:
logging.error("Cannot connect to TimeDisplay: {}".format(e))
def set_time_from_launch(self, time):
if hasattr(self, "arduino"):
self.arduino.write("time_from {}".format(time))
def set_time_to_retrograde(self, time):
if hasattr(self, "arduino"):
self.arduino.write("time_to {}".format(time))
def set_retrograde_time(self, time):
if hasattr(self, "arduino"):
self.arduino.write("retrograde {}".format(time))
def play_video(filename, loop=False, random_orientation=False, random_start=False):
player = find_executable('omxplayer')
if player:
logging.info("Playing video file: {}".format(filename))
filepath = os.path.join("video", filename)
commands = ['sudo', player, '--no-keys', '--no-osd', filepath, '--layer', '10']
# else:
# commands = ['sudo', player, '--no-keys', '--no-osd', filepath, '--layer', '10']
if loop:
commands.append('--loop')
if random_start:
commands.append('-p')
commands.append(random.randint(0, 60))
if random_orientation:
commands.append('--orientation')
commands.append(random.choice(['0', '180']))
p = subprocess.Popen(commands, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
time.sleep(0.2) # wait for video to start to not conflict with audio
else:
logging.error('No video player found')
# -- Functions --
def t_time_to_seconds(t_time_val):
raw_time = t_time_val[2:].split(":")
seconds = time_to_seconds(raw_time[0], raw_time[1], raw_time[2])
if t_time_val[:2] == "T-":
seconds = -seconds
return seconds
def time_to_seconds(hours=0, minutes=0, seconds=0):
# Define the constants
SECONDS_PER_MINUTE = 60
SECONDS_PER_HOUR = 3600
total_seconds = int(hours) * SECONDS_PER_HOUR
total_seconds = total_seconds + (int(minutes) * SECONDS_PER_MINUTE)
total_seconds = total_seconds + int(seconds)
return total_seconds
def time_from(from_time):
now = datetime.datetime.now()
return int((now - from_time).total_seconds())
def formatted_time(time_val):
time_val = abs(time_val)
hour = time_val // 3600
time_val %= 3600
minutes = time_val // 60
time_val %= 60
seconds = time_val
return "%02d:%02d:%02d" % (hour, minutes, seconds)
def t_time(time):
prefix = "T-" if time < 0 else "T+"
t_time = prefix + formatted_time(time)
return t_time
def interpolated_value(start_time, start_val, end_time, end_val, current_time, rate):
multiplier = math.pow(current_time-start_time, rate) / math.pow(end_time-start_time, rate)
current_val = (float(end_val)-float(start_val)) * multiplier + float(start_val)
return current_val
if __name__ == '__main__':
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO)
# set cwd
os.chdir(os.path.dirname(os.path.abspath(__file__)))
try:
sim = MercurySim()
# keyboard.on_press(sim.key_press)
sim.run_simulation()
logging.info('Ready')
# play_video('launch.mp4')
while True:
time.sleep(0.1)
except KeyboardInterrupt:
logging.info("User Interrupt")
subprocess.Popen(['sudo', 'killall', 'fbi'])
sim.running = False
sim.teardown()
sys.exit(0)

BIN
src/audio/capcom_1.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_10-old.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_11.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_15.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_2.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_3.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_30.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_35.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_4.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_40.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_5.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_6.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_60.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_7.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_8.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_9.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
src/audio/capcom_go_1.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_go_2.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_go_3.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_go_4.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/audio/capcom_mark.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_max_q.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
src/audio/capcom_orbits.wav Normal file

Binary file not shown.

BIN
src/audio/capcom_p40.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More