Merge branch 'master' into koller

This commit is contained in:
2023-01-29 15:47:42 +01:00
5 changed files with 226 additions and 83 deletions
+3
View File
@@ -12,3 +12,6 @@ python-dateutil==2.8.2
pytz==2021.3
scipy==1.7.1
six==1.16.0
numpy~=1.19.3
screeninfo~=0.8.1
+84 -22
View File
@@ -239,12 +239,13 @@ class CoilConstantCalibration(Thread):
class MagnetometerCalibrationSimple(Thread):
TEST_VECTOR_MAGNITUDE = 100e-6 # In Tesla. Chosen so it can be achieved with a 3A PSU.
def __init__(self, view_queue, calibration_points, calibration_interval, mgm_to_helmholtz_cos_trans):
def __init__(self, view_queue, calibration_points, calibration_interval, calibration_mag_field,
mgm_to_helmholtz_cos_trans):
Thread.__init__(self)
self.view_queue = view_queue
self.calibration_points = calibration_points
self.calibration_mag_field = calibration_mag_field
self.calibration_interval = calibration_interval
self.matrix_trans_mgm_to_hh = [[x.get() for x in row] for row in mgm_to_helmholtz_cos_trans]
@@ -305,7 +306,7 @@ class MagnetometerCalibrationSimple(Thread):
# Collect sensor data for each test vector
for vec_idx, test_vec in enumerate(test_vectors):
# Command output
applied_vec = test_vec * self.TEST_VECTOR_MAGNITUDE
applied_vec = test_vec * self.calibration_mag_field
self.cage_dev.set_field_raw(applied_vec)
# Sleep for a certain duration to allow psu to stabilize output and magnetometer to supply readings
@@ -405,13 +406,14 @@ class MagnetometerCalibrationSimple(Thread):
class MagnetometerCalibrationComplete(Thread):
TEST_VECTOR_MAGNITUDE = 100e-6 # In Tesla. Chosen so it can be achieved with a 3A PSU.
def __init__(self, view_queue, calibration_points, calibration_interval, mgm_to_helmholtz_cos_trans, right_column):
def __init__(self, view_queue, calibration_points, calibration_interval, calibration_mag_field,
mgm_to_helmholtz_cos_trans, right_column):
Thread.__init__(self)
self.view_queue = view_queue
self.calibration_points = calibration_points
self.calibration_interval = calibration_interval
self.calibration_mag_field = calibration_mag_field
self.matrix_trans_mgm_to_hh = [[x.get() for x in row] for row in mgm_to_helmholtz_cos_trans]
self.right_column = right_column
@@ -443,7 +445,7 @@ class MagnetometerCalibrationComplete(Thread):
def calibration_procedure(self):
# According to method outlined in:
# Chi, C. & Janosek, Lv, J-W., Wang, D (2018). Calibration of triaxial magnetometer with ellipsoid
# fitting method, DOI:10.1088/1755-1315/237/3/032015
# fitting method, DOI:10.1088/1755-1315/237/3/032015 and https://github.com/nliaudat/magnetometer_calibration
# This contains the raw experiment data for exporting
# Each row is a dict containing the applied vector and measured vector
@@ -472,7 +474,7 @@ class MagnetometerCalibrationComplete(Thread):
# Collect sensor data for each test vector
for vec_idx, test_vec in enumerate(test_vectors):
# Command output
applied_vec = test_vec * self.TEST_VECTOR_MAGNITUDE
applied_vec = test_vec * self.calibration_mag_field
self.cage_dev.set_field_raw(applied_vec)
# Sleep for a certain duration to allow psu to stabilize output and magnetometer to supply readings
@@ -523,7 +525,7 @@ class MagnetometerCalibrationComplete(Thread):
matrix_trans_mgm_to_hh_np = np.zeros((3, 3))
for row in range(3):
for col in range(3):
matrix_trans_mgm_to_hh_np[row][col] = matrix_trans_mgm_to_hh_tk[row][col].get()
matrix_trans_mgm_to_hh_np[row][col] = matrix_trans_mgm_to_hh_tk[row][col]
# matrix_trans_mgm_to_hh_np = [[-1, 0, 0], [0, 1, 0], [0, 0, -1]] # hardcoded for MGM 1 / 3
# matrix_trans_mgm_to_hh_np = [[0, 1, 0], [-1, 0, 0], [0, 0, 1]] # hardcoded for MGM 0 / 2
ui_print("Applying transformation matrix to data. h_{set,mgm} = mgm_T_hh * h_{set,hh}")
@@ -572,11 +574,7 @@ class MagnetometerCalibrationComplete(Thread):
# Retrieve calibration parameters
q_mat_inv = np.linalg.inv(q_mat)
b = -np.dot(q_mat_inv, n)
<<<<<<< Updated upstream
a_mat_inv = np.real(1 / csqrt(np.dot(n.T, np.dot(q_mat_inv, n)) - d) * linalg_scipy.sqrtm(q_mat))
=======
a_mat_inv = np.real(mag_amp_avg_set / np.sqrt(np.dot(n.T, np.dot(q_mat_inv, n)) - d) * scipy.linalg.sqrtm(q_mat))
>>>>>>> Stashed changes
a_mat = np.linalg.inv(a_mat_inv)
# Calculate error
cal_x = np.zeros(mag_x_m.shape)
@@ -586,14 +584,14 @@ class MagnetometerCalibrationComplete(Thread):
for i in range(len(mag_x_m)):
h = np.array([[mag_x_m[i], mag_y_m[i], mag_z_m[i]]]).T
h_hat = np.matmul(a_mat_inv, h - b) # Scaling issue
cal_x[i] = h_hat[0] * mag_amp_avg_set
cal_y[i] = h_hat[1] * mag_amp_avg_set
cal_z[i] = h_hat[2] * mag_amp_avg_set
cal_x[i] = h_hat[0]
cal_y[i] = h_hat[1]
cal_z[i] = h_hat[2]
mag = np.dot(h_hat.T, h_hat)
err = (mag[0][0] - 1) ** 2
total_error += err
# Scale unity solution back to original scaling
a_mat_inv = a_mat_inv * mag_amp_avg_set
a_mat_inv = a_mat_inv
# Console output
ui_print("Average magnitude: mag_amp_avg_set = {:.4f} uT, mag_amp_avg_m = {:.4f} uT".format(
mag_amp_avg_set * 10 ** 6, mag_amp_avg_m * 10 ** 6))
@@ -694,7 +692,7 @@ class MagnetometerCalibrationComplete(Thread):
return mag_x_set, mag_y_set, mag_z_set, mag_x_m, mag_y_m, mag_z_m
@staticmethod
def fit_ellipsoid(mag_x_m, mag_y_m, mag_z_m):
def fit_ellipsoid_old(mag_x_m, mag_y_m, mag_z_m):
# Script is adapted version from ThePoorEngineer - Calibrating the magnetometer
# https://thepoorengineer.com/en/calibrating-the-magnetometer/#Calibration
a1 = mag_x_m ** 2
@@ -749,10 +747,75 @@ class MagnetometerCalibrationComplete(Thread):
return q_mat, n, d
@staticmethod
<<<<<<< Updated upstream
def plot_magnetometer_calibration(target_column, mag_x_set, mag_y_set, mag_z_set, mag_x_m, mag_y_m, mag_z_m, cal_x, cal_y,
cal_z, mag_amp_avg_set):
=======
def fit_ellipsoid(mag_x_m, mag_y_m, mag_z_m):
""" Estimate ellipsoid parameters from a set of points.
Parameters
----------
mag_x_m, mag_y_m, mag_z_m : array_like, array_like, array_like
The samples (M,N) where M=3 (x,y,z) and N=number of samples.
Returns
-------
s : array_like
The samples (M,N) where M=3 (x,y,z) and N=number of samples.
Returns
-------
M, n, d : array_like, array_like, float
The ellipsoid parameters M, n, d.
References
----------
.. [1] Qingde Li; Griffiths, J.G., "Least squares ellipsoid specific
fitting," in Geometric Modeling and Processing, 2004.
Proceedings, vol., no., pp.335-340, 2004
.. https://github.com/nliaudat/magnetometer_calibration/blob/main/calibrate.py
"""
# Converts to samples (M,N) where M=3 (x,y,z) and N=number of samples.
s = np.array([mag_x_m, mag_y_m, mag_z_m])
# d (samples)
d = np.array([s[0] ** 2., s[1] ** 2., s[2] ** 2.,
2. * s[1] * s[2], 2. * s[0] * s[2], 2. * s[0] * s[1],
2. * s[0], 2. * s[1], 2. * s[2], np.ones_like(s[0])])
# s, s_11, s_12, s_21, s_22 (eq. 11)
s = np.dot(d, d.T)
s_11 = s[:6, :6]
s_12 = s[:6, 6:]
s_21 = s[6:, :6]
s_22 = s[6:, 6:]
# c (Eq. 8, k=4)
c = np.array([[-1, 1, 1, 0, 0, 0],
[1, -1, 1, 0, 0, 0],
[1, 1, -1, 0, 0, 0],
[0, 0, 0, -4, 0, 0],
[0, 0, 0, 0, -4, 0],
[0, 0, 0, 0, 0, -4]])
# v_1 (eq. 15, solution)
e = np.dot(np.linalg.inv(c),
s_11 - np.dot(s_12, np.dot(np.linalg.inv(s_22), s_21)))
e_w, e_v = np.linalg.eig(e)
v_1 = e_v[:, np.argmax(e_w)]
if v_1[0] < 0:
v_1 = -v_1
# v_2 (eq. 13, solution)
v_2 = np.dot(np.dot(-np.linalg.inv(s_22), s_21), v_1)
# Quadratic-form parameters
m = np.array([[v_1[0], v_1[3], v_1[4]],
[v_1[3], v_1[1], v_1[5]],
[v_1[4], v_1[5], v_1[2]]])
n = np.array([[v_2[0]],
[v_2[1]],
[v_2[2]]])
d = v_2[3]
return m, n, d
def fit_ellipsoid(mag_x_m, mag_y_m, mag_z_m):
""" Estimate ellipsoid parameters from a set of points.
Parameters
@@ -825,7 +888,6 @@ class MagnetometerCalibrationComplete(Thread):
@staticmethod
def plot_magnetometer_calibration(target_column, mag_x_set, mag_y_set, mag_z_set, mag_x_m, mag_y_m, mag_z_m,
cal_x, cal_y, cal_z, mag_amp_avg_set):
>>>>>>> Stashed changes
plot_fontsize = 5
ax_width = 0.2
+5
View File
@@ -11,3 +11,8 @@ class DeviceAccessError(Exception):
class DeviceBusy(DeviceAccessError):
"""Error thrown when the HW proxy (i.e. access) cannot be acquired"""
pass
class MagFieldOutOfBounds(Exception):
"""Set magnetic field must be a positive number between 0 and 200µT!"""
pass
+3
View File
@@ -50,3 +50,6 @@ default_psu_config = {
# Configuration for socket interface
SOCKET_PORT = 6677
SOCKET_MAX_CONNECTIONS = 5
# Hardware safety limits
MAG_MAG_FIELD = 5*37*1e-6 # [µT=A*µT/A] min coil constant x PSU current limit
+131 -61
View File
@@ -8,6 +8,7 @@ from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from tkinter import filedialog
import screeninfo
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
@@ -25,14 +26,14 @@ import src.config_handling as config
import src.csv_logging as log
from src.calibration import AmbientFieldCalibration, CoilConstantCalibration, MagnetometerCalibrationSimple, \
MagnetometerCalibrationComplete
from src.exceptions import DeviceAccessError
from src.exceptions import DeviceAccessError, MagFieldOutOfBounds
from src.utility import ui_print, save_dict_list_to_csv, load_dict_list_from_csv
import src.helmholtz_cage_device as helmholtz_cage_device
# Define global font styles:
screen_height_limit1 = 1100 # Limit after which font size gets reduced
screen_height_limit2 = 900 # Limit after which font size gets reduced
points = [13, 11, 9, 7, 6, 5]
points = [15, 13, 11, 9, 7, 6]
font = "Arial"
HEADER_FONT = (font, points[0], "bold")
SUB_HEADER_FONT = (font, points[2], "bold")
@@ -53,22 +54,30 @@ class HelmholtzGUI(Tk):
except TclError:
pass
# Check if multiple monitors connected and open the window on the largest or the non-primary monitor
monitors = screeninfo.get_monitors()
[sc_no, sc_x_max, sc_y_max, sc_width_max, sc_height_max] = [0, monitors[0].x, monitors[0].y,
monitors[0].width, monitors[0].height]
for i in range(len(monitors)):
if sc_width_max <= monitors[i].width:
[sc_no, sc_x_max, sc_y_max, sc_width_max, sc_height_max] = [i, monitors[i].x, monitors[i].y,
monitors[i].width, monitors[i].height]
print("Opening console on largest screen: #{} with {} x {}".format(sc_no, sc_width_max, sc_height_max))
Tk.geometry(self, "{}x{}+{}+{}".format(sc_width_max, sc_height_max, sc_x_max, sc_y_max))
Tk.state(self, 'zoomed')
# Change default fonts if display resolution is too small
screen_width = Tk.winfo_screenwidth(self)
screen_height = Tk.winfo_screenheight(self)
print("Screensize: {} x {}".format(screen_width, screen_height))
if screen_height <= screen_height_limit2:
if sc_height_max <= screen_height_limit2:
red = 2
elif screen_height <= screen_height_limit1:
elif sc_height_max <= screen_height_limit1:
red = 1
else:
red = 0
global HEADER_FONT, SUB_HEADER_FONT, BIG_BUTTON_FONT, SMALL_BUTTON_FONT, DEFAULT_FONT
HEADER_FONT = (font, points[0+red], "bold")
SUB_HEADER_FONT = (font, points[2+red], "bold")
BIG_BUTTON_FONT = (font, points[1+red], "bold")
SMALL_BUTTON_FONT = (font, points[2+red])
DEFAULT_FONT = (font, points[2+red])
HEADER_FONT = (font, points[0 + red], "bold")
SUB_HEADER_FONT = (font, points[2 + red], "bold")
BIG_BUTTON_FONT = (font, points[1 + red], "bold")
SMALL_BUTTON_FONT = (font, points[2 + red])
DEFAULT_FONT = (font, points[2 + red])
self.option_add("*font", DEFAULT_FONT)
self.Menu = TopMenu(self) # display dropdown menu bar at the top (see TopMenu class for details)
@@ -89,7 +98,8 @@ class HelmholtzGUI(Tk):
main_area = Frame(self, padx=10, pady=10) # create main area Frame where controls of each mode are displayed
main_area.pack(side="top", fill="both", expand=True) # pack main area at the top of the window
main_area.grid_rowconfigure(0, weight=5, minsize=800) # configure rows and columns of the Tkinter grid to expand with window
main_area.grid_rowconfigure(0, weight=5,
minsize=800) # configure rows and columns of the Tkinter grid to expand with window
main_area.grid_columnconfigure(0, weight=1)
# initialize the GUI pages for the different modes and setup switching between them
@@ -253,17 +263,17 @@ class ManualMode(Frame):
# add button for executing the current entries
execute_button = Button(self.buttons_frame, text="Execute", command=self.execute,
pady=5, padx=5, font=BIG_BUTTON_FONT)
pady=5, padx=5, font=SMALL_BUTTON_FONT)
execute_button.grid(row=row_counter, column=0, padx=5)
# add button for quick power_down
power_down_button = Button(self.buttons_frame, text="Power Down All", command=self.power_down,
pady=5, padx=5, font=BIG_BUTTON_FONT)
pady=5, padx=5, font=SMALL_BUTTON_FONT)
power_down_button.grid(row=row_counter, column=1, padx=5)
# add button for reinitialization of devices
reinit_button = Button(self.buttons_frame, text="Reinitialize", command=self.reinitialize,
pady=5, padx=5, font=BIG_BUTTON_FONT)
pady=5, padx=5, font=SMALL_BUTTON_FONT)
reinit_button.grid(row=row_counter, column=2, padx=5)
row_counter = row_counter + 1
@@ -578,8 +588,6 @@ class CalibrateAmbientField(Frame):
self.controller = controller
# To center window
# self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.left_column = Frame(self)
self.left_column.grid(row=0, column=0, sticky="nsew")
self.right_column = Frame(self)
@@ -645,7 +653,7 @@ class CalibrateAmbientField(Frame):
field_data_axis_units.grid(row=i, column=3, padx=5, pady=3)
row_counter += 1
# Calibration start and save to csv buttons
# Calibration start and reinitialize buttons
start_button_frame = Frame(self.left_column)
start_button_frame.grid(row=row_counter, column=0, sticky="sw")
self.start_ambient_calibration_button = Button(start_button_frame, text="Calibrate Ambient Field",
@@ -656,6 +664,11 @@ class CalibrateAmbientField(Frame):
command=self.calibration_procedure_coil_constants,
pady=5, padx=5, font=SMALL_BUTTON_FONT)
self.start_k_calibration_button.grid(row=0, column=1, padx=10, pady=10)
# Reinitialize button
self.reinitialize_button = Button(start_button_frame, text="Reinitialize",
command=self.reinitialize,
pady=5, padx=5, font=SMALL_BUTTON_FONT)
self.reinitialize_button.grid(row=0, column=2, padx=10, pady=10)
row_counter += 1
# Calibration progress bar
@@ -969,6 +982,15 @@ class CalibrateAmbientField(Frame):
self.clipboard_append(self.coil_constant_clipboard)
self.update()
def reinitialize(self): # called on "Reinitialize!" button press
# reinitialize all PSUs and the Arduino
g.CAGE_DEVICE.reconnect_hardware_async()
# log change to the log file if user has selected event logging in the Configure Logging window
logger = self.controller.pages[ConfigureLogging] # get object of logging configurator
if logger.event_logging: # data should be logged when test bench is commanded
logger.log_datapoint() # log data
class CalibrateMagnetometerSimple(Frame):
def __init__(self, parent, controller):
@@ -997,6 +1019,7 @@ class CalibrateMagnetometerSimple(Frame):
self.calibration_procedure_progress_var = IntVar(value=0)
# Calibration parameters
self.calibration_points_var = IntVar(value=8)
self.mag_field_magnitude_var = DoubleVar(value=100)
self.calibration_interval_var = DoubleVar(value=5)
# Calibration results
self.sensitivity_result_vars = [StringVar(), StringVar(), StringVar()]
@@ -1048,26 +1071,51 @@ class CalibrateMagnetometerSimple(Frame):
# Centered controls
controls_frame = Frame(self.left_column)
controls_frame.grid(row=row_counter, column=0, sticky="nw")
# Magnitude of magnetic field
mag_field_magnitude_label = Label(controls_frame, text="Magnetic field magnitude")
mag_field_magnitude_label.grid(row=0, column=0, pady=5, sticky="nw")
mag_field_magnitude_entry = Entry(controls_frame, textvariable=self.mag_field_magnitude_var)
mag_field_magnitude_entry.grid(row=0, column=1, pady=5, sticky="nw")
mag_field_magnitude_unit = Label(controls_frame, text="µT (0 to {:.0f} µT)".format(g.MAG_MAG_FIELD * 1e6))
mag_field_magnitude_unit.grid(row=0, column=2, pady=5, sticky="nw")
# Number of calibration points
calibration_point_nr_label = Label(controls_frame, text="# of calibration points")
calibration_point_nr_label.grid(row=0, column=0, pady=5, sticky="nw")
calibration_point_nr_label.grid(row=1, column=0, pady=5, sticky="nw")
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_points_var)
calibration_point_nr_entry.grid(row=0, column=1, pady=5, sticky="nw")
calibration_point_nr_entry.grid(row=1, column=1, pady=5, sticky="nw")
calibration_point_nr__unit = Label(controls_frame, text="- (> 8 points)")
calibration_point_nr__unit.grid(row=1, column=2, pady=5, sticky="nw")
# Measurement interval
calibration_point_nr_label = Label(controls_frame, text="Measurement interval [s]")
calibration_point_nr_label.grid(row=1, column=0, pady=5, sticky="nw")
calibration_point_nr_label.grid(row=2, column=0, pady=5, sticky="nw")
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_interval_var)
calibration_point_nr_entry.grid(row=1, column=1, pady=5, sticky="nw")
calibration_point_nr_entry.grid(row=2, column=1, pady=5, sticky="nw")
calibration_point_nr_unit = Label(controls_frame, text="s (> 2 s)")
calibration_point_nr_unit.grid(row=2, column=2, pady=5, sticky="nw")
# Measurement interval
calibration_point_nr_label = Label(controls_frame, text="Measurement interval [s]")
calibration_point_nr_label.grid(row=2, column=0, pady=5, sticky="nw")
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_interval_var)
calibration_point_nr_entry.grid(row=2, column=1, pady=5, sticky="nw")
calibration_point_nr_unit = Label(controls_frame, text="s (> 2 s)")
calibration_point_nr_unit.grid(row=2, column=2, pady=5, sticky="nw")
# Calibration start buttons
start_button_frame = Frame(controls_frame)
start_button_frame.grid(row=2, column=0, columnspan=2)
start_button_frame.grid(row=3, column=0, columnspan=1, sticky="nw")
self.start_calibration_button = Button(start_button_frame, text="Start Calibration",
command=self.start_calibration_procedure,
pady=5, padx=5, font=SMALL_BUTTON_FONT)
self.start_calibration_button.grid(row=0, column=0, padx=10, pady=(30, 10))
self.start_calibration_button.grid(row=0, column=0, padx=10, pady=(30, 10), sticky="we")
# Reinitialize button
reinitialize_button_frame = Frame(controls_frame)
reinitialize_button_frame.grid(row=3, column=1, columnspan=1)
self.reinitialize_button = Button(reinitialize_button_frame, text="Reinitialize",
command=self.reinitialize,
pady=5, padx=5, font=SMALL_BUTTON_FONT)
self.reinitialize_button.grid(row=0, column=0, padx=10, pady=(30, 10), sticky="we")
# Calibration progress bar
progress_bar_frame = Frame(controls_frame)
progress_bar_frame.grid(row=3, column=0, columnspan=2)
progress_bar_frame.grid(row=4, column=0, columnspan=2)
calibration_procedure_progress_label = Label(progress_bar_frame, text="Progress:")
calibration_procedure_progress_label.grid(row=0, column=0, padx=10, pady=10, sticky="nw")
calibration_procedure_progress = ttk.Progressbar(progress_bar_frame,
@@ -1325,12 +1373,18 @@ class CalibrateMagnetometerSimple(Frame):
try:
calibration_points = self.calibration_points_var.get()
calibration_interval = self.calibration_interval_var.get()
calibration_mag_field = self.mag_field_magnitude_var.get() * 1e-6 # converted to micro Tesla
if calibration_mag_field <= 0 or calibration_mag_field > g.MAG_MAG_FIELD:
raise MagFieldOutOfBounds
self.calibration_thread = MagnetometerCalibrationSimple(self.view_mpi_queue,
calibration_points,
calibration_interval,
calibration_mag_field,
self.mgm_to_helmholtz_cos_trans)
self.calibration_thread.start()
self.deactivate_buttons()
except MagFieldOutOfBounds as e:
messagebox.showwarning("Calibration failed", "\n{}".format(e))
except (DeviceAccessError, TclError) as e:
messagebox.showwarning("Calibration failed", "Failed to start calibration:\n{}".format(e))
@@ -1409,6 +1463,15 @@ class CalibrateMagnetometerSimple(Frame):
[DoubleVar(value=0), DoubleVar(value=1), DoubleVar(value=0)],
[DoubleVar(value=0), DoubleVar(value=0), DoubleVar(value=1)]]
def reinitialize(self): # called on "Reinitialize!" button press
# reinitialize all PSUs and the Arduino
g.CAGE_DEVICE.reconnect_hardware_async()
# log change to the log file if user has selected event logging in the Configure Logging window
logger = self.controller.pages[ConfigureLogging] # get object of logging configurator
if logger.event_logging: # data should be logged when test bench is commanded
logger.log_datapoint() # log data
class CalibrateMagnetometerComplete(Frame):
def __init__(self, parent, controller):
@@ -1438,6 +1501,7 @@ class CalibrateMagnetometerComplete(Frame):
StringVar(value="No data")]
self.calibration_procedure_progress_var = IntVar(value=0)
# Calibration parameters
self.mag_field_magnitude_var = DoubleVar(value=100)
self.calibration_points_var = IntVar(value=8)
self.calibration_interval_var = DoubleVar(value=5)
# Calibration results
@@ -1500,26 +1564,44 @@ class CalibrateMagnetometerComplete(Frame):
# Centered controls
controls_frame = Frame(self.left_column)
controls_frame.grid(row=row_counter, column=0, sticky="nw")
# Magnitude of magnetic field
mag_field_magnitude_label = Label(controls_frame, text="Magnetic field magnitude")
mag_field_magnitude_label.grid(row=0, column=0, pady=5, sticky="nw")
mag_field_magnitude_entry = Entry(controls_frame, textvariable=self.mag_field_magnitude_var)
mag_field_magnitude_entry.grid(row=0, column=1, pady=5, sticky="nw")
mag_field_magnitude_unit = Label(controls_frame, text="µT (0 to {:.0f} µT)".format(g.MAG_MAG_FIELD * 1e6))
mag_field_magnitude_unit.grid(row=0, column=2, pady=5, sticky="nw")
# Number of calibration points
calibration_point_nr_label = Label(controls_frame, text="# of calibration points")
calibration_point_nr_label.grid(row=0, column=0, pady=5, sticky="nw")
calibration_point_nr_label.grid(row=1, column=0, pady=5, sticky="nw")
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_points_var)
calibration_point_nr_entry.grid(row=0, column=1, pady=5, sticky="nw")
calibration_point_nr_entry.grid(row=1, column=1, pady=5, sticky="nw")
calibration_point_nr__unit = Label(controls_frame, text="- (> 8 points)")
calibration_point_nr__unit.grid(row=1, column=2, pady=5, sticky="nw")
# Measurement interval
calibration_point_nr_label = Label(controls_frame, text="Measurement interval [s]")
calibration_point_nr_label.grid(row=1, column=0, pady=5, sticky="nw")
calibration_point_nr_label.grid(row=2, column=0, pady=5, sticky="nw")
calibration_point_nr_entry = Entry(controls_frame, textvariable=self.calibration_interval_var)
calibration_point_nr_entry.grid(row=1, column=1, pady=5, sticky="nw")
calibration_point_nr_entry.grid(row=2, column=1, pady=5, sticky="nw")
calibration_point_nr_unit = Label(controls_frame, text="s (> 2 s)")
calibration_point_nr_unit.grid(row=2, column=2, pady=5, sticky="nw")
# Calibration start buttons
start_button_frame = Frame(controls_frame)
start_button_frame.grid(row=2, column=0, columnspan=2, sticky="nw")
start_button_frame.grid(row=3, column=0, columnspan=1, sticky="nw")
self.start_calibration_button = Button(start_button_frame, text="Start Calibration",
command=self.start_calibration_procedure,
pady=5, padx=5, font=SMALL_BUTTON_FONT)
self.start_calibration_button.grid(row=0, column=0, padx=10, pady=(30, 10), sticky="we")
# Reinitialize button
reinitialize_button_frame = Frame(controls_frame)
reinitialize_button_frame.grid(row=3, column=1, columnspan=1)
self.reinitialize_button = Button(reinitialize_button_frame, text="Reinitialize",
command=self.reinitialize,
pady=5, padx=5, font=SMALL_BUTTON_FONT)
self.reinitialize_button.grid(row=0, column=0, padx=10, pady=(30, 10), sticky="we")
# Calibration progress bar
progress_bar_frame = Frame(controls_frame)
progress_bar_frame.grid(row=3, column=0, columnspan=2)
progress_bar_frame.grid(row=4, column=0, columnspan=2)
calibration_procedure_progress_label = Label(progress_bar_frame, text="Progress:")
calibration_procedure_progress_label.grid(row=0, column=0, padx=10, pady=10, sticky="nw")
calibration_procedure_progress = ttk.Progressbar(progress_bar_frame,
@@ -1611,11 +1693,8 @@ class CalibrateMagnetometerComplete(Frame):
width=15,
state='readonly')
axis_data.grid(row=row_counter + row, column=1 + column, padx=5, pady=5, sticky="nw")
<<<<<<< Updated upstream
=======
results_label_unit = Label(calibration_results_frame, text="-")
results_label_unit.grid(row=row_counter + row, column=1 + 3, padx=5, pady=5, sticky="nw")
>>>>>>> Stashed changes
row_counter += 3
"""
# A_mat
@@ -1639,11 +1718,8 @@ class CalibrateMagnetometerComplete(Frame):
width=15,
state='readonly')
axis_data.grid(row=row_counter, column=1 + row, padx=5, pady=5, sticky="nw")
<<<<<<< Updated upstream
=======
results_label_unit = Label(calibration_results_frame, text="T")
results_label_unit.grid(row=row_counter, column=1 + row + 1, padx=5, pady=5, sticky="nw")
>>>>>>> Stashed changes
row_counter += 1
# Save calibration buttons
@@ -1803,23 +1879,15 @@ class CalibrateMagnetometerComplete(Frame):
try:
calibration_points = self.calibration_points_var.get()
calibration_interval = self.calibration_interval_var.get()
<<<<<<< Updated upstream
self.calibration_thread = MagnetometerCalibrationComplete(self.view_mpi_queue,
calibration_points,
calibration_interval,
self.mgm_to_helmholtz_cos_trans,
self.right_column)
self.calibration_thread.start()
self.deactivate_buttons()
=======
calibration_mag_field = self.mag_field_magnitude_var.get() * 1e-6 # converted to micro Tesla
if calibration_mag_field <= 0 or calibration_mag_field > g.MAG_MAG_FIELD:
raise MagFieldOutOfBounds
[self.calibration_thread, raw_data] = MagnetometerCalibrationComplete(self.view_mpi_queue,
calibration_points,
calibration_interval,
calibration_mag_field,
self.right_column)
self.calibration_thread = MagnetometerCalibrationComplete(self.view_mpi_queue,
calibration_points,
calibration_interval,
calibration_mag_field,
self.mgm_to_helmholtz_cos_trans,
self.right_column)
self.calibration_thread.start()
self.deactivate_buttons()
# Use collected data to build and solve system of equations
@@ -1832,7 +1900,6 @@ class CalibrateMagnetometerComplete(Frame):
cal_x, cal_y, cal_z, mag_amp_avg_set)
except MagFieldOutOfBounds as e:
messagebox.showwarning("Calibration failed", "\n{}".format(e))
>>>>>>> Stashed changes
except (DeviceAccessError, TclError) as e:
messagebox.showwarning("Calibration failed", "Failed to start calibration:\n{}".format(e))
@@ -1857,21 +1924,15 @@ class CalibrateMagnetometerComplete(Frame):
return
self.calibration_raw_results = raw_data
# Get transformation matrix from GUI and transform data
mgm_to_helmholtz_cos_trans = [[x.get() for x in row] for row in self.mgm_to_helmholtz_cos_trans]
# Execute calibration function and display results
sensor_parameters, mag_x_set, mag_y_set, mag_z_set, mag_x_m, mag_y_m, mag_z_m, cal_x, cal_y, cal_z, mag_amp_avg_set = MagnetometerCalibrationComplete.solve_system(
<<<<<<< Updated upstream
raw_data, self.mgm_to_helmholtz_cos_trans)
MagnetometerCalibrationComplete.plot_magnetometer_calibration(self.right_column, mag_x_set, mag_y_set, mag_z_set,
mag_x_m,
mag_y_m, mag_z_m, cal_x, cal_y,
cal_z, mag_amp_avg_set)
=======
raw_data, mgm_to_helmholtz_cos_trans)
MagnetometerCalibrationComplete.plot_magnetometer_calibration(self.right_column,
mag_x_set, mag_y_set, mag_z_set,
mag_x_m, mag_y_m, mag_z_m,
cal_x, cal_y, cal_z, mag_amp_avg_set)
>>>>>>> Stashed changes
# Pass results to UI
self.put_message('calibration_data', {'results': sensor_parameters, 'raw_data': raw_data})
except TypeError:
@@ -1972,6 +2033,15 @@ class CalibrateMagnetometerComplete(Frame):
[DoubleVar(value=0), DoubleVar(value=1), DoubleVar(value=0)],
[DoubleVar(value=0), DoubleVar(value=0), DoubleVar(value=1)]]
def reinitialize(self): # called on "Reinitialize!" button press
# reinitialize all PSUs and the Arduino
g.CAGE_DEVICE.reconnect_hardware_async()
# log change to the log file if user has selected event logging in the Configure Logging window
logger = self.controller.pages[ConfigureLogging] # get object of logging configurator
if logger.event_logging: # data should be logged when test bench is commanded
logger.log_datapoint() # log data
class HardwareConfiguration(Frame):
"""Settings window to set program constants"""