/* Copyright 2002-2017 CS Systèmes d'Information * Licensed to CS Systèmes d'Information (CS) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * CS licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.orekit.bodies; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.junit.Assert; import org.junit.Test; import org.orekit.Utils; import org.orekit.errors.OrekitException; import org.orekit.frames.Frame; import org.orekit.frames.FramesFactory; import org.orekit.time.AbsoluteDate; import org.orekit.time.TimeScalesFactory; import org.orekit.utils.TimeStampedPVCoordinates; public class CelestialBodyFactoryTest { @Test public void getSun() throws OrekitException { Utils.setDataRoot("regular-data"); CelestialBody sun = CelestialBodyFactory.getSun(); Assert.assertNotNull(sun); } @Test public void clearCache() throws OrekitException { Utils.setDataRoot("regular-data"); CelestialBody sun = CelestialBodyFactory.getSun(); Assert.assertNotNull(sun); CelestialBodyFactory.clearCelestialBodyCache(); CelestialBody sun2 = CelestialBodyFactory.getSun(); Assert.assertNotNull(sun2); Assert.assertNotSame(sun, sun2); } @Test public void clearLoaders() throws OrekitException { Utils.setDataRoot("regular-data"); CelestialBody sun = CelestialBodyFactory.getSun(); Assert.assertNotNull(sun); CelestialBodyFactory.clearCelestialBodyLoaders(); CelestialBody sun2 = CelestialBodyFactory.getSun(); Assert.assertNotNull(sun2); Assert.assertNotSame(sun, sun2); CelestialBodyFactory.clearCelestialBodyLoaders(CelestialBodyFactory.SUN); CelestialBodyFactory.clearCelestialBodyCache(CelestialBodyFactory.SUN); CelestialBodyFactory.addDefaultCelestialBodyLoader(JPLEphemeridesLoader.DEFAULT_DE_SUPPORTED_NAMES); CelestialBody sun3 = CelestialBodyFactory.getSun(); Assert.assertNotNull(sun3); Assert.assertNotSame(sun, sun3); Assert.assertNotSame(sun2, sun3); } @Test public void testHorizon() throws OrekitException { // The following data are an excerpt from a telnet session with JPL Horizon system // note that in Horizon we selected Jupiter barycenter rather than Jupiter body center // this seems to match better the content of the DE-431 ephemeris // ******************************************************************************* // Ephemeris / PORT_LOGIN Mon Oct 26 04:53:43 2015 Pasadena, USA / Horizons // ******************************************************************************* // Target body name: Jupiter Barycenter (5) {source: DE-0431LE-0431} // Center body name: Solar System Barycenter (0) {source: DE-0431LE-0431} // Center-site name: BODY CENTER // ******************************************************************************* // Start time : A.D. 2000-Jan-01 00:00:00.0000 CT // Stop time : A.D. 2003-Dec-31 23:59:00.0000 CT // Step-size : 1440 minutes // ******************************************************************************* // Center geodetic : 0.00000000,0.00000000,0.0000000 {E-lon(deg),Lat(deg),Alt(km)} // Center cylindric: 0.00000000,0.00000000,0.0000000 {E-lon(deg),Dxy(km),Dz(km)} // Center radii : (undefined) // Output units : KM-S // Output format : 02 // Reference frame : ICRF/J2000.0 // Output type : GEOMETRIC cartesian states // Coordinate systm: Earth Mean Equator and Equinox of Reference Epoch // ******************************************************************************* // JDCT // X Y Z // VX VY VZ // ******************************************************************************* // $$SOE // 2451544.500000000 = A.D. 2000-Jan-01 00:00:00.0000 (TDB) // X = 5.978411018921824E+08 Y = 4.085508359611598E+08 Z = 1.605595308103096E+08 // VX=-7.892151874487445E+00 VY= 1.017751699703826E+01 VZ= 4.554715748011852E+00 // 2451545.500000000 = A.D. 2000-Jan-02 00:00:00.0000 (TDB) // X = 5.971584965869523E+08 Y = 4.094296790808872E+08 Z = 1.609528639632485E+08 // VX=-7.908893450088906E+00 VY= 1.016606978596496E+01 VZ= 4.550216570971850E+00 // 2451546.500000000 = A.D. 2000-Jan-03 00:00:00.0000 (TDB) // X = 5.964744456934582E+08 Y = 4.103075321378759E+08 Z = 1.613458079269412E+08 // VX=-7.925614558638352E+00 VY= 1.015459888397081E+01 VZ= 4.545706740033853E+00 // 2451547.500000000 = A.D. 2000-Jan-04 00:00:00.0000 (TDB) // X = 5.957889509819047E+08 Y = 4.111843930867567E+08 Z = 1.617383617815004E+08 // VX=-7.942315157290042E+00 VY= 1.014310432640078E+01 VZ= 4.541186269306714E+00 // 2451548.500000000 = A.D. 2000-Jan-05 00:00:00.0000 (TDB) // X = 5.951020142261952E+08 Y = 4.120602598852173E+08 Z = 1.621305246082588E+08 // VX=-7.958995203281466E+00 VY= 1.013158614867071E+01 VZ= 4.536655172931710E+00 // 2451549.500000000 = A.D. 2000-Jan-06 00:00:00.0000 (TDB) // X = 5.944136372039236E+08 Y = 4.129351304940084E+08 Z = 1.625222954897725E+08 // VX=-7.975654653933506E+00 VY= 1.012004438626713E+01 VZ= 4.532113465082445E+00 final TimeStampedPVCoordinates[] refPV = new TimeStampedPVCoordinates[] { createPV(2000, 1, 1, 5.978411018921824E+08, 4.085508359611598E+08, 1.605595308103096E+08, -7.892151874487445E+00, 1.017751699703826E+01, 4.554715748011852E+00), createPV(2000, 1, 2, 5.971584965869523E+08, 4.094296790808872E+08, 1.609528639632485E+08, -7.908893450088906E+00, 1.016606978596496E+01, 4.550216570971850E+00), createPV(2000, 1, 3, 5.964744456934582E+08, 4.103075321378759E+08, 1.613458079269412E+08, -7.925614558638352E+00, 1.015459888397081E+01, 4.545706740033853E+00), createPV(2000, 1, 4, 5.957889509819047E+08, 4.111843930867567E+08, 1.617383617815004E+08, -7.942315157290042E+00, 1.014310432640078E+01, 4.541186269306714E+00), createPV(2000, 1, 5, 5.951020142261952E+08, 4.120602598852173E+08, 1.621305246082588E+08, -7.958995203281466E+00, 1.013158614867071E+01, 4.536655172931710E+00), createPV(2000, 1, 6, 5.944136372039236E+08, 4.129351304940084E+08, 1.625222954897725E+08, -7.975654653933506E+00, 1.012004438626713E+01, 4.532113465082445E+00) }; Utils.setDataRoot("regular-data"); final CelestialBody jupiter = CelestialBodyFactory.getJupiter(); for (final TimeStampedPVCoordinates ref : refPV) { TimeStampedPVCoordinates testPV = jupiter.getPVCoordinates(ref.getDate(), FramesFactory.getICRF()); Assert.assertEquals(0.0, Vector3D.distance(ref.getPosition(), testPV.getPosition()), 4.0e-4); Assert.assertEquals(0.0, Vector3D.distance(ref.getVelocity(), testPV.getVelocity()), 1.0e-11); } } private TimeStampedPVCoordinates createPV(int year, int month, int day, double xKm, double yKm, double zKM, double vxKmS, double vyKms, double vzKms) { return new TimeStampedPVCoordinates(new AbsoluteDate(year, month, day, TimeScalesFactory.getTDB()), new Vector3D( xKm * 1000, yKm * 1000, zKM * 1000), new Vector3D(vxKmS * 1000, vyKms * 1000, vzKms * 1000)); } @Test public void testSerialization() throws OrekitException, IOException, ClassNotFoundException { Utils.setDataRoot("regular-data"); for (String name : new String[] { CelestialBodyFactory.SOLAR_SYSTEM_BARYCENTER, CelestialBodyFactory.SUN, CelestialBodyFactory.MERCURY, CelestialBodyFactory.VENUS, CelestialBodyFactory.EARTH_MOON, CelestialBodyFactory.EARTH, CelestialBodyFactory.MOON, CelestialBodyFactory.MARS, CelestialBodyFactory.JUPITER, CelestialBodyFactory.SATURN, CelestialBodyFactory.URANUS, CelestialBodyFactory.NEPTUNE, CelestialBodyFactory.PLUTO }) { CelestialBody original = CelestialBodyFactory.getBody(name); ByteArrayOutputStream bosBody = new ByteArrayOutputStream(); ObjectOutputStream oosBody = new ObjectOutputStream(bosBody); oosBody.writeObject(original); Assert.assertTrue(bosBody.size() > 400); Assert.assertTrue(bosBody.size() < 460); ByteArrayInputStream bisBody = new ByteArrayInputStream(bosBody.toByteArray()); ObjectInputStream oisBody = new ObjectInputStream(bisBody); CelestialBody deserializedBody = (CelestialBody) oisBody.readObject(); Assert.assertTrue(original == deserializedBody); ByteArrayOutputStream bosInertialFrame = new ByteArrayOutputStream(); ObjectOutputStream oosInertialFrame = new ObjectOutputStream(bosInertialFrame); oosInertialFrame.writeObject(original.getInertiallyOrientedFrame()); Assert.assertTrue(bosInertialFrame.size() > 400); Assert.assertTrue(bosInertialFrame.size() < 460); ByteArrayInputStream bisInertialFrame = new ByteArrayInputStream(bosInertialFrame.toByteArray()); ObjectInputStream oisInertialFrame = new ObjectInputStream(bisInertialFrame); Frame deserializedInertialFrame = (Frame) oisInertialFrame.readObject(); Assert.assertTrue(original.getInertiallyOrientedFrame() == deserializedInertialFrame); ByteArrayOutputStream bosBodyFrame = new ByteArrayOutputStream(); ObjectOutputStream oosBodyFrame = new ObjectOutputStream(bosBodyFrame); oosBodyFrame.writeObject(original.getBodyOrientedFrame()); Assert.assertTrue(bosBodyFrame.size() > 400); Assert.assertTrue(bosBodyFrame.size() < 460); ByteArrayInputStream bisBodyFrame = new ByteArrayInputStream(bosBodyFrame.toByteArray()); ObjectInputStream oisBodyFrame = new ObjectInputStream(bisBodyFrame); Frame deserializedBodyFrame = (Frame) oisBodyFrame.readObject(); Assert.assertTrue(original.getBodyOrientedFrame() == deserializedBodyFrame); } } @Test public void multithreadTest() throws OrekitException { Utils.setDataRoot("regular-data"); checkMultiThread(10, 100); } private void checkMultiThread(final int threads, final int runs) throws OrekitException { final AtomicReference<OrekitException> caught = new AtomicReference<OrekitException>(); ExecutorService executorService = Executors.newFixedThreadPool(threads); List<Future<?>> results = new ArrayList<Future<?>>(); for (int i = 0; i < threads; i++) { Future<?> result = executorService.submit(new Runnable() { public void run() { try { for (int run = 0; run < runs; run++) { CelestialBody mars = CelestialBodyFactory.getBody(CelestialBodyFactory.MARS); Assert.assertNotNull(mars); CelestialBodyFactory.clearCelestialBodyLoaders(); } } catch (OrekitException oe) { caught.set(oe); } } }); results.add(result); } try { executorService.shutdown(); executorService.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException ie) { Assert.fail(ie.getLocalizedMessage()); } for (Future<?> result : results) { Assert.assertTrue("Not all threads finished -> possible deadlock", result.isDone()); } if (caught.get() != null) { throw caught.get(); } } @Test public void testEarthMoonBarycenter() throws OrekitException { Utils.setDataRoot("regular-data/de405-ephemerides"); CelestialBody sun = CelestialBodyFactory.getSun(); CelestialBody mars = CelestialBodyFactory.getMars(); CelestialBody earth = CelestialBodyFactory.getEarth(); CelestialBody earthMoonBarycenter = CelestialBodyFactory.getEarthMoonBarycenter(); List<Frame> frames = Arrays.asList(FramesFactory.getEME2000(), FramesFactory.getGCRF(), sun.getInertiallyOrientedFrame(), mars.getInertiallyOrientedFrame(), earth.getInertiallyOrientedFrame()); AbsoluteDate date = new AbsoluteDate(1969, 7, 23, TimeScalesFactory.getTT()); final double refDistance = bodyDistance(sun, earthMoonBarycenter, date, frames.get(0)); for (Frame frame : frames) { Assert.assertEquals(frame.toString(), refDistance, bodyDistance(sun, earthMoonBarycenter, date, frame), 1.0e-14 * refDistance); } } private double bodyDistance(CelestialBody body1, CelestialBody body2, AbsoluteDate date, Frame frame) throws OrekitException { Vector3D body1Position = body1.getPVCoordinates(date, frame).getPosition(); Vector3D body2Position = body2.getPVCoordinates(date, frame).getPosition(); Vector3D bodyPositionDifference = body1Position.subtract(body2Position); return bodyPositionDifference.getNorm(); } }