Inputs of build for measurement builders in Orekit 12.0

Hi everyone,

The latest major version of our beloved library came with a bunch of API breaks, and maybe one of the most “disturbing” one might be the build method in MeasurementBuilder. Indeed it now takes an AbsoluteDate along with a Map of ObservableSatellite and OrekitStepInterpolator. So my question is: how to make it work with an array of SpacecraftState, like it used to take as inputs?
I’m aware that this method is mostly to be used within the orbit determination and is not originally meant for direct use, but I believe some people would use it to simulate measurements, so I think this topic will be of use to them.

The trick is that OrekitStepInterpolator is a bit of an obscure interface, only implemented natively by to private classes. I did find one in the tests:

        final OrekitStepInterpolator fakeInterpolator = new OrekitStepInterpolator() {
            public OrekitStepInterpolator restrictStep(SpacecraftState newPreviousState, SpacecraftState newCurrentState) { return null; }
            public boolean isPreviousStateInterpolated() { return false; }
            public boolean isForward() { return true; }
            public boolean isCurrentStateInterpolated() { return false; }
            public SpacecraftState getPreviousState() { return spacecraftState; }
            public SpacecraftState getInterpolatedState(AbsoluteDate date) { return spacecraftState; }
            public SpacecraftState getCurrentState() { return spacecraftState; }
        };

This looks like a rather brute force wrapp around a SpacecraftState. Is this sufficient for when someone wants to use the build method “like before”?

Best,
Romain.

No, this method is not intended to be used in orbit determination, it is intended to be used from the generation framework.

No, it is not sufficient. The problem is that we need to be able to move the satellite a little. See issue 1220 and also the last part of this discussion. In the case of interplanetary mission, we don’t even move spacecrafts “a little” but rather “a lot”, and using shiftedBy is not sufficient, so returning a constant state is even worse.

Hi,

@Serrof maybe if you change this line:

public SpacecraftState getInterpolatedState(AbsoluteDate date) { return spacecraftState; }

With something like:

public SpacecraftState getInterpolatedState(AbsoluteDate date) { return spacecraftState.shiftedBy(date.durationFrom(spacecraftState.getDate())); }

It will work like before no?

I’m not sure about the public boolean isForward() { return true; } though.

@luc I know you"re not happy with using “shiftedBys” but we already have had two questions on this new API. I understand Orekit should be as accurate as possible but it should also be accessible to users :wink:
We did cope with “shiftedBy” for years in the OD and the measurement generation, so why not add a default method in the MeasurementBuilder interface that would allow the old code to work?
It would look like this (Not sure about all the methods in the interpolator, I haven’t thought this through very much).

    /** Generate a single measurement.<p>
     * 
     * Warning: This method uses "shiftedBy" so it is not as accurate as the method above that uses interpolators.
     * 
     * @param states all spacecraft states (i.e. including ones that may not be relevant for the current builder)
     * @return generated measurement
     */
    default T build(AbsoluteDate date, SpacecraftState[] states) {
        final Map<ObservableSatellite, OrekitStepInterpolator> interpolators = new ConcurrentHashMap<>();
        
        for (int i = 0; i < states.length; i++) {
            final ObservableSatellite sat = getSatellites()[i];
            final SpacecraftState state = states[i];
            
            final OrekitStepInterpolator interpolator = new OrekitStepInterpolator() {
                public OrekitStepInterpolator restrictStep(SpacecraftState newPreviousState, SpacecraftState newCurrentState) { return null; }
                public boolean isPreviousStateInterpolated() { return false; }
                public boolean isForward() { return true; }
                public boolean isCurrentStateInterpolated() { return false; }
                public SpacecraftState getPreviousState() { return state; }
                public SpacecraftState getInterpolatedState(AbsoluteDate date) { return state.shiftedBy(date.durationFrom(state.getDate())); }
                public SpacecraftState getCurrentState() { return state; }
            };
            interpolators.put(sat, interpolator);
        }
        
        return build( date, interpolators);
    }

What do you think?

happy :lying_face:

No, seriously, your change seems sound to me, +1 for this method.

1 Like

:laughing: Loved your honesty @luc

I opened issue 1283 regarding this discussion.