Rectangular sensor view‘s code error

Hello, I have completed defining a rectangular observation sensor on a satellite and attempted to observe the ground. But I have made multiple modifications to the elevation and half Aperture AlongTrack, half Aperture AcrossTrack, as well as extending the observation time, but I have found that no results can be observed. When the observation time was extended to 1400000000 seconds, it still did not occur. I feel like there may be some issues with the code, but I can’t figure out where the problem lies. Could you please help me take a look.
Cheers,
Yang

import java.io.File;
import java.util.Locale;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.ode.events.Action;
import org.hipparchus.util.FastMath;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.LofOffset;
import org.orekit.bodies.BodyShape;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.data.DataContext;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.frames.TopocentricFrame;
import org.orekit.geometry.fov.DoubleDihedraFieldOfView;
import org.orekit.geometry.fov.FieldOfView;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.propagation.events.BooleanDetector;
import org.orekit.propagation.events.ElevationDetector;
import org.orekit.propagation.events.EventDetector;
import org.orekit.propagation.events.FieldOfViewDetector;
import org.orekit.propagation.events.NegateDetector;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;

public class RectangularSensorView {
	public static void main(String[] args) {
		final File home = new File(System.getProperty("user.home"));
		final File orekitData = new File(home, "orekit-data");
		if (!orekitData.exists()) {
			System.err.format(Locale.US, "Failed to find %s folder%n", orekitData.getAbsolutePath());
			System.err.format(Locale.US,
					"You need to download %s from %s, unzip it in %s and rename it 'orekit-data' for this tutorial to work%n",
					"orekit-data-master.zip",
					"https://gitlab.orekit.org/orekit/orekit-data/-/archive/master/orekit-data-master.zip",
					home.getAbsolutePath());
			System.exit(1);
		}
		final DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();
		manager.addProvider(new DirectoryCrawler(orekitData));

		// Initial state definition : date, orbit
		final AbsoluteDate initialDate = new AbsoluteDate(2023, 9, 15, 4, 0, 00.000, TimeScalesFactory.getUTC());
		final double mu = 3.986004415e+14; // gravitation coefficient
		final Frame inertialFrame = FramesFactory.getEME2000(); // inertial frame for orbit definition
		final Vector3D position = new Vector3D(2797914.567, -2288195.171, 6012468.374);
		final Vector3D velocity = new Vector3D(-6089.132, 2403.774, 3732.121);
		final PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);
		final Orbit initialOrbit = new KeplerianOrbit(pvCoordinates, inertialFrame, initialDate, mu);

		// Earth and frame
		final Frame earthFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
		final BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
				Constants.WGS84_EARTH_FLATTENING, earthFrame);

		// Station
		final double longitude = FastMath.toRadians(0);
		final double latitude = FastMath.toRadians(0);
		final double altitude = 0.;
		final GeodeticPoint station1 = new GeodeticPoint(latitude, longitude, altitude);
		final TopocentricFrame sta1Frame = new TopocentricFrame(earth, station1, "喀什");

		// Defining rectangular field of view
		double halfApertureAlongTrack = FastMath.toRadians(20);
		double halfApertureAcrossTrack = FastMath.toRadians(20);

		FieldOfView fov = new DoubleDihedraFieldOfView(Vector3D.MINUS_I, // From satellite to body center
				Vector3D.PLUS_K, halfApertureAcrossTrack, // Across track direction
				Vector3D.PLUS_J, halfApertureAlongTrack, // Along track direction
				0); // Angular margin

		// Defining attitude provider
		AttitudeProvider attitudeProvider = new LofOffset(inertialFrame, LOFType.LVLH);

		// Defining your propagator and setting up the attitude provider
		Propagator propagator = new KeplerianPropagator(initialOrbit);
		propagator.setAttitudeProvider(attitudeProvider);
	
		
		// Event definition
		final double maxcheck = 20.0;
		final double threshold = 0.001;
		final double elevation = FastMath.toRadians(100.0);
		final EventDetector sta1Visi = new ElevationDetector(maxcheck, threshold, sta1Frame)
				.withConstantElevation(elevation).withHandler((s, detector, increasing) -> {
					if (increasing) {
						System.out.println("Visibility begins on " + detector.getTopocentricFrame().getName() + " at "
								+ s.getDate());
					} else {
						System.out.println("Visibility ends on " + detector.getTopocentricFrame().getName() + " at "
								+ s.getDate());
					}
					return Action.CONTINUE; 
				});

		FieldOfViewDetector fovDetector = new FieldOfViewDetector(sta1Frame, fov);
		BooleanDetector bd = BooleanDetector.andCombine(sta1Visi, new NegateDetector(fovDetector));
		propagator.addEventDetector(bd);

		final SpacecraftState finalState = propagator.propagate(initialDate.shiftedBy(1440000.));

		System.out.println(" Final state : " + finalState.getDate().durationFrom(initialDate));
	}

}

No satellite can exceed 90° elevation (it occurs when it is exactly above station), so 100° elevation can never be reached.

Now I have modified the elevation to 5deg, but there is still no result


Well, in my opinion, I believe something wrong has happened in my code. Because the satellite shouldn’t fail to observe the station in such a long time. Could you help me find which code goes wrong?

You should register the handler to the bd detector, not to the sta1Visi detector. Doing so, you loose the possibility to call detector.getTopocentricFrame() as the detector will be a BooleanDetector and not an ElevationDtector, so in the handler you should replace detector.getTopocentricFrame() by sta1Frame.getName()

public class RectangularSensorView {
public static void main(String args) {
final File home = new File(System.getProperty(“user.home”));
final File orekitData = new File(home, “orekit-data”);
if (!orekitData.exists()) {
System.err.format(Locale.US, “Failed to find %s folder%n”, orekitData.getAbsolutePath());
System.err.format(Locale.US,
“You need to download %s from %s, unzip it in %s and rename it ‘orekit-data’ for this tutorial to work%n”,
“orekit-data-master.zip”,
https://gitlab.orekit.org/orekit/orekit-data/-/archive/master/orekit-data-master.zip”,
home.getAbsolutePath());
System.exit(1);
}
final DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();
manager.addProvider(new DirectoryCrawler(orekitData));

	// Initial state definition : date, orbit
	final AbsoluteDate initialDate = new AbsoluteDate(2023, 9, 15, 4, 0, 00.000, TimeScalesFactory.getUTC());
	final double mu = 3.986004415e+14; // gravitation coefficient
	final Frame inertialFrame = FramesFactory.getEME2000(); // inertial frame for orbit definition
	final Vector3D position = new Vector3D(2797914.567, -2288195.171, 6012468.374);
	final Vector3D velocity = new Vector3D(-6089.132, 2403.774, 3732.121);
	final PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);
	final Orbit initialOrbit = new KeplerianOrbit(pvCoordinates, inertialFrame, initialDate, mu);

	// Earth and frame
	final Frame earthFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
	final BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
			Constants.WGS84_EARTH_FLATTENING, earthFrame);

	// Station
	final double longitude = FastMath.toRadians(5);
	final double latitude = FastMath.toRadians(5);
	final double altitude = 0.;
	final GeodeticPoint station1 = new GeodeticPoint(latitude, longitude, altitude);
	final TopocentricFrame sta1Frame = new TopocentricFrame(earth, station1, "喀什");

	// Defining rectangular field of view
	double halfApertureAlongTrack = FastMath.toRadians(20);
	double halfApertureAcrossTrack = FastMath.toRadians(20);

	FieldOfView fov = new DoubleDihedraFieldOfView(Vector3D.MINUS_I, // From satellite to body center
			Vector3D.PLUS_K, halfApertureAcrossTrack, // Across track direction
			Vector3D.PLUS_J, halfApertureAlongTrack, // Along track direction
			0); // Angular margin

	// Defining attitude provider
	AttitudeProvider attitudeProvider = new LofOffset(inertialFrame, LOFType.LVLH);

	// Defining your propagator and setting up the attitude provider
	Propagator propagator = new KeplerianPropagator(initialOrbit);
	propagator.setAttitudeProvider(attitudeProvider);

	
	// Event definition
	final double maxcheck = 20.0;
	final double threshold = 0.001;
	final double elevation = FastMath.toRadians(5.0);
	final EventDetector sta1Visi = new ElevationDetector(maxcheck, threshold, sta1Frame)
			.withConstantElevation(elevation).withHandler((s, detector, increasing) -> {
				if (increasing) {
					System.out.println("Visibility begins on " + sta1Frame.getName() + " at "
							+ s.getDate());
				} else {
					System.out.println("Visibility ends on " + sta1Frame.getName() + " at "
							+ s.getDate());
				}
				return Action.CONTINUE; 
			});

	FieldOfViewDetector fovDetector = new FieldOfViewDetector(sta1Frame, fov);
	BooleanDetector bd = BooleanDetector.andCombine(sta1Visi, new NegateDetector(fovDetector));
	propagator.addEventDetector(bd);

	final SpacecraftState finalState = propagator.propagate(initialDate.shiftedBy(14400.));

	System.out.println(" Final state : " + finalState.getDate().durationFrom(initialDate));
}

}
I have tried to use your method to fix my code, but it failed again. Nothing right happen.If possible, can you provide complete and executable code?

Here it is. The only modifications are:

  • changed 100° to 5°
  • associate event handler to boolean detector
  • use sta1Frame.getName() directly in handler
import java.io.File;
import java.util.Locale;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.ode.events.Action;
import org.hipparchus.util.FastMath;
import org.orekit.attitudes.AttitudeProvider;
import org.orekit.attitudes.LofOffset;
import org.orekit.bodies.BodyShape;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.data.DataContext;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.LOFType;
import org.orekit.frames.TopocentricFrame;
import org.orekit.geometry.fov.DoubleDihedraFieldOfView;
import org.orekit.geometry.fov.FieldOfView;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.SpacecraftState;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.propagation.events.BooleanDetector;
import org.orekit.propagation.events.ElevationDetector;
import org.orekit.propagation.events.EventDetector;
import org.orekit.propagation.events.FieldOfViewDetector;
import org.orekit.propagation.events.NegateDetector;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.PVCoordinates;

public class RectangularSensorView {
    public static void main(String[] args) {
        final File home = new File(System.getProperty("user.home"));
        final File orekitData = new File(home, "orekit-data");
        if (!orekitData.exists()) {
            System.err.format(Locale.US, "Failed to find %s folder%n", orekitData.getAbsolutePath());
            System.err.format(Locale.US,
                    "You need to download %s from %s, unzip it in %s and rename it 'orekit-data' for this tutorial to work%n",
                    "orekit-data-master.zip",
                    "https://gitlab.orekit.org/orekit/orekit-data/-/archive/master/orekit-data-master.zip",
                    home.getAbsolutePath());
            System.exit(1);
        }
        final DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();
        manager.addProvider(new DirectoryCrawler(orekitData));

        // Initial state definition : date, orbit
        final AbsoluteDate initialDate = new AbsoluteDate(2023, 9, 15, 4, 0, 00.000, TimeScalesFactory.getUTC());
        final double mu = 3.986004415e+14; // gravitation coefficient
        final Frame inertialFrame = FramesFactory.getEME2000(); // inertial frame for orbit definition
        final Vector3D position = new Vector3D(2797914.567, -2288195.171, 6012468.374);
        final Vector3D velocity = new Vector3D(-6089.132, 2403.774, 3732.121);
        final PVCoordinates pvCoordinates = new PVCoordinates(position, velocity);
        final Orbit initialOrbit = new KeplerianOrbit(pvCoordinates, inertialFrame, initialDate, mu);

        // Earth and frame
        final Frame earthFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
        final BodyShape earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
                Constants.WGS84_EARTH_FLATTENING, earthFrame);

        // Station
        final double longitude = FastMath.toRadians(0);
        final double latitude = FastMath.toRadians(0);
        final double altitude = 0.;
        final GeodeticPoint station1 = new GeodeticPoint(latitude, longitude, altitude);
        final TopocentricFrame sta1Frame = new TopocentricFrame(earth, station1, "喀什");

        // Defining rectangular field of view
        double halfApertureAlongTrack = FastMath.toRadians(20);
        double halfApertureAcrossTrack = FastMath.toRadians(20);

        FieldOfView fov = new DoubleDihedraFieldOfView(Vector3D.MINUS_I, // From satellite to body center
                Vector3D.PLUS_K, halfApertureAcrossTrack, // Across track direction
                Vector3D.PLUS_J, halfApertureAlongTrack, // Along track direction
                0); // Angular margin

        // Defining attitude provider
        AttitudeProvider attitudeProvider = new LofOffset(inertialFrame, LOFType.LVLH);

        // Defining your propagator and setting up the attitude provider
        Propagator propagator = new KeplerianPropagator(initialOrbit);
        propagator.setAttitudeProvider(attitudeProvider);
    
        
        // Event definition
        final double maxcheck = 20.0;
        final double threshold = 0.001;
        final double elevation = FastMath.toRadians(5.0);
        final EventDetector sta1Visi = new ElevationDetector(maxcheck, threshold, sta1Frame)
                .withConstantElevation(elevation);

        FieldOfViewDetector fovDetector = new FieldOfViewDetector(sta1Frame, fov);
        BooleanDetector bd = BooleanDetector.andCombine(sta1Visi, new NegateDetector(fovDetector)).withHandler((s, detector, increasing) -> {
            if (increasing) {
                System.out.println("Visibility begins on " + sta1Frame.getName() + " at "
                        + s.getDate());
            } else {
                System.out.println("Visibility ends on " + sta1Frame.getName() + " at "
                        + s.getDate());
            }
            return Action.CONTINUE; 
        });
        propagator.addEventDetector(bd);

        final SpacecraftState finalState = propagator.propagate(initialDate.shiftedBy(1440000.));

        System.out.println(" Final state : " + finalState.getDate().durationFrom(initialDate));
    }

}

When run, this produces:

Visibility begins on 喀什 at 2023-09-18T10:25:39.70760156671333Z
Visibility ends on 喀什 at 2023-09-18T10:26:45.07856555648929Z
Visibility begins on 喀什 at 2023-09-22T10:10:32.13665133014264Z
Visibility ends on 喀什 at 2023-09-22T10:11:37.48872441022495Z
Visibility begins on 喀什 at 2023-09-26T09:55:24.56339447309803Z
Visibility ends on 喀什 at 2023-09-26T09:56:29.90159466051769Z
Visibility begins on 喀什 at 2023-09-30T09:40:16.98873786983511Z
Visibility ends on 喀什 at 2023-09-30T09:41:22.31809334971852Z
 Final state : 1440000.0

Yes, you are right. With your help, I succeed to run my source code. Thank you very much!