ConstantThrustManeuver Mass Depletion in OD

Hi all,
I’m using ConstantThrustManeuver (currently just using BasicConstantThrustPropulsionModel) with the KalmanEstimator and BatchLSEstimator. I am a bit unclear on how mass depletion is expected to work in OD. If I have a ConstantThrustManeuver in my NumericalPropagatorBuilder’s force model and I use either estimator to process a set of measurements (returning a numerical propagator called propagator), calling propagator.getInitialState().getMass() returns the initial mass that I configured using propagator_builder.setMass(), implying that the mass depletion due to the ConstantThrustManeuver was not taken into account.

Is this expected? I can compute the mass depletion myself using the Isp equation of course, but I guess my concern is that if each subsequent propagator built using the PropagatorBuilder does not take into account mass depletions from the previous processed measurement, all of the mass-dependent forces (drag, SRP, future maneuvers, etc) will be computed using the original mass value instead of the updated mass value. Is there something I’m missing in the API to enable mass depletion during OD? Thanks.

It depends on the estimation date.
If you set up the propagator at a date before the maneuver, then the orbit determination will start from there, then perform a maneuver (consuming fuel) so the dynamics of the satellite, including the maneuver match the measurements. Then it returns a fully configured propagator at the date you requested, i.e. still before the maneuver, and therefore before mass is consumed.
The mass after maneuver should be found in the state after the propagation.

Check the date of the initial state you get from the propagator to be sure.

Thanks for your response Luc. So, my initial orbit which I configure the propagator builder is at 2024-11-08T10:41:23.093Z. My maneuver is at 2024-11-09T11:18:15.000Z, and my measurements are between 2024-11-09T09:52:07.151Z (just before the maneuver) and 2024-11-10T09:56:46.124Z (almost a day after the maneuver). The initial state date on the fully configured propagator I get back from the estimator after processing those measurements is 2024-11-10T09:56:46.124Z - my final measurement time, which is after the maneuver and is what I expected. (This is with the Kalman filter btw)

Based on that and your message Luc, I’d have expected that same fully configured propagator’s .getMass() to report a lower mass value than the initial mass. The maneuver has an Isp of about 170s and I’m expecting it to lower the mass by about 0.04kg, but the initial and final mass values match exactly.

After digging into the source code, I think this is essentially a bug in KalmanModel.predictState.

I noticed that if I collect the predicted states at each KalmanEstimation using the KalmanObserver, the mass is updated on the specific KalmanEstimation where my maneuver is part of the propagation span, but that that mass delta isn’t carried over to the builder and thus to the corrected spacecraft state, so it’s lost at the next observation epoch.

(Measurement time, estimation.getPredictedSpacecraftStates()[0].getMass())
('2024-11-09T09:53:04.28783369064331Z', 3000.5812),
 ('2024-11-09T09:53:10.28986871242523Z', 3000.5812),
 ('2024-11-09T09:53:16.29285430908203Z', 3000.5812),
 ('2024-11-09T09:53:22.29497611522675Z', 3000.5812),
 ('2024-11-10T02:49:11.74203193187714Z', 3000.531945651275), <=== This is the first measurement epoch after the maneuver.
 ('2024-11-10T02:49:17.74406731128693Z', 3000.5812), <=== Mass reverts back to its initial value.
 ('2024-11-10T02:49:23.74705290794373Z', 3000.5812),
 ('2024-11-10T02:49:41.75410890579224Z', 3000.5812),
 ('2024-11-10T05:15:03.15509116649628Z', 3000.5812),
 ('2024-11-10T05:15:11.95112943649292Z', 3000.5812),
 ('2024-11-10T05:15:20.74716806411743Z', 3000.5812),

I believe the reason is that in KalmanModel.predictState, while the PropagatorBuilder’s Orbit is updated, the mass value is not:

// Propagate the reference trajectory to measurement date
final SpacecraftState predictedSpacecraftState = referenceTrajectories[k].propagate(date);
setPredictedSpacecraftState(predictedSpacecraftState, k);

// Update the builder with the predicted orbit
// This updates the orbital drivers with the values of the predicted orbit
getBuilders().get(k).resetOrbit(predictedSpacecraftState.getOrbit());
// => Derek: Mass should be updated on the builder here! 
//        getBuilders().get(k).setMass(predictedSpacecraftState.getMass());

This way, the corrected spacecraft state which is constructed from the PropagatorBuilder will receive the updated mass value, and thus the initial state of the Propagator used to process the next measurement will also have the updated mass value.

1 Like

Good analysis!
Could you register the bug to our forge?

Done! KalmanModel does not update spacecraft mass from predicted state on PropagatorBuilder between measurements (#1587) · Issues · Orekit / Orekit · GitLab

Thanks Luc! I haven’t made any source contributions to Orekit yet but I will see if I can put one together for this issue if possible.

3 Likes