Hello,
Below is an example using @luc explaination.
I used two arbitrary orbits with one having a much higher sma to see the lowest orbit catching up with the highest.
The phase difference is stored in a matrix so that you can get the phase difference for any satellites with respect to any other satellite.
Code
import org.hipparchus.linear.MatrixUtils;
import org.hipparchus.linear.RealMatrix;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.MathUtils;
import org.orekit.data.DataContext;
import org.orekit.data.DataProvider;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.PositionAngleType;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.PropagatorsParallelizer;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.propagation.sampling.MultiSatFixedStepHandler;
import org.orekit.time.AbsoluteDate;
import org.orekit.utils.Constants;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PhaseBetweenSatellites {
public static void main(String[] args) {
// Load orekit data
loadOrekitData();
// Orbit 1
final Orbit orbit1 = getOrbit1();
// Orbit 2
final Orbit orbit2 = getOrbit2();
// Orbit 3
final Orbit orbit3 = getOrbit3();
// Create propagators
final Propagator propagator1 = new KeplerianPropagator(orbit1);
final Propagator propagator2 = new KeplerianPropagator(orbit2);
final Propagator propagator3 = new KeplerianPropagator(orbit3);
final List<Propagator> propagators = Arrays.asList(propagator1, propagator2, propagator3);
// Create multi sat step handler
final PhaseDifferenceStepHandler handler = new PhaseDifferenceStepHandler();
// Create propagators parallelizer
double step = 60.;
final PropagatorsParallelizer parallelizer = new PropagatorsParallelizer(propagators, step, handler);
// Propagate
final AbsoluteDate startDate = orbit1.getDate();
final AbsoluteDate stopDate = startDate.shiftedBy(Constants.JULIAN_DAY);
parallelizer.propagate(startDate, stopDate);
// Retrieve list of phase angle differences
final List<RealMatrix> phaseDifferenceMatrixList = handler.getPhaseDifferenceMatrixList();
// Print difference between satellite 1 and 2 (angle2 - angle1) throughout the propagation
for (int i = 0; i < phaseDifferenceMatrixList.size(); i++) {
final double diff1With2 = phaseDifferenceMatrixList.get(i).getData()[0][1];
final double normalizedDiff1With2 = MathUtils.normalizeAngle(diff1With2, 0);
final double normalizedDiff2With2InDegree = FastMath.toDegrees(normalizedDiff1With2);
System.out.println(startDate.shiftedBy(i * step));
if (normalizedDiff1With2 < 0) {
System.out.format("Satellite 2 in front of satellite 1 by %4.2f°.\n\n",
FastMath.abs(normalizedDiff2With2InDegree));
} else if (normalizedDiff1With2 > 0) {
System.out.format("Satellite 2 behind of satellite 1 by %4.2f°.\n\n",
normalizedDiff2With2InDegree);
} else {
System.out.format("Satellite 2 at same phase angle satellite 1.\n\n");
}
}
}
private static void loadOrekitData() {
final File rootFile = new File(System.getProperty("user.home"));
final File orekitData = new File(rootFile, "orekit-data");
if (!orekitData.exists()) {
System.out.format("File %s not found.%n", orekitData.getAbsolutePath());
}
final DataProvider dirCrawler = new DirectoryCrawler(orekitData);
DataContext.getDefault().getDataProvidersManager().addProvider(dirCrawler);
}
private static Orbit getOrbit1() {
double a = 7000e3;
double e = 0.001;
double i = FastMath.toRadians(60.0);
double omega = FastMath.toRadians(0.0);
double raan = FastMath.toRadians(45.0);
double nu = FastMath.toRadians(0); // True anomaly
return new KeplerianOrbit(a, e, i, omega, raan, nu,
PositionAngleType.TRUE,
FramesFactory.getEME2000(),
new AbsoluteDate(),
Constants.IERS2010_EARTH_MU);
}
private static Orbit getOrbit2() {
double a = 10000e3;
double e = 0.001;
double i = FastMath.toRadians(60.0);
double omega = FastMath.toRadians(0.0);
double raan = FastMath.toRadians(45.0);
double nu = FastMath.toRadians(30); // True anomaly
return new KeplerianOrbit(a, e, i, omega, raan, nu,
PositionAngleType.TRUE,
FramesFactory.getEME2000(),
new AbsoluteDate(),
Constants.IERS2010_EARTH_MU);
}
private static Orbit getOrbit3() {
double a = 8500e3;
double e = 0.001;
double i = FastMath.toRadians(60.0);
double omega = FastMath.toRadians(0.0);
double raan = FastMath.toRadians(45.0);
double nu = FastMath.toRadians(15); // True anomaly
return new KeplerianOrbit(a, e, i, omega, raan, nu,
PositionAngleType.TRUE,
FramesFactory.getEME2000(),
new AbsoluteDate(),
Constants.IERS2010_EARTH_MU);
}
private static class PhaseDifferenceStepHandler implements MultiSatFixedStepHandler {
final List<RealMatrix> phaseDifferenceMatrixList = new ArrayList<>();
@Override
public void handleStep(List<SpacecraftState> states) {
// Create matrix to store results
final RealMatrix phaseDifferenceMatrix = MatrixUtils.createRealDiagonalMatrix(new double[states.size()]);
for (int i = 1; i < states.size(); i++) {
for (int j = 0; j < i; j++) {
// Compute phase difference
final double phase2 = states.get(i).getLv();
final double phase1 = states.get(j).getLv();
final double phaseDifference = phase2 - phase1;
// Store in matrix
phaseDifferenceMatrix.setEntry(i, j, phaseDifference);
phaseDifferenceMatrix.setEntry(j, i, -phaseDifference);
}
}
// Store in list
phaseDifferenceMatrixList.add(phaseDifferenceMatrix);
}
public List<RealMatrix> getPhaseDifferenceMatrixList() {
return phaseDifferenceMatrixList;
}
}
}
Cheers,
Vincent