forked from zietzm/Helmholtz_Test_Bench
Merge branch 'master' into koller
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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"""
|
||||
|
||||
Reference in New Issue
Block a user