Files
matlab-python/src/tilt/conversion.py
2025-10-12 20:16:19 +02:00

323 lines
10 KiB
Python

"""
Data conversion functions for Tilt sensors.
Converts raw sensor data to physical units (angles, temperatures).
"""
import numpy as np
import logging
from typing import Tuple
logger = logging.getLogger(__name__)
def convert_tilt_link_hr_data(
angle_data: np.ndarray,
temperature: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> Tuple[np.ndarray, np.ndarray]:
"""
Convert raw Tilt Link HR data to physical units (angles in degrees).
Converts MATLAB conv_grezziTLHR.m function.
Args:
angle_data: Raw angle data (ADC counts)
temperature: Raw temperature data
calibration_data: Calibration coefficients
If column 4 == 0: XY gain is common
Column 1: gain XY
Column 2: gain temp
Column 3: offset temp
Else: separate XY gains
Column 1: gain X
Column 2: gain Y
Column 3: gain temp
Column 4: offset temp
n_sensors: Number of sensors
Returns:
Tuple of (converted_angles, converted_temperature)
"""
logger.info(f"Converting Tilt Link HR data for {n_sensors} sensors")
n_timestamps = angle_data.shape[0]
angle_converted = angle_data.copy()
temp_converted = temperature.copy()
# Check if XY gains are common or separate
if len(calibration_data.shape) == 1 or calibration_data.shape[1] < 4:
# Simple case: single calibration set
xy_common = True
gain_xy = calibration_data[0] if len(calibration_data) > 0 else 1.0
gain_temp = calibration_data[1] if len(calibration_data) > 1 else 1.0
offset_temp = calibration_data[2] if len(calibration_data) > 2 else 0.0
else:
# Check column 4 (index 3)
if np.all(calibration_data[:, 3] == 0):
# XY gains are common
xy_common = True
gain_angles = calibration_data[:, 0] # Common gain for both axes
gain_temp = calibration_data[:, 1]
offset_temp = calibration_data[:, 2]
else:
# Separate XY gains
xy_common = False
gain_x = calibration_data[:, 0]
gain_y = calibration_data[:, 1]
gain_temp = calibration_data[:, 2]
offset_temp = calibration_data[:, 3]
# Convert angles
if xy_common:
# Common gain for X and Y
for i in range(n_sensors):
gain = gain_angles[i] if hasattr(gain_angles, '__len__') else gain_xy
angle_converted[:, i * 2] = angle_data[:, i * 2] * gain # X
angle_converted[:, i * 2 + 1] = angle_data[:, i * 2 + 1] * gain # Y
else:
# Separate gains for X and Y
for i in range(n_sensors):
angle_converted[:, i * 2] = angle_data[:, i * 2] * gain_x[i] # X
angle_converted[:, i * 2 + 1] = angle_data[:, i * 2 + 1] * gain_y[i] # Y
# Convert temperatures
for i in range(n_sensors):
g_temp = gain_temp[i] if hasattr(gain_temp, '__len__') else gain_temp
off_temp = offset_temp[i] if hasattr(offset_temp, '__len__') else offset_temp
temp_converted[:, i] = temperature[:, i] * g_temp + off_temp
logger.info("Tilt Link HR data conversion completed")
return angle_converted, temp_converted
def convert_tilt_link_data(
acceleration: np.ndarray,
temperature: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> Tuple[np.ndarray, np.ndarray]:
"""
Convert raw Tilt Link data to physical units (acceleration in g).
Similar to RSN conversion but for standard Tilt Link sensors.
Args:
acceleration: Raw acceleration data
temperature: Raw temperature data
calibration_data: Calibration coefficients for each sensor
n_sensors: Number of sensors
Returns:
Tuple of (converted_acceleration, converted_temperature)
"""
logger.info(f"Converting Tilt Link data for {n_sensors} sensors")
n_timestamps = acceleration.shape[0]
acc_converted = np.zeros_like(acceleration)
temp_converted = np.zeros_like(temperature)
for i in range(n_sensors):
cal = calibration_data[i]
# Acceleration conversion (typically 2 or 3 axes)
# Assume biaxial for Tilt Link
acc_converted[:, i * 2] = cal[0] * acceleration[:, i * 2] + cal[1] # X
acc_converted[:, i * 2 + 1] = cal[2] * acceleration[:, i * 2 + 1] + cal[3] # Y
# Temperature conversion
if len(cal) > 4:
temp_converted[:, i] = cal[4] * temperature[:, i] + cal[5]
else:
temp_converted[:, i] = temperature[:, i]
logger.info("Tilt Link data conversion completed")
return acc_converted, temp_converted
def convert_biaxial_link_data(
raw_data: np.ndarray,
temperature: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> Tuple[np.ndarray, np.ndarray]:
"""
Convert raw Biaxial Link (BL) data to physical units.
Converts MATLAB conv_grezziBL.m function.
Args:
raw_data: Raw sensor data
temperature: Raw temperature data
calibration_data: Calibration coefficients
n_sensors: Number of sensors
Returns:
Tuple of (converted_data, converted_temperature)
"""
logger.info(f"Converting Biaxial Link data for {n_sensors} sensors")
data_converted = np.zeros_like(raw_data)
temp_converted = np.zeros_like(temperature)
for i in range(n_sensors):
cal = calibration_data[i]
# Biaxial: 2 axes per sensor
data_converted[:, i * 2] = cal[0] * raw_data[:, i * 2] + cal[1]
data_converted[:, i * 2 + 1] = cal[2] * raw_data[:, i * 2 + 1] + cal[3]
# Temperature
if len(cal) > 4:
temp_converted[:, i] = cal[4] * temperature[:, i] + cal[5]
else:
temp_converted[:, i] = temperature[:, i]
logger.info("Biaxial Link data conversion completed")
return data_converted, temp_converted
def convert_pendulum_link_data(
raw_data: np.ndarray,
temperature: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> Tuple[np.ndarray, np.ndarray]:
"""
Convert raw Pendulum Link (PL) data to physical units.
Args:
raw_data: Raw sensor data
temperature: Raw temperature data
calibration_data: Calibration coefficients
n_sensors: Number of sensors
Returns:
Tuple of (converted_data, converted_temperature)
"""
logger.info(f"Converting Pendulum Link data for {n_sensors} sensors")
data_converted = np.zeros_like(raw_data)
temp_converted = np.zeros_like(temperature)
for i in range(n_sensors):
cal = calibration_data[i]
# Pendulum typically has 2 axes
data_converted[:, i * 2] = cal[0] * raw_data[:, i * 2] + cal[1]
data_converted[:, i * 2 + 1] = cal[2] * raw_data[:, i * 2 + 1] + cal[3]
# Temperature
if len(cal) > 4:
temp_converted[:, i] = cal[4] * temperature[:, i] + cal[5]
else:
temp_converted[:, i] = temperature[:, i]
logger.info("Pendulum Link data conversion completed")
return data_converted, temp_converted
def convert_kessler_link_data(
raw_data: np.ndarray,
temperature: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> Tuple[np.ndarray, np.ndarray]:
"""
Convert raw Kessler Link (KL/KLHR) data to physical units.
Converts MATLAB conv_grezziKLHR.m function.
Args:
raw_data: Raw sensor data
temperature: Raw temperature data
calibration_data: Calibration coefficients
n_sensors: Number of sensors
Returns:
Tuple of (converted_data, converted_temperature)
"""
logger.info(f"Converting Kessler Link data for {n_sensors} sensors")
data_converted = np.zeros_like(raw_data)
temp_converted = np.zeros_like(temperature)
for i in range(n_sensors):
cal = calibration_data[i]
# Kessler biaxial inclinometer
data_converted[:, i * 2] = cal[0] * raw_data[:, i * 2] + cal[1]
data_converted[:, i * 2 + 1] = cal[2] * raw_data[:, i * 2 + 1] + cal[3]
# Temperature
if len(cal) > 4:
temp_converted[:, i] = cal[4] * temperature[:, i] + cal[5]
else:
temp_converted[:, i] = temperature[:, i]
logger.info("Kessler Link data conversion completed")
return data_converted, temp_converted
def convert_thermistor_data(
raw_data: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> np.ndarray:
"""
Convert raw thermistor (ThL) data to temperature in Celsius.
Converts MATLAB conv_grezziThL.m function.
Args:
raw_data: Raw ADC values
calibration_data: Calibration coefficients (gain, offset)
n_sensors: Number of sensors
Returns:
Converted temperature array
"""
logger.info(f"Converting Thermistor data for {n_sensors} sensors")
temp_converted = np.zeros_like(raw_data)
for i in range(n_sensors):
cal = calibration_data[i]
# Linear conversion: T = gain * ADC + offset
temp_converted[:, i] = cal[0] * raw_data[:, i] + cal[1]
logger.info("Thermistor data conversion completed")
return temp_converted
def convert_pt100_data(
raw_data: np.ndarray,
calibration_data: np.ndarray,
n_sensors: int
) -> np.ndarray:
"""
Convert raw PT100 sensor data to temperature in Celsius.
Converts MATLAB conv_grezziPT100.m function.
Args:
raw_data: Raw resistance or ADC values
calibration_data: Calibration coefficients
n_sensors: Number of sensors
Returns:
Converted temperature array
"""
logger.info(f"Converting PT100 data for {n_sensors} sensors")
temp_converted = np.zeros_like(raw_data)
for i in range(n_sensors):
cal = calibration_data[i]
# PT100 typically linear: T = gain * R + offset
temp_converted[:, i] = cal[0] * raw_data[:, i] + cal[1]
logger.info("PT100 data conversion completed")
return temp_converted