Recreate Launch-8 Roll In av3-fc

Take data from Launch-8 and run it through our current flight computer to look for qualitativly similar results.

Import Data


In [1]:
import numpy as np

# launch 8 roll CAN data
columns = np.loadtxt('../data/Launch-8/roll/raw/output_trim.csv', delimiter=',', unpack=True, usecols=(0,1,2,3))
roll_sample_rate = 1000
roll_time  = columns[0]
roll_accel = columns[1]
roll_rate  = columns[2]
roll_fin   = columns[3]

# zero time
roll_time = roll_time - 4540.7
roll_time_orig = roll_time

# roll rate in deg/sec
roll_rate = roll_rate - roll_rate[0:10].mean()
roll_rate = roll_rate / 42.9

# acceleromter in m/s/s
roll_accel -= roll_accel[0:10].mean()
roll_accel *= -0.0068

# fin angle in degrees
roll_fin -= roll_fin[0:10].mean()
roll_fin /= (roll_fin.max()/15.0)

# launch 8 Opal IMU data
columns = np.loadtxt('../data/Launch-8/opal/Opal_launch_rotated.csv', delimiter=',', unpack=True)
opal_sample_rate = 128.0
opal_time = columns[0]
opal_accel_x = columns[1]
opal_accel_y = columns[2]
opal_rate_x = columns[4]*57.2957795
opal_rate_y = columns[5]*57.2957795
opal_mag_x = columns[7]
opal_mag_y = columns[8]
opal_mag_z = columns[9]

In [2]:
# Resample both to ADIS time
from scipy.signal import resample

adis_sample_rate = 819.2

n = int((len(opal_time) / opal_sample_rate) * adis_sample_rate)

opal_time = resample(opal_time, n)
opal_accel_x = resample(opal_accel_x, n)
opal_accel_y = resample(opal_accel_y, n)
opal_rate_x = resample(opal_rate_x, n)
opal_rate_y = resample(opal_rate_y, n)
opal_mag_x = resample(opal_mag_x, n)
opal_mag_y = resample(opal_mag_y, n)
opal_mag_z = resample(opal_mag_z, n)


n = int((len(roll_time) / roll_sample_rate) * adis_sample_rate)
roll_time  = resample(roll_time, n)
roll_accel = resample(roll_accel, n)
roll_rate  = resample(roll_rate, n)

# line up zero
opal_zero = min(range(len(opal_time)), key=lambda i: abs(opal_time[i]-0.0))
print "Opal t=0:", opal_zero

roll_zero = min(range(len(roll_time)), key=lambda i: abs(roll_time[i]-0.0))
print "Roll t=0:", roll_zero


opal_time = opal_time[opal_zero-roll_zero:]
end_time = len(roll_time)

opal_time = opal_time[:end_time]
opal_accel_x = opal_accel_x[opal_zero-roll_zero:]
opal_accel_x = opal_accel_x[:end_time]
opal_accel_y = opal_accel_y[opal_zero-roll_zero:]
opal_accel_y = opal_accel_y[:end_time]
opal_rate_x = opal_rate_x[opal_zero-roll_zero:]
opal_rate_x = opal_rate_x[:end_time]
opal_rate_y = opal_rate_y[opal_zero-roll_zero:]
opal_rate_y = opal_rate_y[:end_time]
opal_mag_x = opal_mag_x[opal_zero-roll_zero:]
opal_mag_x = opal_mag_x[:end_time]
opal_mag_y = opal_mag_y[opal_zero-roll_zero:]
opal_mag_y = opal_mag_y[:end_time]
opal_mag_z = opal_mag_z[opal_zero-roll_zero:]
opal_mag_z = opal_mag_z[:end_time]


Opal t=0: 181
Roll t=0: 19

In [3]:
%matplotlib inline
import utils
from matplotlib import rcParams
rcParams.update({'font.size': 14})

# fix time offset, t=0 is launch, not first value in list
t_0_offset = -0.016
times = []
for t in range(len(roll_time)):
    times.append(t_0_offset + (t*1/adis_sample_rate))

fig = utils.Plot(r"Launch 8 Acceleration", "Time [$s$]", "Acceleration [$m/s/s$]")
fig.plot(times, opal_accel_x, color=utils.blue)
fig.plot(times, opal_accel_y, color=utils.green)
fig.plot(times, roll_accel)
fig.show()



In [4]:
fig = utils.Plot(r"Launch 8 Roll", "Time [$s$]", "Rate [$m/s/s$]")
fig.plot(times, opal_rate_x, color=utils.blue)
fig.plot(times, opal_rate_y, color=utils.green)
fig.plot(times, roll_rate)
fig.show()



In [5]:
fig = utils.Plot(r"Launch 8 Magetometer", "Time [$s$]", "Magnetic Field [?]")
fig.plot(times, opal_mag_x, color=utils.blue)
fig.plot(times, opal_mag_y, color=utils.green)
fig.plot(times, opal_mag_z)
fig.show()


ADIS Data To FC

Now that we have data, we can send it to the flight computer.

First we start the FC:


In [6]:
import os
import subprocess
import time

# start the Flight comptuer
subprocess.call(['./start-stop-fc.sh', 'start'])
time.sleep(2.0) # settling time

In [7]:
import socket
import errno
from contextlib import closing

# Arming commands:
def arm():
    with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as sock:
        sock.bind(('', 35666))
        sock.connect(('127.0.0.1', 36000))
        sock.settimeout(0.01)
        try:
            sock.send("DI_SLOCK")
            time.sleep(0.5)
            sock.send("#YOLO")
            time.sleep(0.2)
        except socket.error as e:
            if e.errno == errno.ECONNREFUSED:
                print('connection refused, continuing')
            else:
                raise

arm() # FC now armed (so it will send fin commands)

In [8]:
# send resampled data to the Flight Comptuer
from psas_packet import io, messages
ADIS = messages.MESSAGES['ADIS']

last_time_sent = 0
target_delay = (1/adis_sample_rate)
with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as sock:
        sock.bind(('', 35020))
        sock.connect(('127.0.0.1', 36000))
        sock.settimeout(0.01)
        net = io.Network(sock)

        for i, t in enumerate(times):
            data = {
                'VCC': 5.0,
                'Gyro_X': roll_rate[i],
                'Gyro_Y': opal_rate_y[i],
                'Gyro_Z': opal_rate_x[i],
                'Acc_X': roll_accel[i],
                'Acc_Y': opal_accel_y[i],
                'Acc_Z': opal_accel_x[i],
                'Magn_X': 53e-6,
                'Magn_Y': 0,
                'Magn_Z': 0,
                'Temp': 20,
                'Aux_ADC': 0,
            }

            now = time.time()
            real_delay = now - last_time_sent
            # if we're too fast, slow down
            if real_delay < target_delay:
                #print (target_delay - real_delay)-0.0001
                time.sleep((target_delay - real_delay)) # try and fix average skew
            net.send_data(ADIS, i, data)
            last_time_sent = time.time()

In [9]:
# Stop FC
subprocess.call(['./start-stop-fc.sh', 'stop'])

# Move logfile for archiving
os.rename('./logfiles/logfile-001', './logfiles/softloop-001')

In [10]:
# Analysis
with io.BinFile('./logfiles/softloop-001') as fclog:
    adis_time = []
    accel = []
    roll_rate = []
    fin_time = []
    fin_angle = []
    state_time = []
    state_accel = []
    state_vel = []
    state_alt = []
    state_roll_rate = []
    state_roll = []
    for fourcc, data in fclog.read():
        if fourcc == 'ADIS':
            adis_time.append(data['timestamp'])
            roll_rate.append(data['Gyro_X'])
            accel.append(data['Acc_X'])
        elif fourcc == 'ROLL':
            fin_time.append(data['timestamp'])
            fin_angle.append(data['Angle'])
        elif fourcc == 'VSTE':
            state_time.append(data['Time'])
            state_accel.append(data['Acc_up'])
            state_vel.append(data['Vel_up'])
            state_alt.append(data['Altitude'])
            state_roll_rate.append(data['Roll_Rate'])
            state_roll.append(data['Roll_Angle'])
        elif fourcc != 'SEQN':
            print fourcc, data


# Time in seconds
fin_time = np.array(fin_time)
adis_time = np.array(adis_time)
adis_time -= adis_time[0]
adis_time = adis_time / 1e9
fin_time -= fin_time[0]
fin_time = fin_time / 1e9


Skipped unknown header: MESG

MESG {'timestamp': 2516666745}
boundary?

In [11]:
fig = utils.Plot(r"Fin Angle", "Time [$s$]", r"$\alpha$ [${}^0$]")
fig.plot(roll_time_orig, roll_fin, color=utils.blue, label="Launch-8 Actual Fin Angle")
fig.plot(fin_time, fin_angle, label="FC Fin Angle")
fig.ylim([-16, 16])
fig.legend(loc=3)
fig.show()