mirror of
https://git.intern.spaceteamaachen.de/ALPAKA/SPATZ.git
synced 2025-06-10 18:15:59 +00:00
Added observers for tracking data
This commit is contained in:
parent
22d6280123
commit
b331e9b27a
302
demo.ipynb
302
demo.ipynb
File diff suppressed because one or more lines are too long
@ -131,7 +131,7 @@ class Dataset(Advanceable):
|
|||||||
ArrayLike: The current transformation matrix from local to body-fixed coords.
|
ArrayLike: The current transformation matrix from local to body-fixed coords.
|
||||||
"""
|
"""
|
||||||
# Get the rotation in the local coordinate system.
|
# Get the rotation in the local coordinate system.
|
||||||
rots = self.__fetch_values(['pitch_l', 'yaw_l', 'roll_l'])
|
rots = self.fetch_values(['pitch_l', 'yaw_l', 'roll_l'])
|
||||||
pitch_l, yaw_l, roll_l = rots[0], rots[1], rots[2]
|
pitch_l, yaw_l, roll_l = rots[0], rots[1], rots[2]
|
||||||
|
|
||||||
return self.T1(roll_l) @ self.T2(pitch_l - math.pi/2) @ self.T1(-yaw_l)
|
return self.T1(roll_l) @ self.T2(pitch_l - math.pi/2) @ self.T1(-yaw_l)
|
||||||
@ -141,8 +141,8 @@ class Dataset(Advanceable):
|
|||||||
Returns:
|
Returns:
|
||||||
ArrayLike: The current transformation matrix from global to local coords.
|
ArrayLike: The current transformation matrix from global to local coords.
|
||||||
"""
|
"""
|
||||||
decl = self.__fetch_value('declination')
|
decl = self.fetch_value('declination')
|
||||||
long = self.__fetch_value('longitude')
|
long = self.fetch_value('longitude')
|
||||||
t0 = self.__df['time'].iloc[0]
|
t0 = self.__df['time'].iloc[0]
|
||||||
|
|
||||||
omega_E = (2*math.pi) / (24*60*60)
|
omega_E = (2*math.pi) / (24*60*60)
|
||||||
@ -189,7 +189,7 @@ class Dataset(Advanceable):
|
|||||||
"""
|
"""
|
||||||
return self.get_mach_number() > 1
|
return self.get_mach_number() > 1
|
||||||
|
|
||||||
def __fetch_value(self, name: str) -> float:
|
def fetch_value(self, name: str) -> float:
|
||||||
"""Get a specific value from the dataframe.
|
"""Get a specific value from the dataframe.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -212,7 +212,7 @@ class Dataset(Advanceable):
|
|||||||
# Interpolate linearly between the two data points.
|
# Interpolate linearly between the two data points.
|
||||||
return (1 - alpha) * self.__df[name].iloc[self.__idx] + alpha * self.__df[name].iloc[self.__idx + 1]
|
return (1 - alpha) * self.__df[name].iloc[self.__idx] + alpha * self.__df[name].iloc[self.__idx + 1]
|
||||||
|
|
||||||
def __fetch_values(self, names: List[str]) -> np.array:
|
def fetch_values(self, names: List[str]) -> np.array:
|
||||||
"""Get specific values from the dataframe.
|
"""Get specific values from the dataframe.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -221,14 +221,14 @@ class Dataset(Advanceable):
|
|||||||
Returns:
|
Returns:
|
||||||
np.array: Returns a numpy array containing the requested values in the same order as in the input list.
|
np.array: Returns a numpy array containing the requested values in the same order as in the input list.
|
||||||
"""
|
"""
|
||||||
return np.asarray([self.__fetch_value(name) for name in names])
|
return np.asarray([self.fetch_value(name) for name in names])
|
||||||
|
|
||||||
def get_velocity(self) -> float:
|
def get_velocity(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
np.array: Returns the velocity at the current time of the simulation.
|
np.array: Returns the velocity at the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('velocity')
|
return self.fetch_value('velocity')
|
||||||
|
|
||||||
def get_acceleration(self, frame='FL') -> ArrayLike:
|
def get_acceleration(self, frame='FL') -> ArrayLike:
|
||||||
"""_summary_
|
"""_summary_
|
||||||
@ -239,7 +239,7 @@ class Dataset(Advanceable):
|
|||||||
Returns:
|
Returns:
|
||||||
ArrayLike: _description_
|
ArrayLike: _description_
|
||||||
"""
|
"""
|
||||||
acc = self.__fetch_values(['ax', 'ay', 'az'])
|
acc = self.fetch_values(['ax', 'ay', 'az'])
|
||||||
|
|
||||||
if frame == 'B':
|
if frame == 'B':
|
||||||
return self.launch_rail_to_body() @ acc
|
return self.launch_rail_to_body() @ acc
|
||||||
@ -251,7 +251,7 @@ class Dataset(Advanceable):
|
|||||||
Returns:
|
Returns:
|
||||||
ArrayLike: Gets the derivatives in angular velocity across all axes of the rocket.
|
ArrayLike: Gets the derivatives in angular velocity across all axes of the rocket.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_values(['omega_X', 'omega_Y', 'omega_Z'])
|
return self.fetch_values(['omega_X', 'omega_Y', 'omega_Z'])
|
||||||
|
|
||||||
def get_velocity(self, frame='FL') -> ArrayLike:
|
def get_velocity(self, frame='FL') -> ArrayLike:
|
||||||
"""
|
"""
|
||||||
@ -262,7 +262,7 @@ class Dataset(Advanceable):
|
|||||||
ArrayLike: _description_
|
ArrayLike: _description_
|
||||||
"""
|
"""
|
||||||
|
|
||||||
vel = self.__fetch_values(['vx', 'vy', 'vz'])
|
vel = self.fetch_values(['vx', 'vy', 'vz'])
|
||||||
|
|
||||||
if frame == 'B':
|
if frame == 'B':
|
||||||
return self.launch_rail_to_body() @ vel
|
return self.launch_rail_to_body() @ vel
|
||||||
@ -274,63 +274,63 @@ class Dataset(Advanceable):
|
|||||||
Returns:
|
Returns:
|
||||||
float: Returns the mach number at the current time of the simulation.
|
float: Returns the mach number at the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('mach')
|
return self.fetch_value('mach')
|
||||||
|
|
||||||
def get_speed_of_sound(self) -> float:
|
def get_speed_of_sound(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
float: Returns the speed of sound at the current time of the simulation.
|
float: Returns the speed of sound at the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('speedofsound')
|
return self.fetch_value('speedofsound')
|
||||||
|
|
||||||
def get_rotation_rates(self) -> np.array:
|
def get_rotation_rates(self) -> np.array:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
np.array: Returns the rotation rates at the current time of the simulation.
|
np.array: Returns the rotation rates at the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_values(['OMEGA_X', 'OMEGA_Y', 'OMEGA_Z'])
|
return self.fetch_values(['OMEGA_X', 'OMEGA_Y', 'OMEGA_Z'])
|
||||||
|
|
||||||
def get_rotation(self) -> np.array:
|
def get_rotation(self) -> np.array:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
np.array: _description_
|
np.array: _description_
|
||||||
"""
|
"""
|
||||||
return self.__fetch_values(['pitch_l', 'yaw_l', 'roll_l'])
|
return self.fetch_values(['pitch_l', 'yaw_l', 'roll_l'])
|
||||||
|
|
||||||
def get_temperature(self) -> float:
|
def get_temperature(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
np.array: Returns the temperature at the current time of the simulation.
|
np.array: Returns the temperature at the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('temperature')
|
return self.fetch_value('temperature')
|
||||||
|
|
||||||
def get_pressure(self) -> float:
|
def get_pressure(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
np.array: Returns the pressure at the current time of the simulation.
|
np.array: Returns the pressure at the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('pressure')
|
return self.fetch_value('pressure')
|
||||||
|
|
||||||
def get_thrust(self) -> float:
|
def get_thrust(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
float: Returns the thrust value for the current time of the simulation.
|
float: Returns the thrust value for the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('thrust')
|
return self.fetch_value('thrust')
|
||||||
|
|
||||||
def get_drag(self) -> float:
|
def get_drag(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
float: Returns the drag value for the current time of the simulation.
|
float: Returns the drag value for the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('drag')
|
return self.fetch_value('drag')
|
||||||
|
|
||||||
def get_mass(self) -> float:
|
def get_mass(self) -> float:
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
float: Returns the mass value for the current time of the simulation.
|
float: Returns the mass value for the current time of the simulation.
|
||||||
"""
|
"""
|
||||||
return self.__fetch_value('mass')
|
return self.fetch_value('mass')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
2
spatz/observer/__init__.py
Normal file
2
spatz/observer/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
from spatz.sensors import Sensor
|
||||||
|
from spatz.observer.observer import Observer
|
33
spatz/observer/observer.py
Normal file
33
spatz/observer/observer.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
from typing import Any, List, Dict, AnyStr
|
||||||
|
from numpy.typing import ArrayLike
|
||||||
|
|
||||||
|
from spatz.dataset import Dataset
|
||||||
|
from spatz.logger import Logger
|
||||||
|
from spatz.transforms import Transform
|
||||||
|
|
||||||
|
|
||||||
|
class Observer:
|
||||||
|
def __init__(self, dataset: Dataset, logger: Logger, attributes: List[str]):
|
||||||
|
self._dataset = dataset
|
||||||
|
self._logger = logger
|
||||||
|
self.__attrs = attributes
|
||||||
|
|
||||||
|
def _get_name(self) -> AnyStr:
|
||||||
|
return 'general'
|
||||||
|
|
||||||
|
def set_dataset(self, dataset: Dataset):
|
||||||
|
self._dataset = dataset
|
||||||
|
|
||||||
|
def set_logger(self, logger: Logger):
|
||||||
|
self._logger = logger
|
||||||
|
|
||||||
|
def _log(self, name: AnyStr, value: Any):
|
||||||
|
self._logger.write(name, value, self._get_name())
|
||||||
|
|
||||||
|
def __call__(self) -> ArrayLike:
|
||||||
|
data = self._dataset.fetch_values(self.__attrs)
|
||||||
|
|
||||||
|
for attrib, value in zip(self.__attrs, data):
|
||||||
|
self._log(attrib, value)
|
||||||
|
|
||||||
|
return data
|
@ -22,6 +22,9 @@ class Sensor:
|
|||||||
def set_logger(self, logger: Logger):
|
def set_logger(self, logger: Logger):
|
||||||
self._logger = logger
|
self._logger = logger
|
||||||
|
|
||||||
|
def set_transforms(self, transforms: List[Transform]):
|
||||||
|
self._transforms = transforms
|
||||||
|
|
||||||
def _log(self, name: AnyStr, value: Any):
|
def _log(self, name: AnyStr, value: Any):
|
||||||
self._logger.write(name, value, self._get_name())
|
self._logger.write(name, value, self._get_name())
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ from spatz.sensors import Sensor
|
|||||||
from spatz.dataset import Dataset
|
from spatz.dataset import Dataset
|
||||||
from spatz.logger import Logger
|
from spatz.logger import Logger
|
||||||
from spatz.sensors import Sensor
|
from spatz.sensors import Sensor
|
||||||
|
from spatz.observer import Observer
|
||||||
|
|
||||||
|
|
||||||
class UniformTimeSteps:
|
class UniformTimeSteps:
|
||||||
@ -89,11 +90,34 @@ class Simulation:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def add_sensor(self, sensor, *args, **kwargs) -> Sensor:
|
def add_sensor(self, sensor, *args, **kwargs) -> Sensor:
|
||||||
|
"""Register a new sensor for this simulation. A registered sensor can be called like a function and returns
|
||||||
|
the current measurements. The class' constructor arguments have to be given aswell.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sensor (_type_): A subclass of the abstract Sensor class.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Sensor: Returns an object of the provided sensor subclass.
|
||||||
|
"""
|
||||||
assert issubclass(sensor, Sensor), "Expected a subclass of Sensor."
|
assert issubclass(sensor, Sensor), "Expected a subclass of Sensor."
|
||||||
|
|
||||||
self.__sensors.append(sensor(self.__dataset, self.__logger, *args, **kwargs))
|
self.__sensors.append(sensor(self.__dataset, self.__logger, *args, **kwargs))
|
||||||
|
|
||||||
return self.__sensors[-1]
|
return self.__sensors[-1]
|
||||||
|
|
||||||
|
def add_observer(self, attributes: List[str]) -> Observer:
|
||||||
|
"""Register a new observer for this simulation observing the provided attributes.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
attributes (List[str]): A list of strings describing the attributes to observe.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Observer: An observer object which can be called like a function to obtain the desired data.
|
||||||
|
"""
|
||||||
|
assert len(attributes) != 0, "Observed attributes list must be nonempty."
|
||||||
|
|
||||||
|
self.__sensors.append(Observer(self.__dataset, self.__logger, attributes))
|
||||||
|
|
||||||
|
return self.__sensors[-1]
|
||||||
|
|
||||||
|
|
@ -152,6 +152,9 @@ def preprocess_file(path):
|
|||||||
df = compute_omegas(df)
|
df = compute_omegas(df)
|
||||||
df = preprocess_rotations(df)
|
df = preprocess_rotations(df)
|
||||||
|
|
||||||
|
# Set the altitude to meters
|
||||||
|
df['altitude'] *= 1000
|
||||||
|
|
||||||
renaming = {
|
renaming = {
|
||||||
'sonic_velocity': 'speedofsound',
|
'sonic_velocity': 'speedofsound',
|
||||||
'Time': 'time',
|
'Time': 'time',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user