The following is a method I wrote, which only realizes the calculation of the satellite visual window, but does not realize the satellite circle number and the lifting rail mark corresponding to the calculation window.
public void satToFacility(String line1, String line2, Date startDate, Date endDate, String facilityName,
Double longitude, Double latitude, Double altitude, Double minElevation){
//加载固定数据
Dataloading dataloading = new Dataloading();
dataloading.dataLoade();
// Initial state definition : date, orbit
//计算时间段由北京时间转为UTC时间
TimeScale utc = TimeScalesFactory.getUTC();
AbsoluteDate start = new AbsoluteDate(startDate, utc);
AbsoluteDate end = new AbsoluteDate(endDate, utc);
final double mu = 3.986004415e+14; // gravitation coefficient
final Frame inertialFrame = FramesFactory.getEME2000(); // inertial frame for orbit definition
TLE tle = new TLE(line1, line2);
TLEPropagator tlePropagator = TLEPropagator.selectExtrapolator(tle);
// 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);
final GeodeticPoint facility = new GeodeticPoint(latitude, longitude, altitude);
final TopocentricFrame sta1Frame = new TopocentricFrame(earth, facility, facilityName);
//定义事件处理器,用于处理事件
final double maxcheck = 60.0;
final double threshold = 0.01;
final EventDetector sta1Visi =
new ElevationDetector(maxcheck, threshold, sta1Frame)
.withConstantElevation(minElevation)
.withHandler((s, detector, increasing) → {
if (increasing) {
System.out.println(“地面站名称: “+((ElevationDetector) detector).getTopocentricFrame().getName()
+” 跟踪开始时间: " + s.getDate()
+” 入境方位角: “+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getAzimuth(s.getPosition(), s.getFrame(), s.getDate()))
+” 入境俯仰角: "+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getElevation(s.getPosition(), s.getFrame(), s.getDate()))
);
} else {
System.out.println(“地面站名称: “+((ElevationDetector) detector).getTopocentricFrame().getName()
+” 跟踪结束时间: " + s.getDate()
+” 入境方位角: “+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getAzimuth(s.getPosition(), s.getFrame(), s.getDate()))
+” 入境俯仰角: "+FastMath.toDegrees(((ElevationDetector) detector).getTopocentricFrame().getElevation(s.getPosition(), s.getFrame(), s.getDate()))
);
}
return Action.CONTINUE; // Continue processing the event
});
// Add event to be detected
tlePropagator.addEventDetector(sta1Visi);
// Propagate from the initial date to the first raising or for the fixed duration
final SpacecraftState state = tlePropagator.propagate(start,end);
Hello @gengjianben,
If i understand your problem, you want to be able to save the revolution count of each satellite visual window ?
yes,andSatellite ascending/descending orbit
Revolution count
It can be done using a NodeDetector
filtered with an EventSlopeFilter
& coupled with a custom EventHandler
:
Code
import org.hipparchus.ode.events.Action;
import org.orekit.data.DataContext;
import org.orekit.data.DataProvider;
import org.orekit.data.DirectoryCrawler;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.propagation.analytical.tle.TLE;
import org.orekit.propagation.analytical.tle.TLEPropagator;
import org.orekit.propagation.events.EventDetector;
import org.orekit.propagation.events.EventSlopeFilter;
import org.orekit.propagation.events.FilterType;
import org.orekit.propagation.events.NodeDetector;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import java.io.File;
import java.util.concurrent.atomic.AtomicInteger;
public class OrbitRevolutionCounter {
public static void main(String[] args) {
try {
// Initialize Orekit data
loadOrekitData();
// Define the TLE of the satellite
String line1 = "1 25544U 98067A 23051.54758796 .00006497 00000+0 12484-3 0 9993";
String line2 = "2 25544 51.6447 109.6434 0006629 348.2835 11.7775 15.50216967390537";
TLE tle = new TLE(line1, line2);
// Create a TLE propagator
TLEPropagator propagator = TLEPropagator.selectExtrapolator(tle);
// Set the start and end dates for propagation
AbsoluteDate startDate = new AbsoluteDate(2023, 1, 1, 0, 0, 0.000, TimeScalesFactory.getUTC());
AbsoluteDate endDate = startDate.shiftedBy(86400.0); // Propagate for 1 day
// inertial frame (EME2000) definitions
Frame inertialFrame = FramesFactory.getEME2000();
// Create a detector for node crossing
final AtomicInteger revolutionCounter = new AtomicInteger();
EventDetector nodeDetector = new NodeDetector(inertialFrame);
// Trigger orbit count at ascending node
final EventDetector ascendingNodeDetector =
new EventSlopeFilter<>(nodeDetector, FilterType.TRIGGER_ONLY_INCREASING_EVENTS)
.withHandler((spacecraftState, eventDetector, b) -> {
System.out.println("Revolution #" + revolutionCounter.incrementAndGet() + " at " + spacecraftState.getDate());
return Action.CONTINUE;
});
// Add the event detector to the propagator
propagator.addEventDetector(ascendingNodeDetector);
// Propagate from the start to the end date
propagator.propagate(startDate, endDate);
System.out.println("Total revolutions in 1 day: " + revolutionCounter.get());
}
catch (Exception e) {
e.printStackTrace();
}
}
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);
}
}
Output
Revolution #1 at 2023-01-01T01:26:40.794226058194Z
Revolution #2 at 2023-01-01T02:59:33.09875379433856Z
Revolution #3 at 2023-01-01T04:32:25.39999450741908Z
Revolution #4 at 2023-01-01T06:05:17.69783899592005Z
Revolution #5 at 2023-01-01T07:38:09.99239383932184Z
Revolution #6 at 2023-01-01T09:11:02.28361525002211Z
Revolution #7 at 2023-01-01T10:43:54.57150458040749Z
Revolution #8 at 2023-01-01T12:16:46.85606268774112Z
Revolution #9 at 2023-01-01T13:49:39.13728854883064Z
Revolution #10 at 2023-01-01T15:22:31.41517701760435Z
Revolution #11 at 2023-01-01T16:55:23.68971870984771Z
Revolution #12 at 2023-01-01T18:28:15.96091332019481Z
Revolution #13 at 2023-01-01T20:01:08.22876874410557Z
Revolution #14 at 2023-01-01T21:34:00.49321105482781Z
Revolution #15 at 2023-01-01T23:06:52.75445201836968Z
Total revolutions in 1 day: 15
Ascending/Descending orbit
It can be done by creating a custom EventDetector
, very similar to the NodeDetector
, which would base its g method on the derivative of the Z component (in a frame where the equator is defined such as EME2000).
I’ll let you try this one !
Cheers,
Vincent
Thank you very much. I’ll try to do it later.
I think that we really need an EventHandler for revolution count increment. They are probably 2-3 implementations of this handler in the forum
I’ve opened an issue to implement it : Add a revolution counter handler (#1589) · Issues · Orekit / Orekit · GitLab
I very recently added a CountAndContinue
handler on the develop branch, so I guess it’s done?
I think we could use it to make something more user friendly and straightforward.
Since this is the first time for me to contact Orekit, I am not familiar with it. I thought that defining the output visible window of common detectors could also directly output the circle number and satellite lift-orbit information. Thank you for your help, and I am trying to do it
Since my stations are in the Northern Hemisphere,I think it is enough to see if there is a positive vector to the north. I judged it according to the northward component of the velocity vector of the satellite at the time of the maximum elevation angle.
In addition, I think that Orekit is a powerful calculation tool for solving almost all kinds of orbital problems(a small area that I can get my hands on), it is not a fixed software like STK which gives a lot of information directly, but because of this it has more flexibility than STK.And the masters and experts in the forum are really really really friendly and patient, I wish you more friendships and more knowledge here.
Cheers!
Thank you,This is a good idea,Vincent has told me above, the same idea as you, I am still thinking on my own how to implement it
I had a problem when I tried. I understand you’re talking about comparing the X-axis velocity vector of the satellite with the X of the north vector of the ground station, right? Similar to if (s.Goetpvcoordinates ().getVelocity().getX()>sta1Frame.getNorth().getX()), again by the dot product of two vectors to determine whether it is zero.
Here’s how I solved it. I’m good for now. if(sta1Frame.getNorth().dotproduct (s.Goetpvcoordinates ().getvelocity ())<0)