Flat-Spin-Übergangsmanöver: Warum ist der Drehimpuls nicht konstant?

In einem Artikel von Rahn und Barba, in dem ein Flat-Spin-Übergangsmanöver untersucht wird, wird folgende Abbildung dargestellt:

Geben Sie hier die Bildbeschreibung ein

Ich versuche, diese Figur zu reproduzieren, indem ich die folgenden gekoppelten Bewegungsgleichungen integriere, die im Artikel angegeben sind:

Geben Sie hier die Bildbeschreibung ein

Unter Verwendung der folgenden Simulationsparameter:

Geben Sie hier die Bildbeschreibung ein

Der Drehimpuls berechnet sich zu:

Geben Sie hier die Bildbeschreibung ein

Die Ergebnisse:

Geben Sie hier die Bildbeschreibung ein

Erstellt durch den folgenden MATLAB-Code:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Example Rahn & Barba (1991) %%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Principal moments of inertia of spacecraft including slug
Ix = 2000;
Iy = 1500;
Iz = 1000;
I = [Ix Iy Iz];

% Principal moments of inertia of spherical propellant slug
J = 18;

% Spacecraft body rates
omega_x = 0.1224;
omega_y = 0;
omega_z = 2.99;
omega_0 = [omega_x omega_y omega_z];

% Relative rates between spacecraft body and propellant slug
sigma_x = 0;
sigma_y = 0;
sigma_z = 0;
sigma_0 = [sigma_x sigma_y sigma_z];

% Viscous damping coefficient
mu_x = 30;
mu_y = 30;
mu_z = 30;
mu = [mu_x mu_y mu_z];

% Torques about principal axes
Tx = 0;
Ty = 0;
Tz = 0;
T = [Tx Ty Tz];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Integrate system of differential equations
options = [];
[t1, x1] = ode45( @omega_dynamics, [0 1000], [omega_0 sigma_0], options, I, mu, T, J );

% Calculate angular momentum
h = ((Ix * x1(:,1) + J * x1(:,4)).^2 + (Iy * x1(:,2) + J * x1(:,5)).^2 + (Iz * x1(:,3) + J * x1(:,6)).^2).^(1/2);

figure(1)
% Plot minor-axis spin rate
subplot(2,2,1);
plot(t1,x1(:,3))
axis([0 1000 -2 3])
title('Minor Axis Spin Rate')
xlabel('Time - seconds')
ylabel('rad/s')
% Plot intermediate-axis spin rate
subplot(2,2,2);
plot(t1,x1(:,2))
title('Intermediate Axis Spin Rate')
xlabel('Time - seconds')
ylabel('rad/s')
% Plot major-axis spin rate
subplot(2,2,3);
plot(t1,x1(:,1))
title('Major Axis Spin Rate')
xlabel('Time - seconds')
ylabel('rad/s')
% Plot angular momentum
subplot(2,2,4);
plot(t1,h)
title('Angular Momentum')
xlabel('Time - seconds')
ylabel('Nms')

function dx = omega_dynamics(~, x_0, I, mu, T, J)

    % Initial state vector
    omega_x = x_0(1);
    omega_y = x_0(2);
    omega_z = x_0(3);
    sigma_x = x_0(4);
    sigma_y = x_0(5);
    sigma_z = x_0(6);

    % Constants
    mu_x = mu(1);
    mu_y = mu(2);
    mu_z = mu(3);
    Ix = I(1);
    Iy = I(2);
    Iz = I(3);
    Tx = T(1);
    Ty = T(2);
    Tz = T(3);

    % Differential equations
    omega_dot_x = ((Iy - Iz)*omega_y*omega_z + mu_x*sigma_x + Tx)/(Ix - J);
    omega_dot_y = ((Iz - Ix)*omega_z*omega_x + mu_y*sigma_y + Ty)/(Iy - J);
    omega_dot_z = ((Ix - Iy)*omega_x*omega_y + mu_z*sigma_z + Tz)/(Iz - J);
    sigma_dot_x = -omega_dot_x - mu_x*sigma_x/J - omega_y*sigma_z + omega_z*sigma_y;
    sigma_dot_y = -omega_dot_y - mu_y*sigma_y/J - omega_z*sigma_x + omega_x*sigma_z;
    sigma_dot_z = -omega_dot_z - mu_z*sigma_z/J - omega_x*sigma_y + omega_y*sigma_x;

    % Return vector
    dx = [omega_dot_x; omega_dot_y; omega_dot_z; sigma_dot_x; sigma_dot_y; sigma_dot_z];

end

Wie aus den Ergebnissen ersichtlich ist, ist der Drehimpuls, der konstant sein sollte, nicht konstant und nimmt während des Übergangsmanövers sogar zu. Ich habe meinen Code auf und ab überprüft, konnte aber keine Fehler finden. Ich vermute, dass es etwas mit der ode45Funktion zu tun hat, bin mir aber nicht sicher. Hat hier jemand eine Ahnung was los ist?

2‰-Drift über die Simulation, wobei die Anfangsbedingungen vier signifikante Stellen aufweisen, wahrscheinlich aufgrund von Rundungsfehlern.
Ich würde sagen, unabhängig von den Anfangsbedingungen sollte der Drehimpuls konstant bleiben. Dann muss es also etwas im ode45Algorithmus geben, das diese Drift verursacht.
Interessante Frage!
"ode45 ist ein vielseitiger ODE-Löser und der erste Löser, den Sie für die meisten Probleme ausprobieren sollten. Wenn das Problem jedoch schwierig ist oder eine hohe Genauigkeit erfordert, gibt es andere ODE-Löser, die möglicherweise besser für das Problem geeignet sind."
Ich stimme zu, die Anfangsbedingungen sollten die erwartete Nullsumme nicht beeinflussen, aber progressive Annäherungen (Gleitkommaoperationen) können Fehler akkumulieren.
Von allen Solvern, die MATLAB anbietet, kommen die Ergebnisse, die ode113und ode23sproduzieren, dem Original am nächsten. Befriedigend sind sie trotzdem nicht. Aber tatsächlich scheint es eine Lösungssache zu sein.
Haben Sie versucht, die Fehlertoleranzoptionen festzulegen ( mathworks.com/help/matlab/math/summary-of-ode-options.html )?
@uhoh Ich glaube nicht, dass das Innenleben des ode45-Algorithmus, der in Matlab integriert ist, um Differentialgleichungen numerisch zu lösen, auch nur im entferntesten ein Thema der Weltraumforschung ist. Ich wäre also nicht überrascht, wenn Ihre Frage einige Off-Topic-Stimmen erhalten würde.
@ user2705196 Schauen Sie sich diese Antwort an , die RK4 zeigt (ich hätte als nächstes RK45 und eine variable Schrittgröße hinzugefügt, wenn der Benutzer interessiert wäre) und diese Frage . Die Berechnung von Umlaufbahnbahnen und Raumfahrzeugbewegungen ist von zentraler Bedeutung für die Erforschung des Weltraums und ist auf dieser Website ein klares und solides Thema. Siehe auch Hilfe bei meiner Spannspannung; Wie kann man dieses Starrkörper-Schwerkraftgradientendrehmoment ableiten und berechnen? Übrigens ist es nicht meine Frage, ich habe gerade editiert ...
@uhoh Ich erkläre nur, warum Leute möglicherweise dafür stimmen, diese Frage aus Gründen zu schließen, die nichts damit zu tun haben, dass sie die Antwort nicht kennen. Und deine Argumentation überzeugt mich nicht. Es klingt ein bisschen so, als würde man sagen "Digitalkameras sind wichtig für die Weltraumforschung, daher ist die Frage, wie ein CCD funktioniert, direkt zum Thema".

Antworten (2)

Kurze Antwort: Es handelt sich um ein ODE-Solver-Problem.

Beim Einstellen der relativen und absoluten Fehlertoleranzen werden bessere Ergebnisse erzielt. Beispielsweise optionskann die Variable im MATLAB-Code wie folgt definiert werden:

options = odeset('RelTol',1e-10,'AbsTol',1e-10);

Um den anfänglichen Drehimpuls statt (wie in dieser Antwort darauf hingewiesen wurde) zu lassen 3000, kann3000.0045 die Gleichung zur Berechnung des Drehimpulses auch wie folgt für die anfängliche Spinrate der Nebenachse gelöst werden:

omega_z = ( ( 3000^2 - ( Ix * omega_x )^2 ) / ( Iz^2 ) )^( 1/2 );

Um schließlich die Achsen des Drehimpulsdiagramms anzupassen, fügen Sie hinzu:

axis([0 1000 2999 3001])

Daraus ergibt sich folgende Abbildung:

Geben Sie hier die Bildbeschreibung ein

Sehr schöne Antwort und tolle Neuigkeiten! Ich würde mich rtolnur an die Angabe halten. Absolute Toleranz oder atolist umständlich zu verwenden, wenn Sie Zahlen mit physikalischen Einheiten haben. rtolist alles, was du brauchst. Sehen Sie auch, ob Sie eine Möglichkeit finden, die vertikale Achse angular momentumautomatisch skalieren zu lassen, damit Sie immer sehen können, wie groß die Abweichung ist. Wenn Sie es auf [2999 bis 3001] fixieren, können Sie nicht sehen, was los ist.
@uhoh Es stellt sich heraus, dass, wenn ich RelTolnur spezifiziere, die Genauigkeit nur auf 10^(-2). AbsTolAuch die Angabe ergibt 10^(-6)Genauigkeit. Sie haben Recht mit der Skalierung, um die Abweichung anzuzeigen, aber das Ziel war, die Abbildung im Artikel zu reproduzieren. Daher reicht es aus, die Achse zu fixieren.
Probieren Sie eine Untersuchung der spezifischen Werte aus, die Sie verwenden. Die Wirkung der beiden wird unterschiedlich sein, da einer normalisiert ist und der andere nicht. Es reicht nicht zu sagen, dass Sie den Parameter verwendet oder nicht verwendet haben, Sie müssen den Wert des Parameters optimieren. Sie werden beide einen Einfluss haben, und wenn Sie sie einfach gleich setzen, kann einer einen anderen Einfluss haben als der andere, aber es gibt keinen Grund, sie auf denselben Wert zu setzen. Viel Glück, vorbei und raus!
Oh, außer fühlen Sie sich frei, Ihre eigene Antwort zu akzeptieren! Es beschreibt am besten die Lösung für Ihre Frage.

Ich habe Ihr Matlab in Python umgeschrieben (was wirklich einfach ist und das ist kein Zufall!) und den Standard-SciPy-ODE-Integrator verwendet. Beim Überprüfen info['mused']sehe ich, dass immer der Adams-Algorithmus (nicht steif) verwendet wurde, sodass die Steifigkeit nicht das Problem ist.

Warum nicht einfach das „alte und kaputte“ Matlab fallen lassen und das „neue heiße“ Python übernehmen? ( MIB-Referenz )

Ich würde vermuten, dass Sie anfangen sollten, Ihre Matlab-Dokumentation zu lesen ode45und Ihre Fehlertoleranz niedriger einzustellen. Ich vermute, das ode45ist, was ich RK45 nennen würde und eine variable Schrittgröße 4/5 der Ordnung Runge-Kutta ist. Es sollte in Ordnung sein, aber wenn Sie keine Toleranz angeben, wird es eine für Sie auswählen.

Es ist möglich, dass Matlab zwischen der Veröffentlichung Ihrer Referenz und dem Ausführen Ihres Beispiels einige Standardeinstellungen geändert hat oder der Autor einige verwendet und vergessen hat, Ihnen dies mitzuteilen, oder Sie haben sie nicht bemerkt, die früher in dem, was Sie gelesen haben, erwähnt wurden .

Lange Rede kurzer Sinn, bei mir funktioniert es einwandfrei.

Der Anfangsdrehimpuls ist nicht 3000 unter Verwendung der Initialisierungswerte, sondern genau 3000.0045dort, wo die Simulation beginnt. Es driftet nach 3000.0011000 Sekunden ab. Das ist eine Änderung von 0,003. Die Abweichung von geraden 3000 (oder 3e3) wird im Diagramm angezeigt.

Ich kann das ein wenig verbessern, auf eine Gesamtdrift von nur etwa 0,001, indem ich rtol=1E-10oder rtol=1E-11in den Aufruf von einfüge ODEint.

Geben Sie hier die Bildbeschreibung ein

def omega_dynamics(x_0, t, I, mu, T, J):

    # % Initial state vector
    omega_x, omega_y, omega_z, sigma_x, sigma_y, sigma_z = x_0[:6]

    # % Constants
    mu_x, mu_y, mu_z = mu[:3]
    Ix, Iy, Iz = I[:3]
    Tx, Ty, Tz = T[:3]

    # % Differential equations
    omega_dot_x = ((Iy - Iz)*omega_y*omega_z + mu_x*sigma_x + Tx)/(Ix - J)
    omega_dot_y = ((Iz - Ix)*omega_z*omega_x + mu_y*sigma_y + Ty)/(Iy - J)
    omega_dot_z = ((Ix - Iy)*omega_x*omega_y + mu_z*sigma_z + Tz)/(Iz - J)
    sigma_dot_x = -omega_dot_x - mu_x*sigma_x/J - omega_y*sigma_z + omega_z*sigma_y
    sigma_dot_y = -omega_dot_y - mu_y*sigma_y/J - omega_z*sigma_x + omega_x*sigma_z
    sigma_dot_z = -omega_dot_z - mu_z*sigma_z/J - omega_x*sigma_y + omega_y*sigma_x

    # % Return vector
    dx = np.array([omega_dot_x, omega_dot_y, omega_dot_z, sigma_dot_x, sigma_dot_y, sigma_dot_z])

    return dx

# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# %%%%% Example Rahn & Barba (1991) %%%%%
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint as ODEint

J        = 18.0;                                             # Principal moments of inertia of spherical propellant slug
I        = np.array([2000,   1500,   1000], dtype=float)   # Principal moments of inertia of spacecraft including slug
omega_0  = np.array([0.1224, 0,      2.99], dtype=float)   # Spacecraft body rates
sigma_0  = np.array([0,      0,      0   ], dtype=float)   # Relative rates between spacecraft body and propellant slug
mu       = np.array([30,     30,     30  ], dtype=float)   # Viscous damping coefficient
T        = np.array([0,      0,      0   ], dtype=float)   # Torques about principal axes

h_init   = np.sqrt(((I * omega_0 + J * sigma_0)**2).sum())  # % Calculate angular momentum

print "h_init: ", h_init

times        = np.linspace(0, 1000, 10001)
X0           = np.hstack((omega_0, sigma_0))

x1, info = ODEint(omega_dynamics, X0, times, args=(I, mu, T, J), full_output=True)
print x1.shape

h          = np.sqrt(((I * x1[:, :3] + J * x1[:,3:])**2).sum(axis=1))  # % Calculate angular momentum

if True:
    plt.figure()

    plt.subplot(2, 2, 1)
    plt.plot(times, x1[:, 2])
    plt.ylim(-2, 3)
    plt.title('Minor Axis Spin Rate')
    plt.xlabel('Time - seconds')
    plt.ylabel('rad/s')

    plt.subplot(2, 2, 2)
    plt.plot(times, x1[:, 1])
    plt.title('Intermediate Axis Spin Rate')
    plt.xlabel('Time - seconds')
    plt.ylabel('rad/s')

    plt.subplot(2, 2, 3)
    plt.plot(times, x1[:, 0])
    plt.title('Major Axis Spin Rate')
    plt.xlabel('Time - seconds')
    plt.ylabel('rad/s')

    plt.subplot(2, 2, 4)
    plt.plot(times, h)
    plt.title('Angular Momentum')
    plt.xlabel('Time - seconds')
    plt.ylabel('Nms')

    plt.show()
Danke @uhoh, das bestätigt meine Vermutung. Gut zu wissen, dass der Code in Ordnung ist. All in für Python, wenn ich nicht mit Simulink arbeite :)
@woeterb ja! Wenn Sie einen Weg finden, Sie zu überreden ode45, Ihnen das zu geben, was Sie brauchen, dann posten Sie hier eine weitere Antwort. Wenn es Ihr Problem wirklich löst, können Sie es auch akzeptieren. Ziel ist es, zukünftigen Nutzern die bestmöglichen Informationen zur Verfügung zu stellen. Spaß haben!
Ich habe eine neue Antwort gepostet, die die eigentliche Lösung für das MATLAB-Beispiel enthält. Damit ist die Frage wirklich gelöst. Danke für Ihr Bemühen.