Skip to content

Commit 14d199d

Browse files
aZira371Gui-FernandesBR
authored andcommitted
BUG: correction of singularity bug during align on vectors in weathercocking
- BUG: implemented a dot product check to ensure that singularity bug is avoided when rocket body and wind velocity are anti aligned to make rocket statically stable (in u_dot_generalized_3dof) - MNT: removed redundant double assignment of e0 and w0 vectors within u_dot_generalized_3dof - MNT: format correction to test_flight_3dof.py
1 parent 5ff03cd commit 14d199d

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

rocketpy/simulation/flight.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,8 +1905,6 @@ def u_dot_generalized_3dof(self, t, u, post_processing=False):
19051905

19061906
# Dynamics
19071907
v_dot = K @ (total_force / total_mass)
1908-
e_dot = [0, 0, 0, 0] # Euler derivatives unused in 3DOF
1909-
w_dot = [0, 0, 0] # No angular dynamics in 3DOF
19101908
r_dot = [vx, vy, vz]
19111909
# Weathercocking: evolve body axis direction toward relative wind
19121910
# The body z-axis (attitude vector) should align with -freestream_velocity
@@ -1964,9 +1962,40 @@ def u_dot_generalized_3dof(self, t, u, post_processing=False):
19641962
e_dot = [e0_dot, e1_dot, e2_dot, e3_dot]
19651963
w_dot = [0, 0, 0] # No angular acceleration in 3DOF model
19661964
else:
1967-
# Already aligned or anti-aligned
1968-
e_dot = [0, 0, 0, 0]
1969-
w_dot = [0, 0, 0]
1965+
# Check if aligned or anti-aligned using dot product
1966+
dot = body_z_inertial @ desired_direction # Vector dot product
1967+
if dot > 0.999: # Aligned
1968+
e_dot = [0, 0, 0, 0]
1969+
w_dot = [0, 0, 0]
1970+
elif dot < -0.999: # Anti-aligned
1971+
# Choose an arbitrary perpendicular axis
1972+
# Try [1,0,0] unless body_z_inertial is parallel to it
1973+
x_axis = Vector([1.0, 0.0, 0.0])
1974+
perp_axis = body_z_inertial ^ x_axis
1975+
if abs(perp_axis) < 1e-6:
1976+
# If parallel, use y axis
1977+
y_axis = Vector([0.0, 1.0, 0.0])
1978+
perp_axis = body_z_inertial ^ y_axis
1979+
rotation_axis = perp_axis.normalized()
1980+
# 180 degree rotation: sin(angle) = 1
1981+
omega_mag = self.weathercock_coeff * 1.0
1982+
omega_inertial = rotation_axis * omega_mag
1983+
omega_body = Kt @ omega_inertial
1984+
omega1_wc, omega2_wc, omega3_wc = (
1985+
omega_body.x,
1986+
omega_body.y,
1987+
omega_body.z,
1988+
)
1989+
e0_dot = 0.5 * (-omega1_wc * e1 - omega2_wc * e2 - omega3_wc * e3)
1990+
e1_dot = 0.5 * (omega1_wc * e0 + omega3_wc * e2 - omega2_wc * e3)
1991+
e2_dot = 0.5 * (omega2_wc * e0 - omega3_wc * e1 + omega1_wc * e3)
1992+
e3_dot = 0.5 * (omega3_wc * e0 + omega2_wc * e1 - omega1_wc * e2)
1993+
e_dot = [e0_dot, e1_dot, e2_dot, e3_dot]
1994+
w_dot = [0, 0, 0]
1995+
else:
1996+
# Vectors are nearly aligned, treat as aligned
1997+
e_dot = [0, 0, 0, 0]
1998+
w_dot = [0, 0, 0]
19701999
else:
19712000
# No weathercocking or negligible freestream speed
19722001
e_dot = [0, 0, 0, 0]

tests/unit/simulation/test_flight_3dof.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,6 @@ def test_weathercock_aligned_no_evolution(example_plain_env, point_mass_rocket):
263263
# With alignment, quaternion derivatives should be very small
264264
e_dot = result[6:10]
265265
e_dot_magnitude = sum(ed**2 for ed in e_dot) ** 0.5
266-
assert e_dot_magnitude < 1e-8, "Quaternion derivatives should be very small when aligned"
266+
assert e_dot_magnitude < 1e-8, (
267+
"Quaternion derivatives should be very small when aligned"
268+
)

0 commit comments

Comments
 (0)