Skip to content

Commit e63a73f

Browse files
CopilotaZira371
andcommitted
Refactor: eliminate quaternion derivative code duplication in u_dot_generalized_3dof
Co-authored-by: aZira371 <[email protected]>
1 parent 7d17a00 commit e63a73f

File tree

1 file changed

+27
-48
lines changed

1 file changed

+27
-48
lines changed

rocketpy/simulation/flight.py

Lines changed: 27 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,79 +1929,58 @@ def u_dot_generalized_3dof(self, t, u, post_processing=False):
19291929
rotation_axis = body_z_inertial ^ desired_direction
19301930
rotation_axis_mag = abs(rotation_axis)
19311931

1932+
# Determine omega_body based on alignment state
1933+
omega_body = None
1934+
19321935
if rotation_axis_mag > 1e-8:
1933-
# Normalize rotation axis
1936+
# Normal case: compute angular velocity from misalignment
19341937
rotation_axis = rotation_axis / rotation_axis_mag
19351938

19361939
# The magnitude of the cross product of two unit vectors equals
19371940
# the sine of the angle between them
1938-
sin_angle = rotation_axis_mag
1939-
1940-
# Clamp sin_angle to valid range
1941-
sin_angle = min(1.0, max(-1.0, sin_angle))
1941+
sin_angle = min(1.0, max(-1.0, rotation_axis_mag))
19421942

19431943
# Angular velocity magnitude proportional to misalignment angle
19441944
omega_mag = self.weathercock_coeff * sin_angle
19451945

1946-
# Angular velocity in inertial frame
1947-
omega_inertial = rotation_axis * omega_mag
1948-
1949-
# Transform angular velocity to body frame
1950-
omega_body = Kt @ omega_inertial
1951-
1952-
# Quaternion derivative from angular velocity in body frame
1953-
omega1_wc, omega2_wc, omega3_wc = (
1954-
omega_body.x,
1955-
omega_body.y,
1956-
omega_body.z,
1957-
)
1958-
e0_dot = 0.5 * (-omega1_wc * e1 - omega2_wc * e2 - omega3_wc * e3)
1959-
e1_dot = 0.5 * (omega1_wc * e0 + omega3_wc * e2 - omega2_wc * e3)
1960-
e2_dot = 0.5 * (omega2_wc * e0 - omega3_wc * e1 + omega1_wc * e3)
1961-
e3_dot = 0.5 * (omega3_wc * e0 + omega2_wc * e1 - omega1_wc * e2)
1962-
e_dot = [e0_dot, e1_dot, e2_dot, e3_dot]
1963-
w_dot = [0, 0, 0] # No angular acceleration in 3DOF model
1946+
# Angular velocity in inertial frame, then transform to body frame
1947+
omega_body = Kt @ (rotation_axis * omega_mag)
19641948
else:
19651949
# 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
1950+
dot = body_z_inertial @ desired_direction
1951+
if dot < -0.999: # Anti-aligned
19711952
# Choose an arbitrary perpendicular axis
1972-
# Try [1,0,0] unless body_z_inertial is parallel to it
19731953
x_axis = Vector([1.0, 0.0, 0.0])
19741954
perp_axis = body_z_inertial ^ x_axis
19751955
if abs(perp_axis) < 1e-6:
1976-
# If parallel, use y axis
19771956
y_axis = Vector([0.0, 1.0, 0.0])
19781957
perp_axis = body_z_inertial ^ y_axis
19791958
if abs(perp_axis) < 1e-6:
1980-
# If still parallel, raise an error or choose a default axis
19811959
raise ValueError(
19821960
"Cannot determine a valid rotation axis: "
19831961
"body_z_inertial is parallel to both x and y axes."
19841962
)
19851963
rotation_axis = perp_axis.unit_vector
19861964
# 180 degree rotation: sin(angle) = 1
19871965
omega_mag = self.weathercock_coeff * 1.0
1988-
omega_inertial = rotation_axis * omega_mag
1989-
omega_body = Kt @ omega_inertial
1990-
omega1_wc, omega2_wc, omega3_wc = (
1991-
omega_body.x,
1992-
omega_body.y,
1993-
omega_body.z,
1994-
)
1995-
e0_dot = 0.5 * (-omega1_wc * e1 - omega2_wc * e2 - omega3_wc * e3)
1996-
e1_dot = 0.5 * (omega1_wc * e0 + omega3_wc * e2 - omega2_wc * e3)
1997-
e2_dot = 0.5 * (omega2_wc * e0 - omega3_wc * e1 + omega1_wc * e3)
1998-
e3_dot = 0.5 * (omega3_wc * e0 + omega2_wc * e1 - omega1_wc * e2)
1999-
e_dot = [e0_dot, e1_dot, e2_dot, e3_dot]
2000-
w_dot = [0, 0, 0]
2001-
else:
2002-
# Vectors are nearly aligned, treat as aligned
2003-
e_dot = [0, 0, 0, 0]
2004-
w_dot = [0, 0, 0]
1966+
omega_body = Kt @ (rotation_axis * omega_mag)
1967+
# else: aligned or nearly aligned, omega_body remains None
1968+
1969+
# Compute quaternion derivatives from omega_body
1970+
if omega_body is not None:
1971+
omega1_wc, omega2_wc, omega3_wc = (
1972+
omega_body.x,
1973+
omega_body.y,
1974+
omega_body.z,
1975+
)
1976+
e0_dot = 0.5 * (-omega1_wc * e1 - omega2_wc * e2 - omega3_wc * e3)
1977+
e1_dot = 0.5 * (omega1_wc * e0 + omega3_wc * e2 - omega2_wc * e3)
1978+
e2_dot = 0.5 * (omega2_wc * e0 - omega3_wc * e1 + omega1_wc * e3)
1979+
e3_dot = 0.5 * (omega3_wc * e0 + omega2_wc * e1 - omega1_wc * e2)
1980+
e_dot = [e0_dot, e1_dot, e2_dot, e3_dot]
1981+
else:
1982+
e_dot = [0, 0, 0, 0]
1983+
w_dot = [0, 0, 0] # No angular acceleration in 3DOF model
20051984
else:
20061985
# No weathercocking or negligible freestream speed
20071986
e_dot = [0, 0, 0, 0]

0 commit comments

Comments
 (0)