Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Attention: The newest changes should be on top -->

### Fixed

- BUG: Correct the gravity sign an `Accelerometer` applies when `consider_gravity=True`. The gravitational field was added to the inertial acceleration instead of subtracted from it, so the sensor reported the negative of the proper acceleration along the vertical: one at rest read -g rather than +g. Recorded accelerometer data taken with `consider_gravity=True` changes sign in that term. [#1175](https://github.com/RocketPy-Team/RocketPy/pull/1175)
- BUG: Sample `StochasticFlight` inputs once per simulation [#1126](https://github.com/RocketPy-Team/RocketPy/pull/1126) [#1090](https://github.com/RocketPy-Team/RocketPy/issues/1090)
- BUG: Fix spurious `ValueError` from floating-point roundoff at exact tank depletion [#1166](https://github.com/RocketPy-Team/RocketPy/pull/1166)
- BUG: Draw each declared eccentricity once per simulation [#1168](https://github.com/RocketPy-Team/RocketPy/pull/1168)
Expand Down
12 changes: 8 additions & 4 deletions rocketpy/sensors/accelerometer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ class Accelerometer(InertialSensor):
Attributes
----------
consider_gravity : bool
Whether the sensor considers the effect of gravity on the acceleration.
Whether the sensor reports proper acceleration, which includes the
reaction to gravity, rather than the coordinate acceleration alone.
prints : _InertialSensorPrints
Object that contains the print functions for the sensor.
sampling_rate : float
Expand Down Expand Up @@ -166,8 +167,11 @@ def __init__(
Skewness of the sensor's axes in percentage. Default is 0, meaning
no cross-axis sensitivity is applied.
consider_gravity : bool, optional
If True, the sensor will consider the effect of gravity on the
acceleration. Default is False.
If True, the sensor reports proper acceleration, as a real
accelerometer does: the inertial acceleration less the local
gravitational field, so one at rest reads g along its up axis
rather than zero. If False it reports the coordinate acceleration,
which is zero at rest. Default is False.
name : str, optional
The name of the sensor. Default is "Accelerometer".
seed : int, optional
Expand Down Expand Up @@ -232,7 +236,7 @@ def measure(self, time, **kwargs):
gravity = (
Vector([0, 0, -gravity]) if self.consider_gravity else Vector([0, 0, 0])
)
inertial_acceleration = Vector(u_dot[3:6]) + gravity
inertial_acceleration = Vector(u_dot[3:6]) - gravity

# Vector from rocket cdm to sensor in rocket frame
r = relative_position
Expand Down
48 changes: 47 additions & 1 deletion tests/unit/sensors/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest
from pytest import approx

from rocketpy import Accelerometer
from rocketpy.mathutils.vector_matrix import Matrix, Vector
from rocketpy.tools import euler313_to_quaternions

Expand Down Expand Up @@ -272,7 +273,10 @@ def test_noisy_rotated_accelerometer(noisy_rotated_accelerometer, example_plain_

# calculate acceleration at sensor position in inertial frame
relative_position = Vector([0.4, 0.4, 1])
inertial_acceleration = Vector(U_DOT[3:6]) + Vector([0, 0, -GRAVITY])
# An accelerometer reports proper acceleration: the inertial acceleration
# less the local gravitational field. Gravity points down, so the term it
# contributes points up, which is why one sitting still reads +g, not 0.
inertial_acceleration = Vector(U_DOT[3:6]) - Vector([0, 0, -GRAVITY])
omega = Vector(U[10:13])
omega_dot = Vector(U_DOT[10:13])
acceleration = (
Expand Down Expand Up @@ -317,6 +321,48 @@ def test_noisy_rotated_accelerometer(noisy_rotated_accelerometer, example_plain_
assert noisy_rotated_accelerometer.measured_data[0][0] == TIME


def test_accelerometer_at_rest_reads_gravity_upward(example_plain_env):
"""An accelerometer standing still reads +g along its up axis, not zero.

The test above recomputes the expression under test, so a flipped gravity
term gets mirrored into agreement there instead of being caught. This one
says what the instrument does rather than how it is computed: it senses
the support force holding it up, so at rest it reports g upward. Reversing
the sign in ``Accelerometer.measure`` fails here.

Every noise, bias and drift parameter is left at its default, all of which
are zero, so the measurement is exact rather than bounded.
"""
at_rest = [0.0] * 13
at_rest[6] = 1.0 # identity attitude, so sensor axes are the inertial ones
still = [0.0] * 13
gravity = example_plain_env.gravity.get_value_opt(0)

sensing_gravity = Accelerometer(sampling_rate=100, consider_gravity=True)
sensing_gravity.measure(
time=0,
u=at_rest,
u_dot=still,
relative_position=Vector([0, 0, 0]),
environment=example_plain_env,
)

assert sensing_gravity.measurement == approx([0, 0, gravity], abs=1e-12)

# Without the flag the same sensor reports the coordinate acceleration, so
# the whole of what the flag contributes is that one upward g.
ignoring_gravity = Accelerometer(sampling_rate=100, consider_gravity=False)
ignoring_gravity.measure(
time=0,
u=at_rest,
u_dot=still,
relative_position=Vector([0, 0, 0]),
environment=example_plain_env,
)

assert ignoring_gravity.measurement == approx([0, 0, 0], abs=1e-12)


def test_noisy_rotated_gyroscope(noisy_rotated_gyroscope, example_plain_env):
"""Test the measure method of the Gyroscope class. Checks if saved
measurement is (wx,wy,wz) and if measured_data is [(t, (wx,wy,wz)), ...]
Expand Down
Loading