### Install AHRS from GitHub Repository Source: https://github.com/mayitzin/ahrs/blob/master/README.md This snippet shows how to clone the AHRS repository from GitHub and install it locally. This method ensures you get the latest version of the package. ```shell git clone https://github.com/Mayitzin/ahrs.git cd ahrs python -m pip install . ``` -------------------------------- ### Notebook Setup and Tool Imports Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes the plotting environment for interactive visualizations and imports necessary libraries including NumPy and custom plotting tools from 'tools.py'. Requires 'matplotlib' and 'ipympl'. ```python # Use widgets %matplotlib widget # Import NumPy import numpy as np # Seed random generator GENERATOR = np.random.default_rng(42) # Import plotting tools from tools import plot from tools import plot3 ``` -------------------------------- ### Initialize and View QuaternionArray Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Creates a QuaternionArray object, which handles multiple quaternions. This example initializes an array with slight perturbations from a base quaternion and displays its contents. ```python Quaternions = ahrs.QuaternionArray(np.tile([1., 0., 0., np.sqrt(2)-1], (5, 1)) + np.random.randn(5, 4)*0.05) Quaternions.view() ``` -------------------------------- ### Install AHRS using pip Source: https://github.com/mayitzin/ahrs/blob/master/README.md This command installs the stable release of the AHRS package from PyPI using pip. This is a convenient way to get the latest stable version. ```shell pip install ahrs ``` -------------------------------- ### Import QUEST Estimator in Python Source: https://github.com/mayitzin/ahrs/blob/master/docs/source/filters.rst Demonstrates how to import the QUEST attitude estimator from the AHRS filters module. This is a basic example of accessing the library's functionalities. ```python from ahrs.filters import QUEST ``` -------------------------------- ### Complementary Filter for Sensor Fusion (IMU Mode) Source: https://context7.com/mayitzin/ahrs/llms.txt Provides an example of implementing a Complementary filter for sensor fusion using gyroscope and accelerometer data. Allows adjustment of the gain parameter to prioritize gyro or accel readings. ```python from ahrs.filters import Complementary import numpy as np # Generate sample data num_samples = 1000 gyro_data = np.random.randn(num_samples, 3) * 0.05 # rad/s acc_data = np.random.randn(num_samples, 3) * 0.5 + [0, 0, 9.81] mag_data = np.random.randn(num_samples, 3) * 5 + [20, 0, 40] # IMU mode (gyro + accel) comp = Complementary( gyr=gyro_data, acc=acc_data, frequency=100.0, gain=0.9 # 0.0-1.0: higher values trust gyro more ) print(comp.Q.shape) # (1000, 4) ``` -------------------------------- ### Initialize Madgwick Filter for Incremental Updates (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes the Madgwick filter with a specified initial orientation. This setup is used when processing sensor data incrementally, rather than in a single batch. The initial orientation is provided as a quaternion. ```python initial_quaternion = [1., 0., 0., 0.] madgwick = ahrs.filters.Madgwick(q0=initial_quaternion) ``` -------------------------------- ### Create DCM from Axis-Angle Representation in Python Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Explains and demonstrates the creation of a DCM object using the Axis-Angle representation. It shows how to specify the axis of rotation (a normalized 3D vector) and the angle of rotation in radians. The example also highlights that the input axis vector will be normalized if it's not already. ```python rotation = ahrs.DCM(axang=([0, 0, 1], 45*ahrs.DEG2RAD)) rotation.view() ``` ```python ahrs.DCM(axang=([0, 0, 2], 45*ahrs.DEG2RAD)) ``` -------------------------------- ### Access Additional Sensor Properties and Use for Filter Testing Source: https://context7.com/mayitzin/ahrs/llms.txt Details accessing advanced properties of the generated sensor data, such as frequency, angular positions, angular velocity, biases, and reference vectors. Also shows an example of using generated data to test the Madgwick filter and comparing results. ```python # Access additional properties print(sensors.frequency) # 100.0 Hz print(sensors.angular_positions.shape) # (1000, 3) Euler angles print(sensors.ang_vel.shape) # (1000, 3) Angular velocity print(sensors.biases_gyroscopes) # Constant gyro biases print(sensors.reference_gravitational_vector) # [0, 0, 9.81] print(sensors.reference_magnetic_vector) # Earth's magnetic field # Use generated data for filter testing from ahrs.filters import Madgwick madgwick = Madgwick( gyr=sensors.gyroscopes, acc=sensors.accelerometers, mag=sensors.magnetometers, frequency=sensors.frequency ) estimated_Q = madgwick.Q # Compare with ground truth from ahrs.utils.metrics import quat_geodesic_distance errors = [quat_geodesic_distance(sensors.quaternions[i], estimated_Q[i]) for i in range(len(estimated_Q))] print(f"Mean error: {np.mean(errors):.4f} rad") ``` -------------------------------- ### Quaternion Class Overview Source: https://github.com/mayitzin/ahrs/blob/master/docs/source/quaternion/classQuaternion.rst This section provides an overview of the Quaternion class, detailing its attributes and available methods for various quaternion manipulations. ```APIDOC ## Quaternion Class ### Description Represents a quaternion, a mathematical entity used for rotations in 3D space. This class provides attributes for accessing quaternion components and methods for performing quaternion operations. ### Attributes - **w** (float) - The real part of the quaternion. - **x** (float) - The first imaginary component of the quaternion. - **y** (float) - The second imaginary component of the quaternion. - **z** (float) - The third imaginary component of the quaternion. - **v** (tuple) - The vector part (x, y, z) of the quaternion. - **conjugate** (Quaternion) - Returns the conjugate of the quaternion. - **conj** (Quaternion) - Alias for conjugate. - **inverse** (Quaternion) - Returns the inverse of the quaternion. - **inv** (Quaternion) - Alias for inverse. - **exponential** (Quaternion) - Returns the exponential of the quaternion. - **exp** (Quaternion) - Alias for exponential. - **logarithm** (Quaternion) - Returns the logarithm of the quaternion. - **log** (Quaternion) - Alias for logarithm. ### Methods - **is_pure()** (bool) - Checks if the quaternion has no real part (i.e., is purely imaginary). - **is_real()** (bool) - Checks if the quaternion has no imaginary part. - **is_versor()** (bool) - Checks if the quaternion is a unit quaternion (magnitude is 1). - **is_identity()** (bool) - Checks if the quaternion represents the identity rotation (1 + 0i + 0j + 0k). - **normalize()** (Quaternion) - Returns a normalized version of the quaternion (unit quaternion). - **product(other)** (Quaternion) - Multiplies this quaternion by another quaternion. - **mult_L(other)** (Quaternion) - Performs left-multiplication with another quaternion. - **mult_R(other)** (Quaternion) - Performs right-multiplication with another quaternion. - **rotate(vector)** (ndarray) - Rotates a 3D vector by this quaternion. - **to_array()** (ndarray) - Converts the quaternion to a NumPy array [w, x, y, z]. - **to_list()** (list) - Converts the quaternion to a list [w, x, y, z]. - **to_axang()** (tuple) - Converts the quaternion to an axis-angle representation (axis, angle). - **to_angles()** (tuple) - Converts the quaternion to Euler angles (roll, pitch, yaw). - **to_DCM()** (ndarray) - Converts the quaternion to a Direction Cosine Matrix (DCM). - **from_DCM(matrix)** (Quaternion) - Creates a quaternion from a Direction Cosine Matrix. - **from_rpy(roll, pitch, yaw)** (Quaternion) - Creates a quaternion from roll, pitch, and yaw angles. - **from_angles(angles)** (Quaternion) - Creates a quaternion from Euler angles. - **ode(dt)** (Quaternion) - Propagates the quaternion by a small time step `dt` using its angular velocity. - **random()** (Quaternion) - Creates a random quaternion. ``` -------------------------------- ### Describe DCM Object Methods in Python Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Demonstrates how to use the `describe_methods` utility function (assumed to be from a 'tools' module) to list all methods of a DCM object along with their first descriptive line from the docstring. This is useful for quickly understanding the available functionalities. ```python # List all DCM methods and the first descriptive line from each docstring from tools import describe_methods describe_methods(orientation) ``` -------------------------------- ### Initialize Madgwick Filter with Advanced Parameters - Python Source: https://github.com/mayitzin/ahrs/blob/master/README.md Initializes the Madgwick attitude estimator with accelerometer, gyroscope, and magnetometer data, along with optional gain and frequency parameters for finer tuning. This allows for more precise attitude estimation. ```python attitude = ahrs.filters.Madgwick(acc=acc_data, gyr=gyro_data, mag=mag_data, gain=0.1, frequency=100.0) ``` -------------------------------- ### Create Quaternions from Euler Angles and Randomly Source: https://context7.com/mayitzin/ahrs/llms.txt Demonstrates creating QuaternionArray objects from roll-pitch-yaw angles and generating random quaternions. Requires the numpy library. ```python rpy_angles = np.random.randn(50, 3) * 0.5 # 50 sets of roll-pitch-yaw Q2 = QuaternionArray(rpy=rpy_angles) # Create N random quaternions Q3 = QuaternionArray(5) # 5 random unit quaternions ``` -------------------------------- ### Initialize Quaternion from Identity Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Demonstrates how to create an identity quaternion using the Quaternion class constructor without any arguments. The identity quaternion is the base unit quaternion. ```python q = ahrs.Quaternion() q.view() ``` -------------------------------- ### Initialize Quaternion from Different Formats Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Shows various ways to initialize a Quaternion object: from a random value, a 4-element array, a 3-element array (creating a pure quaternion), a Direction Cosine Matrix (DCM), and Roll-Pitch-Yaw (RPY) angles. Note that quaternion inputs are always normalized. ```python print("Random quaternion:\n", ahrs.Quaternion(random=True)) print("4-element array:\n", ahrs.Quaternion([1., -2., 3., -4])) print("3-element array:\n", ahrs.Quaternion([1., -2., 3.])) print("From DCM:\n", ahrs.Quaternion(dcm=np.array([[np.sqrt(2)/2, -np.sqrt(2)/2, 0], [np.sqrt(2)/2, np.sqrt(2)/2, 0], [0, 0, 1]]))) print("Roll-pitch-yaw angles:\n", ahrs.Quaternion(rpy=np.array([30.0, 20.0, 10.0])*ahrs.DEG2RAD)) ``` -------------------------------- ### Extended Kalman Filter (EKF) for Orientation Estimation (Python) Source: https://context7.com/mayitzin/ahrs/llms.txt Shows how to implement the Extended Kalman Filter for probabilistic orientation estimation. This snippet covers loading sensor data, batch estimation, and real-time incremental updates, including noise parameter configuration. ```python from ahrs.filters import EKF import numpy as np # Load sensor data # Assuming gyro_data, acc_data, mag_data are loaded numpy arrays # gyro_data = np.load('gyroscopes.npy') # (N, 3) rad/s # acc_data = np.load('accelerometers.npy') # (N, 3) m/s² # mag_data = np.load('magnetometers.npy') # (N, 3) μT # Estimate orientations with EKF ekf = EKF( gyr=gyro_data, acc=acc_data, mag=mag_data, frequency=100.0, noises=[0.3**2, 0.5**2, 0.8**2] # Measurement noise variances ) orientations = ekf.Q # (N, 4) quaternions # Real-time incremental updates ekf = EKF(frequency=100.0) Q = np.zeros((len(gyro_data), 4)) Q[0] = [1.0, 0.0, 0.0, 0.0] for t in range(1, len(gyro_data)): Q[t] = ekf.update( q=Q[t-1], gyr=gyro_data[t], acc=acc_data[t], mag=mag_data[t] ) # Access covariance matrices for uncertainty quantification print(ekf.P) # State covariance matrix ``` -------------------------------- ### Initialize Madgwick Filter with Basic Data - Python Source: https://github.com/mayitzin/ahrs/blob/master/README.md Initializes the Madgwick attitude estimator using accelerometer and gyroscope data. This is a fundamental step for attitude estimation. The output is a quaternion representing the estimated attitude. ```python attitude = ahrs.filters.Madgwick(acc=acc_data, gyr=gyro_data) print(attitude.Q.shape) ``` -------------------------------- ### Initialize WMM with Custom Parameters (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes the WMM class with a specific date, latitude, longitude, and height above sea level. Note that height is expected in kilometers. This allows for magnetic field calculations at any point in time and location. ```python import datetime # 34.14 degrees North, 118.35 degrees West, 500 m above sea level (WMM uses km), on the 26th October 2015 wmm = ahrs.utils.WMM(datetime.date(2015, 10, 26), latitude=34.14160468409308, longitude=-118.34978138071212, height=0.5) wmm.magnetic_elements ``` -------------------------------- ### Initialize WMM Class (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes the World Magnetic Model (WMM) class to access Earth's magnetic field data. By default, it uses current date and Munich's location. Coefficients are included in the package. ```python wmm = ahrs.utils.WMM() ``` -------------------------------- ### Quaternion Averaging (Markley's Method and Weighted Average) Source: https://context7.com/mayitzin/ahrs/llms.txt Demonstrates two methods for averaging quaternions: Markley's method for a simple average and a weighted average using provided weights. The results are single quaternion objects. ```python # Average quaternion (Markley's method) Q_avg = Q.average() # Single quaternion print(Q_avg) # (4,) # Weighted average weights = np.exp(-np.arange(100) * 0.05) # Exponential decay Q_weighted = Q.average(weights=weights) ``` -------------------------------- ### Access Quaternion Components and Properties Source: https://context7.com/mayitzin/ahrs/llms.txt Shows how to access the scalar (w) and vector (x, y, z) components of quaternions in a vectorized manner. Also demonstrates checking properties like purity, versor, and identity using boolean arrays. ```python # Access components (vectorized) print(Q.w.shape) # (100,) - all scalar parts print(Q.x.shape) # (100,) - all x components print(Q.v.shape) # (100, 3) - all vector parts # Check properties (returns arrays of booleans) print(Q.is_pure()) # Array of True/False for each quaternion print(Q.is_versor()) # Check if all are unit quaternions print(Q.is_identity()) ``` -------------------------------- ### Generate Synthetic Sensor Data (IMU/MARG) Source: https://context7.com/mayitzin/ahrs/llms.txt Shows how to generate synthetic sensor data including gyroscopes, accelerometers, magnetometers, and true orientations. Allows customization of sample count, frequency, noise levels, and units. ```python from ahrs.utils import Sensors import numpy as np # Generate synthetic sensor data with default random motion sensors = Sensors(num_samples=1000, freq=100.0) # 1000 samples at 100 Hz # Access generated data print(sensors.gyroscopes.shape) # (1000, 3) rad/s print(sensors.accelerometers.shape) # (1000, 3) m/s² print(sensors.magnetometers.shape) # (1000, 3) nT print(sensors.quaternions.shape) # (1000, 4) true orientations print(sensors.rotations.shape) # (1000, 3, 3) rotation matrices # Sensor data with custom noise levels sensors_noisy = Sensors( num_samples=1000, freq=100.0, gyr_noise=0.05, # Gyro noise std dev (rad/s) acc_noise=0.1, # Accel noise std dev (m/s²) mag_noise=1.0 # Mag noise std dev (nT) ) # Generate data in degrees (default is radians) sensors_deg = Sensors(num_samples=1000, in_degrees=True) print(sensors_deg.gyroscopes[0]) # Output in deg/s # Normalized magnetometer output sensors_norm = Sensors(num_samples=1000, normalized_mag=True) print(np.linalg.norm(sensors_norm.magnetometers[0])) # 1.0 # Use existing quaternions to generate sensor data from ahrs import QuaternionArray known_orientations = QuaternionArray(500) # 500 random orientations sensors_from_quat = Sensors(quaternions=known_orientations, freq=200.0) ``` -------------------------------- ### Complementary Filter for Orientation Estimation (Python) Source: https://context7.com/mayitzin/ahrs/llms.txt Demonstrates how to use the Complementary filter for sensor fusion to estimate orientation from gyroscope, accelerometer, and magnetometer data. It covers MARG mode, incremental updates, and custom initial orientations. ```python from ahrs.filters import Complementary import numpy as np # Assuming gyro_data, acc_data, mag_data, num_samples are pre-defined # MARG mode (gyro + accel + mag) comp_marg = Complementary( gyr=gyro_data, acc=acc_data, mag=mag_data, frequency=100.0, gain=0.95 # Higher gain for MARG ) # Incremental update comp = Complementary(frequency=100.0, gain=0.9) Q = np.zeros((num_samples, 4)) Q[0] = [1.0, 0.0, 0.0, 0.0] for t in range(1, num_samples): Q[t] = comp.updateIMU(Q[t-1], gyr=gyro_data[t], acc=acc_data[t]) # With magnetometer for t in range(1, num_samples): Q[t] = comp.updateMARG( Q[t-1], gyr=gyro_data[t], acc=acc_data[t], mag=mag_data[t] ) # Custom initial orientation q0 = np.array([0.9239, 0.3827, 0.0, 0.0]) comp_custom = Complementary( gyr=gyro_data, acc=acc_data, frequency=100.0, q0=q0 ) ``` -------------------------------- ### Initialize Quaternion from RPY and Convert to DCM Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes a quaternion representing a 45-degree yaw rotation and then converts it to its equivalent Direction Cosine Matrix (DCM). This showcases the conversion from RPY angles to DCM via quaternions. ```python q = ahrs.Quaternion(rpy=([0, 0, 45*ahrs.DEG2RAD])) q.view() q.to_DCM() ``` -------------------------------- ### QuaternionArray Class Source: https://github.com/mayitzin/ahrs/blob/master/docs/source/quaternion/classQuaternionArray.rst Provides an overview of the QuaternionArray class, its attributes, and related functionalities for handling arrays of quaternions. ```APIDOC ## QuaternionArray Class ### Description Represents an array of quaternions, offering various attributes and methods for quaternion operations. ### Attributes - **w** (array) - The real part of the quaternions. - **x** (array) - The x-component of the imaginary part. - **y** (array) - The y-component of the imaginary part. - **z** (array) - The z-component of the imaginary part. - **v** (array) - The vector part of the quaternions. - **conjugate** (QuaternionArray) - Returns the conjugate of the quaternion array. - **conj** (QuaternionArray) - Alias for conjugate. - **is_pure** (array of bool) - Checks if quaternions are purely imaginary. - **is_real** (array of bool) - Checks if quaternions are purely real. - **is_versor** (array of bool) - Checks if quaternions are unit quaternions. - **is_identity** (array of bool) - Checks if quaternions are identity quaternions. ### Methods - **average** (Quaternion) - Computes the average of the quaternion array. - **remove_jumps** (QuaternionArray) - Removes jumps in the quaternion array. - **rotate_by** (QuaternionArray) - Rotates the quaternion array by another quaternion array. - **angular_velocities** (array) - Computes the angular velocities from the quaternion array. - **slerp_nan** (QuaternionArray) - Performs spherical linear interpolation, handling NaN values. ``` -------------------------------- ### Quaternion Conjugation, Conversion to Rotation Matrices and Euler Angles Source: https://context7.com/mayitzin/ahrs/llms.txt Illustrates how to compute the conjugate of quaternions, convert them to Direction Cosine Matrices (rotation matrices), and extract Euler angles (roll, pitch, yaw). ```python # Conjugate of all quaternions Q_conj = Q.conjugate() # (100, 4) # Convert to rotation matrices R = Q.to_DCM() # (100, 3, 3) - 100 rotation matrices print(R.shape) # Convert to Euler angles angles = Q.to_angles() # (100, 3) - roll, pitch, yaw print(angles.shape) ``` -------------------------------- ### Generate Synthetic MARG Sensor Data Source: https://github.com/mayitzin/ahrs/blob/master/README.md This Python code demonstrates how to use the `Sensors` class to generate synthetic MARG (Magnetic, Angular Rate, and Gravity) sensor data. It shows how to instantiate the class and access the shapes of the generated gyroscope, accelerometer, magnetometer, and quaternion data. ```python from ahrs.sensors import Sensors sensors = Sensors(num_samples=1000) print(f"Gyroscopes shape: {sensors.gyroscopes.shape}") print(f"Accelerometers shape: {sensors.accelerometers.shape}") print(f"Magnetometers shape: {sensors.magnetometers.shape}") print(f"Quaternions shape: {sensors.quaternions.shape}") ``` -------------------------------- ### Interpolate NaN Values and SLERP Between Quaternions Source: https://context7.com/mayitzin/ahrs/llms.txt Demonstrates filling NaN values within a QuaternionArray using Spherical Linear Interpolation (SLERP) and performing SLERP between two specific quaternions over a series of time steps. ```python # Interpolate over NaN values using SLERP Q[40:45] = np.nan Q.slerp_nan(inplace=True) # Fill NaN values by interpolation # SLERP between two quaternions from ahrs.common.quaternion import slerp q1 = np.array([1.0, 0.0, 0.0, 0.0]) q2 = np.array([0.7071, 0.7071, 0.0, 0.0]) t_values = np.linspace(0, 1, 10) # 10 steps from q1 to q2 Q_interp = slerp(q1, q2, t_values) print(Q_interp.shape) # (10, 4) ``` -------------------------------- ### Simulate IMU Sensor Data from Orientations (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Simulates IMU sensor data including gyroscope, accelerometer, and magnetometer readings from a given set of quaternions representing poses. It synthesizes these signals assuming a continuous recording. The output includes the simulated sensor data and metadata like sampling frequency and number of samples. ```python sensors = ahrs.Sensors(Quaternions) print("Gyroscopes:\n", sensors.gyroscopes) print("Accelerometers:\n", sensors.accelerometers) print("Magnetometers:\n", sensors.magnetometers) print(f"Sampling frequency: {sensors.frequency:.2f} Hz") print(f"Number of samples: {sensors.num_samples:d}") ``` -------------------------------- ### Compare Estimated vs. True Orientations (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Plots the true quaternions against the quaternions estimated by the Madgwick filter. This visualization helps assess the performance of the attitude estimation. ```python plot(simulated_data.quaternions, madgwick.Q) ``` -------------------------------- ### Initialize Global Frame with DCM Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Creates a Direction Cosine Matrix (DCM) representing the global reference frame, which is initialized as an identity matrix. This is useful for establishing a base orientation in 3D space. It also demonstrates visualization using 'plot3'. ```python global_frame = ahrs.DCM() # An empty DCM is initialized as the global frame print("Global frame:") print(global_frame.view()) plot3(frames=global_frame) ``` -------------------------------- ### Describe AHRS Metrics Functions Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb This snippet uses the `describe_functions` utility to list and describe the available metric functions within the `ahrs.utils.metrics` module. It helps in understanding the capabilities for analyzing estimated attitudes. ```python from tools import describe_functions describe_functions(ahrs.utils.metrics) ``` -------------------------------- ### Rotate Quaternions and Compute Angular Velocities Source: https://context7.com/mayitzin/ahrs/llms.txt Shows how to rotate a set of quaternions by another quaternion and how to compute the angular velocities between consecutive quaternions in a sequence given a time step. ```python # Rotate all quaternions by another quaternion q_rotation = np.array([0.9239, 0.3827, 0.0, 0.0]) Q_rotated = Q.rotate_by(q_rotation) # (100, 4) # Compute angular velocities between quaternions dt = 0.01 # 100 Hz sampling angular_vel = Q.angular_velocities(dt) # (99, 3) rad/s print(angular_vel.shape) ``` -------------------------------- ### Direction Cosine Matrix (DCM) Operations and Conversions (Python) Source: https://context7.com/mayitzin/ahrs/llms.txt Illustrates the creation and manipulation of Direction Cosine Matrices (DCMs) for representing 3D rotations. This includes conversion from Euler angles, quaternions, and axis-angle representations, as well as matrix operations and vector rotations. ```python from ahrs import DCM import numpy as np # Create DCM from Euler angles (in degrees by default) dcm = DCM(rpy=[10.0, 20.0, 30.0]) # roll, pitch, yaw print(dcm) # 3x3 rotation matrix print(dcm.shape) # (3, 3) # Create from quaternion q = np.array([0.9239, 0.3827, 0.0, 0.0]) dcm_from_q = DCM(q=q) # Create from axis-angle axis = np.array([0.0, 0.0, 1.0]) # Z-axis angle = np.pi / 4 # 45 degrees in radians dcm_from_axang = DCM(ax=axis, ang=angle) # Identity matrix dcm_identity = DCM() print(dcm_identity.isIdentity()) # True # Check if valid rotation matrix (in SO(3)) print(dcm.isSO3()) # True # Conversions quaternion = dcm.to_quaternion() # [w, x, y, z] euler_angles = dcm.to_angles() # [roll, pitch, yaw] in radians axis_angle = dcm.to_axisangle() # (axis, angle) # Matrix operations dcm_transpose = dcm.T # Transpose (same as inverse for rotation) dcm_inv = dcm.inv # Inverse rotation # Compose rotations dcm2 = DCM(rpy=[5.0, -10.0, 15.0]) dcm_composed = dcm @ dcm2 # Matrix multiplication # Rotate a vector v = np.array([1.0, 0.0, 0.0]) v_rotated = dcm @ v print(v_rotated) ``` -------------------------------- ### Create DCM from Euler Angles Tuple in Python Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Shows a simplified method to create a DCM object by directly providing Euler angles as a tuple to the constructor. The 'zyx' convention is used, and the angles are provided in radians after conversion from degrees. ```python orientation = ahrs.DCM( euler=('zyx', np.array([30.0, 20.0, 10.0])*ahrs.DEG2RAD) ) orientation.view() ``` -------------------------------- ### Create DCM from Valid Rotation Matrix Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Demonstrates the creation of a DCM object from a valid 3x3 orthogonal matrix in SO(3). This method allows initializing the DCM with a specific, pre-defined rotation. The matrix represents a rotation of approximately 45 degrees around the Z-axis. ```python valid_rotation = ahrs.DCM(np.array([[np.sqrt(2)/2, -np.sqrt(2)/2, 0], [np.sqrt(2)/2, np.sqrt(2)/2, 0], [0, 0, 1]])) valid_rotation.view() ``` -------------------------------- ### Orientation Metrics: Distance and Error Calculation (Python) Source: https://context7.com/mayitzin/ahrs/llms.txt Provides functions to compute various error metrics between estimated and true orientations, including geodesic, chordal, angular, and rotation errors. It also demonstrates batch comparison of quaternion arrays and Euclidean distance for Euler angles. ```python from ahrs.utils.metrics import quat_geodesic_distance, quat_chordal_distance from ahrs.utils.metrics import angular_distance, rotation_error, euclidean import numpy as np # Quaternion distances q_true = np.array([0.9239, 0.3827, 0.0, 0.0]) q_estimated = np.array([0.9063, 0.4226, 0.0, 0.0]) # Geodesic distance (angle of rotation difference) geo_dist = quat_geodesic_distance(q_true, q_estimated) print(f"Geodesic distance: {geo_dist:.4f} rad") # Chordal distance (Euclidean distance on unit sphere) chord_dist = quat_chordal_distance(q_true, q_estimated) print(f"Chordal distance: {chord_dist:.4f}") # Angular distance between rotation matrices R_true = np.array([[1, 0, 0], [0, 0.866, -0.5], [0, 0.5, 0.866]]) R_est = np.array([[1, 0, 0], [0, 0.9, -0.436], [0, 0.436, 0.9]]) ang_dist = angular_distance(R_true, R_est) print(f"Angular distance: {ang_dist:.4f} rad") # Rotation error (Frobenius norm) rot_error = rotation_error(R_true, R_est) print(f"Rotation error: {rot_error:.4f}") # Batch comparison of quaternion arrays Q_true = np.random.random((100, 4)) Q_estimated = np.random.random((100, 4)) # Normalize quaternions Q_true = Q_true / np.linalg.norm(Q_true, axis=1, keepdims=True) Q_estimated = Q_estimated / np.linalg.norm(Q_estimated, axis=1, keepdims=True) # Compute errors for each sample errors = np.array([quat_geodesic_distance(Q_true[i], Q_estimated[i]) for i in range(len(Q_true))]) print(f"Mean error: {errors.mean():.4f} rad") print(f"Max error: {errors.max():.4f} rad") print(f"RMSE: {np.sqrt((errors**2).mean()):.4f} rad") # Euler angle euclidean distanceeuler_true = np.array([0.1, 0.2, 0.3]) # roll, pitch, yaweuler_est = np.array([0.12, 0.19, 0.32]) euc_dist = euclidean(euler_true, euler_est) print(f"Euler angle distance: {euc_dist:.4f}") ``` -------------------------------- ### Create DCM from Elemental Rotations in Python Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Demonstrates creating Direction Cosine Matrices (DCMs) for individual rotations around the X, Y, and Z axes using the `ahrs.DCM` class. It also shows how to combine these rotations through matrix multiplication, following a right-to-left order (X -> Y -> Z). ```python print("Rotation of 10 degrees about X-axis:") print(ahrs.DCM(x=10.0*ahrs.DEG2RAD)) print("Rotation of 20 degrees about Y-axis:") print(ahrs.DCM(y=20.0*ahrs.DEG2RAD)) print("Rotation of 30 degrees about Z-axis:") print(ahrs.DCM(z=30.0*ahrs.DEG2RAD)) # New rotation matrix from products of rotations about X-, Y-, and Z-axis, respectively. # Order of matrix multiplication is right to left: x --> y --> z orientation = ahrs.DCM(z=30.0*ahrs.DEG2RAD) @ ahrs.DCM(y=20.0*ahrs.DEG2RAD) @ ahrs.DCM(x=10.0*ahrs.DEG2RAD) print(f"Rotation Matrix {type(orientation)}:") print(orientation) ``` -------------------------------- ### Import AHRS Package Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Imports the main 'ahrs' library, making its functionalities available for use in the current session. This is a fundamental step before utilizing any of the package's features. ```python import ahrs ``` -------------------------------- ### Access Individual Magnetic Elements (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Demonstrates how to access individual magnetic elements provided by the WMM class. This includes Northerly intensity (X), Easterly intensity (Y), and Vertical intensity (Z). ```python wmm.X ``` ```python wmm.Y ``` ```python wmm.Z ``` -------------------------------- ### Generate Random IMU Data for Attitude Estimation (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Generates random orientations and simulates corresponding IMU sensor data (gyroscope, accelerometer, magnetometer). This is useful for testing attitude estimation algorithms. The data can be generated with or without specified units (degrees/radians). ```python simulated_data = ahrs.Sensors(num_samples=1000, in_degrees=False) plot(simulated_data.quaternions, simulated_data.gyroscopes, simulated_data.accelerometers, simulated_data.magnetometers, ylabels = ['quaternions', 'rad/s', 'm/s^2', 'nT']) ``` -------------------------------- ### Attempt to Create DCM from Invalid Matrix Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Illustrates the error handling when attempting to create a DCM object from a matrix that is not a valid rotation matrix (i.e., not in SO(3)). This typically results in an exception or assertion error, indicating the input matrix does not represent a valid orientation. ```python invalid_rotation = ahrs.DCM(np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])) ``` -------------------------------- ### Initialize WGS for Gravitational Calculations Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes the World Geodetic System (WGS) class from the `ahrs.utils.wgs84` module. This object can then be used to compute gravitational forces based on latitude and height above sea level, using an ellipsoidal model. ```python wgs = ahrs.utils.WGS() ``` -------------------------------- ### Estimate Attitude using Madgwick Filter (Batch) (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Initializes and runs the Madgwick attitude estimation filter using simulated IMU sensor data (gyroscope, accelerometer, magnetometer) and the sampling frequency. It computes the full set of orientations from the provided data. ```python madgwick = ahrs.filters.Madgwick(gyr=simulated_data.gyroscopes, acc=simulated_data.accelerometers, mag=simulated_data.magnetometers, frequency=simulated_data.frequency) ``` -------------------------------- ### Retrieve All Magnetic Elements (Python) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Accesses all magnetic elements calculated by the WMM class for the initialized date and location. The elements include intensity (X, Y, Z, H, F), inclination (I), declination (D), and drift (GV). ```python wmm.magnetic_elements ``` -------------------------------- ### Madgwick Orientation Filter in Python Source: https://context7.com/mayitzin/ahrs/llms.txt Implements the Madgwick gradient descent-based orientation filter for IMU and MARG sensor arrays. It can estimate orientations in batch or sample-by-sample, supporting variable sampling rates. This filter fuses gyroscope, accelerometer, and optionally magnetometer data to compute quaternions. ```python import numpy as np from ahrs.filters import Madgwick # Generate or load sensor data num_samples = 1000 gyro_data = np.random.randn(num_samples, 3) * 0.1 # rad/s acc_data = np.random.randn(num_samples, 3) * 0.5 + np.array([0, 0, 9.81]) # m/s^2 mag_data = np.random.randn(num_samples, 3) * 5 + np.array([20, 0, 40]) # μT # Option 1: Estimate all orientations at once (IMU) madgwick = Madgwick(gyr=gyro_data, acc=acc_data, frequency=100.0, gain=0.033) print(madgwick.Q.shape) # (1000, 4) - quaternions for all samples # Option 2: Estimate all orientations at once (MARG with magnetometer) madgwick_marg = Madgwick( gyr=gyro_data, acc=acc_data, mag=mag_data, frequency=100.0, gain=0.041 # Default for MARG ) orientations = madgwick_marg.Q # (1000, 4) quaternions # Option 3: Update sample-by-sample for real-time applications madgwick = Madgwick(frequency=100.0, gain=0.033) Q = np.zeros((num_samples, 4)) Q[0] = [1.0, 0.0, 0.0, 0.0] # Initial identity quaternion for t in range(1, num_samples): Q[t] = madgwick.updateIMU(Q[t-1], gyr=gyro_data[t], acc=acc_data[t]) # Option 4: Variable sampling rate madgwick = Madgwick(gain=0.033) for t in range(1, num_samples): dt = compute_time_delta(t) # Your timing function Q[t] = madgwick.updateIMU(Q[t-1], gyr=gyro_data[t], acc=acc_data[t], dt=dt) # Access results print(f"Final orientation: {Q[-1]}") # [w, x, y, z] quaternion ``` -------------------------------- ### Calculate Mean Quaternion Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Demonstrates how to compute the average (mean) quaternion from a QuaternionArray using the `.average()` method. It also includes a warning about not using the inherited numpy `.mean()` method, which calculates a numerical mean. ```python # Mean Quaternion Quaternions.average() # WARNING: method `mean()` inherited from numpy.array # will compute the numerical mean over all array values, # which is NOT the Mean Quaternion ``` -------------------------------- ### QuaternionArray Class for Batch Processing in Python Source: https://context7.com/mayitzin/ahrs/llms.txt Handles arrays of quaternions, enabling vectorized operations for efficient batch processing of orientation data. It provides methods to manage collections of quaternions, suitable for applications involving multiple orientations or sequences. ```python from ahrs import QuaternionArray import numpy as np # Create array of quaternions Q = QuaternionArray(np.random.random((100, 4)) - 0.5) # 100 random quaternions print(Q.shape) # (100, 4) ``` -------------------------------- ### Log and Exponential Map Operations with AHRS (Python) Source: https://context7.com/mayitzin/ahrs/llms.txt This snippet illustrates the use of the logarithmic and exponential map functions from the `ahrs.common.dcm` module. It shows how to convert a rotation matrix to its skew-symmetric matrix representation (log map) and then back to a rotation matrix (exponential map). ```python from ahrs.common.dcm import log, exp # Assume dcm is a pre-defined direction cosine matrix dcm_matrix = np.array([[ 0.99, -0.01, 0.1 ], [ 0.01, 0.99, -0.1 ], [-0.1, 0.1, 0.99]]) log_R = log(dcm_matrix) # Skew-symmetric matrix R_recovered = exp(log_R) # Back to rotation matrix ``` -------------------------------- ### Calculate Quaternion Angle Difference (QAD) Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Calculates the Quaternion Angle Difference between simulated and estimated quaternions. This metric returns a value between 0 and pi for each quaternion pair, indicating their similarity. Input arrays must contain an equal number of quaternions. ```python qad_differences = ahrs.utils.metrics.qad(simulated_data.quaternions, Quaternions) ``` -------------------------------- ### Quaternion Class for 3D Rotations in Python Source: https://context7.com/mayitzin/ahrs/llms.txt Provides a Quaternion class for representing and manipulating 3D rotations. It supports creation from various formats (array, rotation matrix, Euler angles), quaternion arithmetic (addition, subtraction, Hamilton product), and conversions to other representations like rotation matrices and Euler angles. It also includes methods for rotating vectors. ```python from ahrs import Quaternion import numpy as np # Create quaternions q1 = Quaternion([1.0, 2.0, 3.0, 4.0]) # Automatically normalized print(q1) # Quaternion([0.18257419, 0.36514837, 0.54772256, 0.73029674]) # Access components print(f"Scalar: {q1.w}, Vector: {q1.v}") # w, x, y, z components print(f"x={q1.x}, y={q1.y}, z={q1.z}") # Create from rotation matrix R = np.array([[0.9254, 0.0180, 0.3785], [0.1632, 0.8826, -0.4410], [-0.3420, 0.4698, 0.8138]]) q2 = Quaternion(dcm=R) # Create from Euler angles (roll, pitch, yaw in radians) q3 = Quaternion(rpy=np.array([0.1745, 0.3491, 0.5236])) # 10°, 20°, 30° # Quaternion operations q4 = Quaternion([1.0, 0.0, 1.0, 0.0]) q5 = Quaternion([0.0, 1.0, 0.0, 1.0]) # Hamilton product (multiplication) q_prod = q4 * q5 print(q_prod) # array([-0.5, 0.5, 0.5, 0.5]) # Addition and subtraction (normalized results) q_sum = q4 + q5 q_diff = q4 - q5 # Conjugate and inverse print(q4.conjugate) # [w, -x, -y, -z] print(q4.inverse) # For unit quaternions: same as conjugate print(q4 * q4.inv) # Identity: [1, 0, 0, 0] # Exponential and logarithm q_exp = q4.exponential q_log = q4.logarithm # Power q_power = q4 ** 0.5 # Square root of rotation # Check quaternion properties print(q1.is_pure()) # False (w != 0) print(q1.is_versor()) # True (normalized) print(q1.is_identity()) # False # Conversions dcm = q1.to_DCM() # 3x3 rotation matrix angles = q1.to_angles() # Euler angles [roll, pitch, yaw] axis, angle = q1.to_axang() # Axis-angle representation # Rotate a vector v = np.array([1.0, 2.0, 3.0]) v_rotated = q1.rotate(v) print(v_rotated) # Vector rotated by quaternion # String representation print(str(q1)) # (0.1826 +0.3651i +0.5477j +0.7303k) ``` -------------------------------- ### Display WGS Ellipsoid Properties Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Iterates through and prints the properties of the WGS ellipsoid object. This helps in understanding the parameters defining the ellipsoidal model, such as semi-major axis, flattening, gravitational constant, and rotation rate. ```python wgs_properties = [x for x in dir(wgs) if not (hasattr(wgs.__getattribute__(x), '__call__') or x.startswith('__'))] max_column_width = len(max(wgs_properties, key=len)) for p in wgs_properties: print(f"{p:<{max_column_width}} {wgs.__getattribute__(p)}") ``` -------------------------------- ### Update Package Version using Hatch Source: https://github.com/mayitzin/ahrs/blob/master/README.md This shell command illustrates how to use the `hatch` tool to automatically update the version of the AHRS package. You can specify 'major', 'minor', or 'patch' to increment the corresponding version number. ```shell hatch version ``` -------------------------------- ### Visualize QuaternionArray Source: https://github.com/mayitzin/ahrs/blob/master/notebooks/Showcase.ipynb Visualizes an array of quaternions using a time-series plot. Each line in the plot represents a component (w, x, y, z) of the quaternions over the array elements. ```python plot(Quaternions) ```