diff --git a/.CI/README b/.CI/README new file mode 100644 index 0000000000000000000000000000000000000000..457c6ee3ebf080e149a211a73db41acbc55f2af4 --- /dev/null +++ b/.CI/README @@ -0,0 +1 @@ +A directory for Continuous Integration tooling. \ No newline at end of file diff --git a/.CI/maven-settings.xml b/.CI/maven-settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..6dd1f10984551a6c32c6fd00ea65dcb56de3dc7f --- /dev/null +++ b/.CI/maven-settings.xml @@ -0,0 +1,36 @@ + + + + + Nexus-Orekit + Maven Repository Manager + https://packages.orekit.org/repository/maven-public/ + central + + + + + ci-releases + ${env.NEXUS_USERNAME} + ${env.NEXUS_PASSWORD} + + + ci-snapshots + ${env.NEXUS_USERNAME} + ${env.NEXUS_PASSWORD} + + + \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 9c5f59236afbc4bd7e9a903af7924d98896e3415..fe57439af0219e7607b3ce197db20c11fac2fa5e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,6 +1,11 @@ pipeline { agent any + + environment { + MAVEN_CLI_OPTS = "-s .CI/maven-settings.xml" + } + tools { maven 'mvn-default' jdk 'openjdk-8' @@ -24,12 +29,29 @@ pipeline { if ( env.BRANCH_NAME ==~ /^release-[.0-9]+$/ ) { sh 'mvn verify assembly:single' } + else if ( env.BRANCH_NAME ==~ /^develop$/ ) { + sh 'mvn install site' + } else { sh 'mvn verify site' } } } } + + stage('Deploy') { + // Deploy to staging area only on branch develop or master + // Official deployment on oss.sonatype.org will be done manually + // NB: we skip tests on this stage + when { anyOf { branch 'develop' ; branch 'master' } } + steps { + withCredentials([usernamePassword(credentialsId: 'jenkins-at-nexus', + usernameVariable: 'NEXUS_USERNAME', + passwordVariable: 'NEXUS_PASSWORD')]) { + sh 'mvn $MAVEN_CLI_OPTS deploy -DskipTests=true -Pci-deploy' + } + } + } } post { diff --git a/README.md b/README.md index 7a412077a0d82e19e230f41d9b78ad5907c113c9..0000de4c9f4e77f5d76b03d577683c8e5bccb368 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ __Note:__ Our official repository is ## Documentation Project overview, architecture and development, detailed features list, -tutorials, Javadoc and a lot of other information is available on the +Javadoc and a lot of other information is available on the [Maven site](https://www.orekit.org/site-orekit-development/). ## Getting help diff --git a/checkstyle.xml b/checkstyle.xml index fd0750efdb892b5c8a7ac7fa9f1fa5a92c5ce9f2..02574ce23ffab188bca269d668994c8424cbc382 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -35,7 +35,6 @@ - @@ -46,7 +45,11 @@ - + + + @@ -57,12 +60,13 @@ + org.orekit orekit jar - 10.0 + 10.1-SNAPSHOT ORbit Extrapolation KIT http://www.orekit.org/ @@ -46,7 +46,9 @@ 1.6.8 1.6 3.0.0-M1 - 1.5 + <script type="text/x-mathjax-config">MathJax.Hub.Config({ TeX: { extensions: ["autoload.js"]}});</script> + <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML"></script> + 1.6 4.12 1.8 1.8 @@ -158,6 +160,13 @@ developer + + Yannick Jeandroz + yannick + + developer + + @@ -206,9 +215,6 @@ James Housden - - Yannick Jeandroz - François-Xavier Laffont @@ -239,6 +245,12 @@ Michael Turner + + Gabriele Serafini + + + Shiva Iyer + @@ -430,6 +442,7 @@ ${orekit.maven-javadoc-plugin.version} ${basedir}/src/main/java/org/orekit/overview.html + --allow-script-in-comments -header '${orekit.mathjax.config} ${orekit.mathjax.enable}' CS Systèmes d'information. All rights reserved.]]> https://docs.oracle.com/javase/8/docs/api/ @@ -664,6 +677,7 @@ ${orekit.maven-javadoc-plugin.version} ${basedir}/src/main/java/org/orekit/overview.html + --allow-script-in-comments -header '${orekit.mathjax.config} ${orekit.mathjax.enable}' CS Systèmes d'information. All rights reserved.]]> https://docs.oracle.com/javase/8/docs/api/ @@ -833,6 +847,43 @@ + + continuous-integration + + + + env.CI + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${orekit.maven-surefire-plugin.version} + + + + 1C + + + + + + + + ci-deploy + + + ci-releases + https://packages.orekit.org/repository/maven-releases/ + + + ci-snapshots + https://packages.orekit.org/repository/maven-snapshots/ + + + eclipse diff --git a/release-guide.md b/release-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..0afe81fa24016256912f4555e386e5335304dda5 --- /dev/null +++ b/release-guide.md @@ -0,0 +1,367 @@ +# Orekit Release Guide + +This release guide is largely inspired from [Hipparchus Release +Guide](https://www.hipparchus.org/release-guide.html). It lists the steps that +have been used in the past to release a new version of Orekit. When in doubt +ask the experts: Sébastien Dinot for website questions +and Luc Maisonobe for everything else. + +## Prerequisites + +1. Obtain private key of the Orekit Signing Key, key id: + `0802AB8C87B0B1AEC1C1C5871550FDBD6375C33B` +2. Register for account on OSSRH and associate it with the Orekit project, see: + https://central.sonatype.org/pages/ossrh-guide.html + +If you need help with either ask on the development section of the Orekit +forum. + +Once you have a SonaType OSS account, the corresponding credentials must be set +in the `servers` section of the `$HOME/.m2/settings.xml` file, using an id of +`ossrh`: + + + + ossrh + the user name to connect to the OSS site + the encrypted password + + + +Use `mvn -ep` to generate an encrypted password. + +## Install Graphviz 2.38 + +Graphviz (dot) 2.39 and above put too much blank space in the generated +diagrams. The bug has not yet been fixed in graphviz, so we have to use 2.38 or +earlier. The version in CentOS 7 works, the version in Ubuntu 18.04 does not. + +## Verify the status of develop branch + +Before anything, check on the [continuous integration +site](https://ci.orekit.org/job/Orekit/job/develop/) that everything is fine on +develop branch: + +* All tests pass; +* Code coverage with JaCoCo is up to the requirements; +* There are no Maven, Java, Javadoc, Checkstyle and SpotBugs error or warning. + +If not, fix the warnings and errors first! + +## Prepare Git branch for release + +Release will be performed on a dedicated branch, not directly on master or +develop branch. So a new branch must be created as follows and used for +everything else: + + git branch release-X.Y + git checkout release-X.Y + +## Update maven plugins versions + +Release is a good opportunity to update the maven plugin versions. They are all +gathered at one place, in a set of properties in `orekit/pom.xml`: + + + 3.1.11 + 0.8.3 + 3.1.1 + ... + +You can find the latest version of the plugins using the search feature at +[http://search.maven.org/#search](http://search.maven.org/#search). The +properties name all follow the pattern `orekit.some-plugin-name.version`, the +plugin name should be used in the web form to check for available versions. + +Beware that in some cases, the latest version cannot be used due to +incompatibilities. For example when a plugin was not recently updated and +conflicts appear with newer versions of its dependencies. + +Beware also that some plugins use configuration files that may need update too. +This is typically the case with `maven-checkstyle-plugin` and +`spotbugs-maven-plugin`. The `/checkstyle.xml` and +`/spotbugs-exclude-filter.xml` files may need to be checked. + +Before committing these changes, you have to check that everything works. So +run the following command: + + mvn clean + LANG=C mvn -Prelease site + +If something goes wrong, either fix it by changing the plugin configuration or +roll back to an earlier version of the plugin. + +Browse the generated site starting at page `target/site/index.html` and check +that everything is rendered properly. + +When everything runs fine and the generated site is OK, then you can commit the +changes: + + git add orekit/pom.xml orekit/checkstyle.xml orekit/spotbugs-exclude-filter.xml + git commit -m "Updated maven plugins versions." + +## Updating changes.xml + +Finalize the file `/src/changes/changes.xml` file. + +The release date and description, which are often only set to `TBD` during +development, must be set to appropriate values. The release date at this step +is only a guess one or two weeks in the future, in order to take into account +the 5 days release vote delay. + +Replace the `TBD` description with a text describing the version released: +state if it is a minor or major version, list the major features introduced by +the version etc. (see examples in descriptions of former versions). + +Commit the `changes.xml` file. + + git add src/changes/changes.xml + git commit -m "Updated changes.xml for official release." + +## Updating documentation + +Several files must be updated to take into account the new version: + +| file name | usage | required update | +|----------------------------------|----------------------------|--------------------------------------------------------------------------------------------------------| +| `build.xml` | building file for Ant users| Update project version number. Check all dependencies' versions are consistent with pom.xml | +| `src/site/markdown/index.md` | site home page | Update the text about the latest available version, including important changes from **changes.xml** | +| `src/site/markdown/downloads.md` | downloads links | Add a table with the links for files of the new versions, don't forget the date in the table caption | +| `src/site/markdown/faq.md` | FAQ | Add line to the table of dependencies. | + +Make sure the ant build works: `ant clean clean-lib jar javadoc`. + +Once the files have been updated, commit the changes: + + git add build.xml src/site/markdown/*.md + git commit -m "Updated documentation for the release." + +## Change library version number + +The `pom.xml` file contains the version number of the library. During +development, this version number has the form `X.Y-SNAPSHOT`. For release, the +`-SNAPSHOT` part must be removed. + +Commit the change: + + git add pom.xml + git commit -m "Dropped -SNAPSHOT in version number for official release." + +## Tag and sign the git repository + +When all previous steps have been performed, the local git repository holds the +final state of the sources and build files for the release. It must be tagged +and the tag must be signed. Note that before the vote is finished, the tag can +only signed with a `-RCx` suffix to denote Release Candidate. The final tag +without the `-RCx` suffix will be put once the vote succeeds, on the same +commit (which will therefore have two tags). Tagging and signing is done using +the following command, with `-RCn` replaced with the Release Candidate number: + + git tag X.Y-RCn -s -u 0802AB8C87B0B1AEC1C1C5871550FDBD6375C33B -m "Release Candidate n for version X.Y." + +The tag should be verified using command: + + git tag -v X.Y-RCn + +## Pushing the branch and the tag + +When the tag is ready, the branch and the tag must be pushed to Gitlab so +everyone can review it: + + git push --tags origin release-X.Y + +## Generating signed artifacts + +When these settings have been set up, generating the artifacts is done by +running the following commands: + + mvn clean + mvn assembly:single deploy -DskipStagingRepositoryClose=true -Prelease + +During the generation, maven will trigger gpg which will ask the user for the +pass phrase to access the signing key. Maven didn’t prompt for me, so I had to +add `-Dgpg.passphrase=[passphrase]` + +Once the commands ends, log into the SonaType OSS site +[https://oss.sonatype.org/](https://oss.sonatype.org/) and check the staging +repository contains the expected artifacts with associated signatures and +checksums: + +- orekit-X.Y.pom +- orekit-X.Y.jar +- orekit-X.Y-sources.jar +- orekit-X.Y-javadoc.jar + +The signature and checksum files have similar names with added extensions `.asc`, +`.md5` and `.sha1`. + +Sometimes, the deployment to Sonatype OSS site also adds files with double extension +`.asc.md5` and `.asc.sha1`, which are in fact checksum files on a signature file +and serve no purpose and can be deleted. + +It is also possible that you get `orekit-X.Y-src.zip` (together with signature and +checksums) uploaded to Sonatype OSS site. These files can also be deleted as they +are not intended to be downloaded using maven but will rather be made available +directly on Orekit website. + +Remove `orekit-X.Y.source-jar*` since they are duplicates of the +`orekit-X.Y-sources.jar*` artifacts. (We can’t figure out how to make maven +stop producing these duplicate artifacts). Then click the “Close” button. + + +## Site + +The site is generated locally using: + + LANG=C mvn site + +Once generated, the site can be archived and uploaded to the Orekit site: + + cd target/site + scp -r * user@host:/var/www/mvn-site/site-orekit-X.Y + + +If you need help with this step ask ask Sébastien Dinot +. + +## Calling for the vote + +Everything is now ready so the developers and PMC can vote for the release. +Create a post in the Orekit development category of the forum with a subject +line of the form: + + [VOTE] Releasing Orekit X.Y from release candidate n + +and content of the form: + + This is a VOTE in order to release version X.Y of the Orekit library. + Version X.Y is a maintenance release. + + + Highlights in the X.Y release are: + - feature 1 description + ... + - feature n description + + The release candidate n can be found on the GitLab repository as + tag X.Y-RCn in the release-X.Y branch: + + + The release notes can be read here: + . + + Maven artifacts are available at + . + + The votes will be tallied in 120 hours for now, on 20yy-mm-ddThh:mm:00Z + (this is UTC time). + +You should also ping PMC members so they are aware of the vote. Their +vote is essential for a release as per project governance. + +## Failed vote + +If the vote fails, the maven artifacts must be removed from OSS site by +dropping the repository and non-maven artifacts must be removed from the +`staging` directory in the Orekit site. Then a new release candidate must +be created, with a new number, a new tag and new artifacts. Another vote is +needed for this new release candidate. So make the necessary changes and then +start from the “Tag and sign the git repository” step. + +## Successful vote + +When the vote for a release candidate succeeds, follow the steps below to +publish the release. + +## Tag release version + +As the vote passed, a final signed tag must be added to the succeeding release +candidate, verified and pushed: + + git tag X.Y -s -u 0802AB8C87B0B1AEC1C1C5871550FDBD6375C33B -m "Version X.Y." + git tag -v X.Y + git push --tags + +## Merge release branch + +Merge the release branch into the `develop` branch to include any changes made. +Then updated the version numbers to prepare for the next development cycle. + + git checkout develop + git merge --no-ff release-X.Y + +Edit pom.xml version to SNAPSHOT and make space in the changelog for new +changes. Then commit and push. + +## Publish maven artifacts + +The maven artifacts must be published using OSS site to release the repository. +Select the Orekit repository and click the “Release” button in Nexus Repository +Manager. + +## Publish maven site + +The maven generated site should then be moved out of the staging directory. +Beware to create a new `site-orekit-X.Y` directory for the site and link the +latest version to it. This allows older versions to be kept available if +needed. + + mv staging/site-orekit-X.Y ./ + ln -snf site-orekit-X.Y site-orekit-latest + ln -snf site-orekit-X.Y site-orekit-development + +## Upload to gitlab + +Navigate to Self > Settings > Access Tokens. Enter a name, date, and check the +“api” box, then click “Create personal access token”. Copy the token into the +following command: + + for f in $( ls target/orekit-X.Y*{.zip,.jar}{,.asc} ) ; do + curl --request POST --header "PRIVATE-TOKEN: " --form "file=@$f" \ + https://gitlab.orekit.org/api/v4/projects/1/uploads + done + +Copy the URLs that are printed. + +Next, navigate to Projects > Orekit > Repository > Tags. Find the X.Y tag and +click the edit button to enter release notes. Paste the URLs copied from the +step above. + +Navigate to Projects > Orekit > Releases and make sure it looks nice. + +## Update Orekit site + +Several edits need to be made to the Orekit website. Fetch the current code: + + git clone https://gitlab.orekit.org/orekit/website-2015 + +Edit `download/.htaccess` and replace the URLs of of the 3 Orekit artifacts +with the ones created by gitlab in the previous step. + +Edit `download.html` and update the URLs to point to the new Orekit artifacts. + +Edit `_layouts/home.html` and edit the text of the bug button to use the new version. + +Edit `_config.yml` and add the new version to the list of versions. + +Run: + + jekyll serve + +and make sure the website looks nice. View it on http://localhost:4000/ + +If everything looks good publish the changes by running: + + ./bin/build_and_publish.sh + +## Mark resolved issues as closed + +In gitlab select all the issues included in the release and close them. +Navigate to Projects > Orekit > Issues. Search for `label:Resolved`. Make sure +they were all fixed in this release. Click “Edit Issues”, check all the boxes, +set milestone to X.Y and status to closed. + +## Announce release + +The last step is to announce the release by sending a mail to the announce +list. diff --git a/spotbugs-exclude-filter.xml b/spotbugs-exclude-filter.xml index f4deac491cea0de406acf5c2a1d4f9b56955d0f8..9cc8c82471482d43bd11b14d73fcdbd892ba3459 100644 --- a/spotbugs-exclude-filter.xml +++ b/spotbugs-exclude-filter.xml @@ -252,12 +252,6 @@ - - - - - - diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7758025f8a3c706db9a98ab4858b101a116deee6..7123246367e3614cbe3dd460b269c68a52f9c65e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -20,6 +20,175 @@ Orekit Changes + + + Added default constructors for DSSTZonal and DSSTTesseral. + + + Added OrekitException for unknown number of frequencies in ANTEX files. + + + Added OrekitException in the case where IONEX header is corrupted. + + + Added a specific test for issue 359 in BatchLSEstimatorTest. + The test verifies that a Newtonian attraction is known + by both the propagator builder and the propagator when + it is not added explicitly. + + + Added write of covariance matrices in OEMWriter. + + + Fixed origin transform in CcsdsModifierFrame. + + + Added SBAS orbit propagator. + + + Fixed null pointer exception in MultiplexedMeasurement. + + + Allow users to provide custom convergence checkers for + batch least squares orbit determination. + + + Added multiplexed measurements. + + + Fixed missed changes updates in ParameterDriversList embedding + other ParameterDriversList instances. + + + Moved tutorials to a separate sister project. + + + Added Laplace method for initial orbit determination. + + + Fixed DSST orbit determination tutorial. + + + Added IRNSS orbit propagator. + + + Added support for RINEX 3.04 files. + + + Fixed bugs in the derivatives computation in IodGooding. + Fixed bugs in IodLambert when there's more than an half revolution + between start and final position. + + + Fixed parsing of compact RINEX files with wrong key in header + produced by some Septentrio receivers. + + + Fixed parsing of compact RINEX files with missing types in header + produced by some Septentrio receivers. + + + Improve performance of AggregateBoundedPropagator by factor of 2. + + + Fixed parsing of compact RINEX files with many observation types. + + + Fixed poor design of GLONASS numerical propagator. + + + Fixed an issue in projection to flat ellipse. + + + Added lazily addition of Newtonian attraction to the DSST and + numerical propagator builders. + + + Added EllipticalFieldOfView (with two different ways to define the + ellipticity constraint) that can be used in FieldOfViewDetector, + GroundFieldOfViewDetector and FootprintOverlapDetector. + + + Fields of view with regular polygonal shape can now be built either + based on a defining cone inside the Fov and touching it at edges + middle points, or based on a defining cone outside the Fov and touching + it at vertices. + + + Added CircularFieldOfView that can be used in FieldOfViewDetector, + GroundFieldOfViewDetector and FootprintOverlapDetector. + + + Set up a general hierarchy for Field Of View with various shapes. At + start, it includes DoubleDihedraFieldOfView and PolygonalFieldOfView. + + + Added FilesListCrawler to load files from an explicit list. + + + Fix AbsoluteDate.compareTo() for future/past infinity. + + + Fixed wrong handling of spacecraft states in multi-satellites orbit determination + and multi-satellite measurements generation. + + + Improved contributing guide. + + + Make FieldOfView.getFootprint public. + + + Added combination of measurements. + + + Fix values of GPS C2D, L2D, D2D and S2D frequencies. + + + Add Nequick ionospheric model. + + + Fixed spurious empty line insertion during Rinex 2 decompression + when the number of observations per satellite is a multiple of 5 + + + Fixed decompression of very small negative values in Hatanaka + Compact RINEX format. + + + Orbit determination tutorials (and tests too) now supports compressed + measurement files (gzip, Unix compress, Hatanaka Compact RINEX). + + + Handle properly special events flags in Hatanaka Compact RINEX format. + + + Reset additional state changed by event handlers and not managed by any + additional state providers. + + + Added support for Hatanaka Compact RINEX format. + + + Cope with input stream readers that keep asking for new bytes after end + of Unix compressed files has been reached. + + + Added detection of some corrupted Unix-compressed files. + + + Fixed the Saastamoinen model when station altitude is bigger than 5000.0 meters. + + + Fixed too fast step increase in a bracketing attempt. + + + Added phase measurement builder. + + + Added getWavelength in GNSS Frequency. + + * @param inertialFrame inertial frame with respect to which orbit should be computed * @param type type of Local Orbital Frame diff --git a/src/main/java/org/orekit/bodies/Ellipse.java b/src/main/java/org/orekit/bodies/Ellipse.java index d6c25898cccacf73fad13ffd87ebe0a831d2daa8..27e288360025a061bc4314bb6b1d018a90f64622 100644 --- a/src/main/java/org/orekit/bodies/Ellipse.java +++ b/src/main/java/org/orekit/bodies/Ellipse.java @@ -221,31 +221,42 @@ public class Ellipse implements Serializable { FastMath.copySign(g * FastMath.sqrt(a2 - rEllipse * rEllipse), y)); } else { - final double k = FastMath.hypot(x / a, y / b); - double projectedX = x / k; - double projectedY = y / k; - double deltaX = Double.POSITIVE_INFINITY; - double deltaY = Double.POSITIVE_INFINITY; + + // initial point at evolute cusp along major axis + double omegaX = a * e2; + double omegaY = 0.0; + + double projectedX = x; + double projectedY = y; + double deltaX = Double.POSITIVE_INFINITY; + double deltaY = Double.POSITIVE_INFINITY; int count = 0; final double threshold = ANGULAR_THRESHOLD * ANGULAR_THRESHOLD * a2; while ((deltaX * deltaX + deltaY * deltaY) > threshold && count++ < 100) { // this loop usually converges in 3 iterations - final double omegaX = evoluteFactorX * projectedX * projectedX * projectedX; - final double omegaY = evoluteFactorY * projectedY * projectedY * projectedY; + + // find point at the intersection of ellipse and line going from query point to evolute point final double dx = x - omegaX; final double dy = y - omegaY; final double alpha = b2 * dx * dx + a2 * dy * dy; - final double beta = b2 * omegaX * dx + a2 * omegaY * dy; + final double betaPrime = b2 * omegaX * dx + a2 * omegaY * dy; final double gamma = b2 * omegaX * omegaX + a2 * omegaY * omegaY - a2 * b2; - final double deltaPrime = MathArrays.linearCombination(beta, beta, -alpha, gamma); - final double ratio = (beta <= 0) ? - (FastMath.sqrt(deltaPrime) - beta) / alpha : - -gamma / (FastMath.sqrt(deltaPrime) + beta); + final double deltaPrime = MathArrays.linearCombination(betaPrime, betaPrime, -alpha, gamma); + final double ratio = (betaPrime <= 0) ? + (FastMath.sqrt(deltaPrime) - betaPrime) / alpha : + -gamma / (FastMath.sqrt(deltaPrime) + betaPrime); final double previousX = projectedX; final double previousY = projectedY; projectedX = omegaX + ratio * dx; projectedY = omegaY + ratio * dy; + + // find new evolute point + omegaX = evoluteFactorX * projectedX * projectedX * projectedX; + omegaY = evoluteFactorY * projectedY * projectedY * projectedY; + + // compute convergence parameters deltaX = projectedX - previousX; deltaY = projectedY - previousY; + } return new Vector2D(FastMath.copySign(projectedX, p.getX()), projectedY); } diff --git a/src/main/java/org/orekit/bodies/OneAxisEllipsoid.java b/src/main/java/org/orekit/bodies/OneAxisEllipsoid.java index c42378b6cd141c5ff0f020231c7ab54e6a9ba596..93f4fc327349ec2dd43b580a17e456aa66684df0 100644 --- a/src/main/java/org/orekit/bodies/OneAxisEllipsoid.java +++ b/src/main/java/org/orekit/bodies/OneAxisEllipsoid.java @@ -44,6 +44,7 @@ import org.orekit.utils.TimeStampedPVCoordinates; * axis is the rotation or polar axis.

* @author Luc Maisonobe + * @author Guylaine Prat */ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape { @@ -88,6 +89,15 @@ public class OneAxisEllipsoid extends Ellipsoid implements BodyShape { * WGS84 * {@link org.orekit.utils.Constants#WGS84_EARTH_EQUATORIAL_RADIUS Constants.WGS84_EARTH_EQUATORIAL_RADIUS} * {@link org.orekit.utils.Constants#WGS84_EARTH_FLATTENING Constants.WGS84_EARTH_FLATTENING} + * IERS96 + * {@link org.orekit.utils.Constants#IERS96_EARTH_EQUATORIAL_RADIUS Constants.IERS96_EARTH_EQUATORIAL_RADIUS} + * {@link org.orekit.utils.Constants#IERS96_EARTH_FLATTENING Constants.IERS96_EARTH_FLATTENING} + * IERS2003 + * {@link org.orekit.utils.Constants#IERS2003_EARTH_EQUATORIAL_RADIUS Constants.IERS2003_EARTH_EQUATORIAL_RADIUS} + * {@link org.orekit.utils.Constants#IERS2003_EARTH_FLATTENING Constants.IERS2003_EARTH_FLATTENING} + * IERS2010 + * {@link org.orekit.utils.Constants#IERS2010_EARTH_EQUATORIAL_RADIUS Constants.IERS2010_EARTH_EQUATORIAL_RADIUS} + * {@link org.orekit.utils.Constants#IERS2010_EARTH_FLATTENING Constants.IERS2010_EARTH_FLATTENING} * * @param ae equatorial radius * @param f the flattening (f = (a-b)/a) diff --git a/src/main/java/org/orekit/data/AbstractListCrawler.java b/src/main/java/org/orekit/data/AbstractListCrawler.java new file mode 100644 index 0000000000000000000000000000000000000000..2c9db6950e90f2ff93796e96b31d373cf06586b3 --- /dev/null +++ b/src/main/java/org/orekit/data/AbstractListCrawler.java @@ -0,0 +1,152 @@ +/* Copyright 2002-2019 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.data; + +import java.io.IOException; +import java.io.InputStream; +import java.text.ParseException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.hipparchus.exception.DummyLocalizable; +import org.orekit.errors.OrekitException; + + +/** Provider for data files defined in a list. + *

+ * All {@link DataProvidersManager#addFilter(DataFilter) registered} + * {@link DataFilter filters} are applied. + *

+ *

+ * Zip archives entries are supported recursively. + *

+ * @since 10.1 + * @see DataProvidersManager + * @see NetworkCrawler + * @see FilesListCrawler + * @author Luc Maisonobe + */ +public abstract class AbstractListCrawler implements DataProvider { + + /** Inputs list. */ + private final List inputs; + + /** Build a data classpath crawler. + * @param inputs list of inputs (may be empty if {@link #addInput(Object) addInput} is called later) + */ + @SafeVarargs + protected AbstractListCrawler(final T... inputs) { + this.inputs = Arrays.stream(inputs).collect(Collectors.toList()); + } + + /** Add an input to the supported list. + * @param input input to add + */ + public void addInput(final T input) { + inputs.add(input); + } + + /** Get the list of inputs supported by the instance. + * @return unmodifiable view of the list of inputs supported by the instance + */ + public List getInputs() { + return Collections.unmodifiableList(inputs); + } + + /** Get the complete name of a input. + * @param input input to consider + * @return complete name of the input + */ + protected abstract String getCompleteName(T input); + + /** Get the base name of an input. + * @param input input to consider + * @return base name of the input + */ + protected abstract String getBaseName(T input); + + /** Get a zip/jar crawler for an input. + * @param input input to consider + * @return zip/jar crawler for an input + */ + protected abstract ZipJarCrawler getZipJarCrawler(T input); + + /** Get the stream to read from an input. + * @param input input to read from + * @return stream to read the content of the input + * @throws IOException if the input cannot be opened for reading + */ + protected abstract InputStream getStream(T input) throws IOException; + + /** {@inheritDoc} */ + public boolean feed(final Pattern supported, final DataLoader visitor) { + + try { + OrekitException delayedException = null; + boolean loaded = false; + for (T input : inputs) { + try { + + if (visitor.stillAcceptsData()) { + final String name = getCompleteName(input); + final String fileName = getBaseName(input); + if (ZIP_ARCHIVE_PATTERN.matcher(fileName).matches()) { + + // browse inside the zip/jar file + getZipJarCrawler(input).feed(supported, visitor); + loaded = true; + + } else { + + // apply all registered filters + NamedData data = new NamedData(fileName, () -> getStream(input)); + data = DataProvidersManager.getInstance().applyAllFilters(data); + + if (supported.matcher(data.getName()).matches()) { + // visit the current file + try (InputStream is = data.getStreamOpener().openStream()) { + visitor.loadData(is, name); + loaded = true; + } + } + + } + } + + } catch (OrekitException oe) { + // maybe the next path component will be able to provide data + // wait until all components have been tried + delayedException = oe; + } + } + + if (!loaded && delayedException != null) { + throw delayedException; + } + + return loaded; + + } catch (IOException | ParseException e) { + throw new OrekitException(e, new DummyLocalizable(e.getMessage())); + } + + } + +} diff --git a/src/main/java/org/orekit/data/ClasspathCrawler.java b/src/main/java/org/orekit/data/ClasspathCrawler.java index 2277db1bd68dceac0ebf8af11b09f1acc208b168..14a328890f0491f6a9befbb9bf538379cd299ed5 100644 --- a/src/main/java/org/orekit/data/ClasspathCrawler.java +++ b/src/main/java/org/orekit/data/ClasspathCrawler.java @@ -46,7 +46,8 @@ import org.orekit.errors.OrekitMessages; * data and another one for system-wide or general data. *

*

- * Gzip-compressed files are supported. + * All {@link DataProvidersManager#addFilter(DataFilter) registered} + * {@link DataFilter filters} are applied. *

*

* Zip archives entries are supported recursively. diff --git a/src/main/java/org/orekit/data/DataProvider.java b/src/main/java/org/orekit/data/DataProvider.java index b515ca54be71466d14ed1199f892aca5d7301503..1ad066fcd6dd0d0c1dad86162036b561a1e37d85 100644 --- a/src/main/java/org/orekit/data/DataProvider.java +++ b/src/main/java/org/orekit/data/DataProvider.java @@ -31,7 +31,7 @@ import java.util.regex.Pattern; * providers manager singleton}, or to let this manager use its default * configuration. Once registered, they will be used automatically whenever * some data needs to be loaded. This allow high level applications developers - * to customize Orekit data loading mechanism and get a tighter intergation of + * to customize Orekit data loading mechanism and get a tighter integration of * the library within their application. *

* @see DataLoader diff --git a/src/main/java/org/orekit/data/DataProvidersManager.java b/src/main/java/org/orekit/data/DataProvidersManager.java index cc81c27880bf370a89af4e9cda8c1689e5bd7e71..b9e66ddd7f8eefdc84e4a5d631cf8c097caeee2f 100644 --- a/src/main/java/org/orekit/data/DataProvidersManager.java +++ b/src/main/java/org/orekit/data/DataProvidersManager.java @@ -30,6 +30,7 @@ import java.util.regex.Pattern; import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitMessages; +import org.orekit.gnss.HatanakaCompressFilter; /** Singleton class managing all supported {@link DataProvider data providers}. @@ -102,6 +103,7 @@ public class DataProvidersManager { // set up predefined filters addFilter(new GzipFilter()); addFilter(new UnixCompressFilter()); + addFilter(new HatanakaCompressFilter()); predefinedFilters = filters.size(); diff --git a/src/main/java/org/orekit/data/DirectoryCrawler.java b/src/main/java/org/orekit/data/DirectoryCrawler.java index c20f371d8c83c9247db4bd4cfb28af54d815eec2..6008c68b180a40e326df7816d4bf4c5249ec47b5 100644 --- a/src/main/java/org/orekit/data/DirectoryCrawler.java +++ b/src/main/java/org/orekit/data/DirectoryCrawler.java @@ -39,7 +39,8 @@ import org.orekit.errors.OrekitMessages; * files are checked for loading. *

*

- * Gzip-compressed files are supported. + * All {@link DataProvidersManager#addFilter(DataFilter) registered} + * {@link DataFilter filters} are applied. *

*

* Zip archives entries are supported recursively. diff --git a/src/main/java/org/orekit/data/FilesListCrawler.java b/src/main/java/org/orekit/data/FilesListCrawler.java new file mode 100644 index 0000000000000000000000000000000000000000..0153fead38ec26b05533812341e81808ebc65bef --- /dev/null +++ b/src/main/java/org/orekit/data/FilesListCrawler.java @@ -0,0 +1,72 @@ +/* Copyright 2002-2019 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.data; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + + +/** Provider for data files in an explicit list. + + *

+ * Zip archives entries are supported recursively. + *

+ *

+ * This is a simple application of the visitor design pattern for + * list browsing. + *

+ * @see DataProvidersManager + * @since 10.1 + * @author Luc Maisonobe + */ +public class FilesListCrawler extends AbstractListCrawler { + + /** Build a data classpath crawler. + *

The default timeout is set to 10 seconds.

+ * @param inputs list of input files + */ + public FilesListCrawler(final File... inputs) { + super(inputs); + } + + /** {@inheritDoc} */ + @Override + protected String getCompleteName(final File input) { + return input.getPath(); + } + + /** {@inheritDoc} */ + @Override + protected String getBaseName(final File input) { + return input.getName(); + } + + /** {@inheritDoc} */ + @Override + protected ZipJarCrawler getZipJarCrawler(final File input) { + return new ZipJarCrawler(input); + } + + /** {@inheritDoc} */ + @Override + protected InputStream getStream(final File input) throws IOException { + return new FileInputStream(input); + } + +} diff --git a/src/main/java/org/orekit/data/FundamentalNutationArguments.java b/src/main/java/org/orekit/data/FundamentalNutationArguments.java index 9a5de66de52592ae73ecf6c01a772d83348578ac..9c8612bce38dab6b50f4fde46db6f24ee75d3a46 100644 --- a/src/main/java/org/orekit/data/FundamentalNutationArguments.java +++ b/src/main/java/org/orekit/data/FundamentalNutationArguments.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Serializable; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -179,7 +180,7 @@ public class FundamentalNutationArguments implements Serializable { final DefinitionParser definitionParser = new DefinitionParser(); // setup the reader - final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); int lineNumber = 0; // look for the reference date and the 14 polynomials diff --git a/src/main/java/org/orekit/data/NetworkCrawler.java b/src/main/java/org/orekit/data/NetworkCrawler.java index f2f5f80a2eace2506eac285843fe80467a9410f8..1811ed8d278314e53185386a1c5e63401bb45fe2 100644 --- a/src/main/java/org/orekit/data/NetworkCrawler.java +++ b/src/main/java/org/orekit/data/NetworkCrawler.java @@ -22,10 +22,6 @@ import java.io.InputStream; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; import org.hipparchus.exception.DummyLocalizable; import org.orekit.errors.OrekitException; @@ -59,7 +55,8 @@ import org.orekit.errors.OrekitException; * * *

- * Gzip-compressed files are supported. + * All {@link DataProvidersManager#addFilter(DataFilter) registered} + * {@link DataFilter filters} are applied. *

*

* Zip archives entries are supported recursively. @@ -71,27 +68,18 @@ import org.orekit.errors.OrekitException; * @see DataProvidersManager * @author Luc Maisonobe */ -public class NetworkCrawler implements DataProvider { - - /** URLs list. */ - private final List urls; +public class NetworkCrawler extends AbstractListCrawler { /** Connection timeout (milliseconds). */ private int timeout; /** Build a data classpath crawler. *

The default timeout is set to 10 seconds.

- * @param urls list of data file URLs + * @param inputs list of input file URLs */ - public NetworkCrawler(final URL... urls) { - - this.urls = new ArrayList(); - for (final URL url : urls) { - this.urls.add(url); - } - + public NetworkCrawler(final URL... inputs) { + super(inputs); timeout = 10000; - } /** Set the timeout for connection. @@ -102,66 +90,31 @@ public class NetworkCrawler implements DataProvider { } /** {@inheritDoc} */ - public boolean feed(final Pattern supported, final DataLoader visitor) { - + @Override + protected String getCompleteName(final URL input) { try { - OrekitException delayedException = null; - boolean loaded = false; - for (URL url : urls) { - try { - - if (visitor.stillAcceptsData()) { - final String name = url.toURI().toString(); - final String fileName = new File(url.getPath()).getName(); - if (ZIP_ARCHIVE_PATTERN.matcher(fileName).matches()) { - - // browse inside the zip/jar file - new ZipJarCrawler(url).feed(supported, visitor); - loaded = true; - - } else { - - // apply all registered filters - NamedData data = new NamedData(fileName, () -> getStream(url)); - data = DataProvidersManager.getInstance().applyAllFilters(data); - - if (supported.matcher(data.getName()).matches()) { - // visit the current file - try (InputStream input = data.getStreamOpener().openStream()) { - visitor.loadData(input, name); - loaded = true; - } - } - - } - } - - } catch (OrekitException oe) { - // maybe the next path component will be able to provide data - // wait until all components have been tried - delayedException = oe; - } - } - - if (!loaded && delayedException != null) { - throw delayedException; - } - - return loaded; - - } catch (URISyntaxException | IOException | ParseException e) { - throw new OrekitException(e, new DummyLocalizable(e.getMessage())); + return input.toURI().toString(); + } catch (URISyntaxException ue) { + throw new OrekitException(ue, new DummyLocalizable(ue.getMessage())); } + } + /** {@inheritDoc} */ + @Override + protected String getBaseName(final URL input) { + return new File(input.getPath()).getName(); } - /** Get the stream to read from the remote URL. - * @param url url to read from - * @return stream to read the content of the URL - * @throws IOException if the URL cannot be opened for reading - */ - private InputStream getStream(final URL url) throws IOException { - final URLConnection connection = url.openConnection(); + /** {@inheritDoc} */ + @Override + protected ZipJarCrawler getZipJarCrawler(final URL input) { + return new ZipJarCrawler(input); + } + + /** {@inheritDoc} */ + @Override + protected InputStream getStream(final URL input) throws IOException { + final URLConnection connection = input.openConnection(); connection.setConnectTimeout(timeout); return connection.getInputStream(); } diff --git a/src/main/java/org/orekit/data/PoissonSeriesParser.java b/src/main/java/org/orekit/data/PoissonSeriesParser.java index bc095591c9491534a3b37897f3ff3362f01fbe0c..d16b5933994beece6dc97f4e21acd12a3c669431 100644 --- a/src/main/java/org/orekit/data/PoissonSeriesParser.java +++ b/src/main/java/org/orekit/data/PoissonSeriesParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -524,7 +525,7 @@ public class PoissonSeriesParser { try { // setup the reader - final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); int lineNumber = 0; int expectedIndex = -1; int nTerms = -1; diff --git a/src/main/java/org/orekit/data/SimpleTimeStampedTableParser.java b/src/main/java/org/orekit/data/SimpleTimeStampedTableParser.java index 79f674b74c51bcd29dc2de5691ef7a46d2328773..cfe55cb02c9f2fc6309e6d07515efaae7d75f63e 100644 --- a/src/main/java/org/orekit/data/SimpleTimeStampedTableParser.java +++ b/src/main/java/org/orekit/data/SimpleTimeStampedTableParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -93,7 +94,7 @@ public class SimpleTimeStampedTableParser { try { // setup the reader - final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); final List table = new ArrayList(); diff --git a/src/main/java/org/orekit/data/UnixCompressFilter.java b/src/main/java/org/orekit/data/UnixCompressFilter.java index 0bb694130e908a80bce2221f7d7f13b3d73dca65..5eb95c5564ba8100e22c067c83ae901156673b3a 100644 --- a/src/main/java/org/orekit/data/UnixCompressFilter.java +++ b/src/main/java/org/orekit/data/UnixCompressFilter.java @@ -75,6 +75,9 @@ public class UnixCompressFilter implements DataFilter { /** Underlying compressed stream. */ private final InputStream input; + /** Indicator for end of input. */ + private boolean endOfInput; + /** Common sequences table. */ private final UncompressedSequence[] table; @@ -119,9 +122,9 @@ public class UnixCompressFilter implements DataFilter { ZInputStream(final String name, final InputStream input) throws IOException { - this.name = name; - this.input = input; - + this.name = name; + this.input = input; + this.endOfInput = false; // check header if (input.read() != MAGIC_HEADER_1 || input.read() != MAGIC_HEADER_2) { @@ -232,7 +235,14 @@ public class UnixCompressFilter implements DataFilter { if (previousSequence != null && available < table.length) { // update the table with the next uncompressed byte appended to previous sequence - final byte nextByte = (key == available) ? previousSequence.getByte(0) : table[key].getByte(0); + final byte nextByte; + if (key == available) { + nextByte = previousSequence.getByte(0); + } else if (table[key] != null) { + nextByte = table[key].getByte(0); + } else { + throw new OrekitIOException(OrekitMessages.CORRUPTED_FILE, name); + } table[available++] = new UncompressedSequence(previousSequence, nextByte); if (available > currentMaxKey && currentWidth < maxWidth) { // we need to increase the key size @@ -258,8 +268,9 @@ public class UnixCompressFilter implements DataFilter { public int read() throws IOException { if (currentSequence == null) { - if (!selectNext()) { + if (endOfInput || !selectNext()) { // we have reached end of data + endOfInput = true; return -1; } } diff --git a/src/main/java/org/orekit/data/ZipJarCrawler.java b/src/main/java/org/orekit/data/ZipJarCrawler.java index c671f446042c9286dc5eca9fbaa27291e62ab638..47c0dee194099e54c4fb1c49ef7636e8a19962f9 100644 --- a/src/main/java/org/orekit/data/ZipJarCrawler.java +++ b/src/main/java/org/orekit/data/ZipJarCrawler.java @@ -46,7 +46,8 @@ import org.orekit.errors.OrekitException; * loader, all of them will be loaded. *

*

- * Gzip-compressed files are supported. + * All {@link DataProvidersManager#addFilter(DataFilter) registered} + * {@link DataFilter filters} are applied. *

*

* Zip archives entries are supported recursively. diff --git a/src/main/java/org/orekit/errors/OrekitMessages.java b/src/main/java/org/orekit/errors/OrekitMessages.java index b5f9b7dcf7c6824ae6a2e516fd9037b90296fbc6..9d4dc9854477eed4edb654154a10438db847f642 100644 --- a/src/main/java/org/orekit/errors/OrekitMessages.java +++ b/src/main/java/org/orekit/errors/OrekitMessages.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; +import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.MissingResourceException; import java.util.PropertyResourceBundle; @@ -232,11 +233,20 @@ public enum OrekitMessages implements Localizable { INVALID_SATELLITE_SYSTEM("invalid satellite system {0}"), NO_TEC_DATA_IN_FILE_FOR_DATE("IONEX file {0} does not contain TEC data for date {1}"), INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE("number of maps {0} is inconsistent with header specification: {1}"), + NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER("file {0} does not contain latitude or longitude bondaries in its header section"), + NO_EPOCH_IN_IONEX_HEADER("file {0} does not contain epoch of first or last map in its header section"), ITRF_VERSIONS_PREFIX_ONLY("The first column of itrf-versions.conf is a plain " + "prefix that is matched against the name of each loaded file. It should " + "not contain any regular expression syntax or directory components, i.e. " + "\"/\" or \"\\\". Actual value: \"{0}\"."), - CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT("cannot compute aiming direction at singular point: latitude = {0}, longitude = {1}"); + CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT("cannot compute aiming direction at singular point: latitude = {0}, longitude = {1}"), + STEC_INTEGRATION_DID_NOT_CONVERGE("STEC integration did not converge"), + MODIP_GRID_NOT_LOADED("MODIP grid not be loaded from {0}"), + NEQUICK_F2_FM3_NOT_LOADED("NeQuick coefficient f2 or fm3 not be loaded from {0}"), + NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE("file {0} is not a supported Hatanaka-compressed file"), + INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS("invalid measurement types {0} and {1} for the combination of measurements {2}"), + INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS("frequencies {0} and {1} are incompatibles for the {2} combination"), + NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS("observations {0} and {1} are not in chronological dates"); // CHECKSTYLE: resume JavadocVariable check @@ -319,7 +329,7 @@ public enum OrekitMessages implements Localizable { if (stream != null) { try { // Only this line is changed to make it to read properties files as UTF-8. - bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); + bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8)); } finally { stream.close(); } diff --git a/src/main/java/org/orekit/estimation/iod/IodGibbs.java b/src/main/java/org/orekit/estimation/iod/IodGibbs.java index 964c8d82929820ab95719f1531c833970474b85a..8a73bd26279a2cff7de2908206972838704ecd49 100644 --- a/src/main/java/org/orekit/estimation/iod/IodGibbs.java +++ b/src/main/java/org/orekit/estimation/iod/IodGibbs.java @@ -118,6 +118,24 @@ public class IodGibbs { final AbsoluteDate date = date2; // compute the equivalent Keplerian orbit - return new KeplerianOrbit(pv, frame, date, mu); + final KeplerianOrbit orbit = new KeplerianOrbit(pv, frame, date, mu); + + //define the reverse orbit + final PVCoordinates pv2 = new PVCoordinates(r2, vlEci.scalarMultiply(-1)); + final KeplerianOrbit orbit2 = new KeplerianOrbit(pv2, frame, date, mu); + + //check which orbit is correct + final Vector3D estP3 = orbit.shiftedBy(date3.durationFrom(date2)). + getPVCoordinates().getPosition(); + final double dist = estP3.subtract(r3).getNorm(); + final Vector3D estP3_2 = orbit2.shiftedBy(date3.durationFrom(date2)). + getPVCoordinates().getPosition(); + final double dist2 = estP3_2.subtract(r3).getNorm(); + + if (dist <= dist2) { + return orbit; + } else { + return orbit2; + } } } diff --git a/src/main/java/org/orekit/estimation/iod/IodGooding.java b/src/main/java/org/orekit/estimation/iod/IodGooding.java index 325d5700024580e930397163a4bb2ccad8c6d2c8..23674096ec30a46e5bc4dac5612d0c3628d6d9a0 100644 --- a/src/main/java/org/orekit/estimation/iod/IodGooding.java +++ b/src/main/java/org/orekit/estimation/iod/IodGooding.java @@ -135,18 +135,21 @@ public class IodGooding { * @param lineOfSight1 line of sight 1 * @param dateObs1 date of observation 1 * @param lineOfSight2 line of sight 2 - * @param dateObs2 date of observation 1 + * @param dateObs2 date of observation 2 * @param lineOfSight3 line of sight 3 - * @param dateObs3 date of observation 1 + * @param dateObs3 date of observation 3 * @param rho1init initial guess of the range problem. range 1, in meters * @param rho3init initial guess of the range problem. range 3, in meters + * @param nRev number of complete revolutions between observation1 and 3 + * @param direction true if posigrade (short way) * @return an estimate of the Keplerian orbit */ public KeplerianOrbit estimate(final Vector3D O1, final Vector3D O2, final Vector3D O3, final Vector3D lineOfSight1, final AbsoluteDate dateObs1, final Vector3D lineOfSight2, final AbsoluteDate dateObs2, final Vector3D lineOfSight3, final AbsoluteDate dateObs3, - final double rho1init, final double rho3init) { + final double rho1init, final double rho3init, final int nRev, + final boolean direction) { this.date1 = dateObs1; @@ -167,8 +170,8 @@ public class IodGooding { // solve the range problem solveRangeProblem(rho1init / R, rho3init / R, dateObs3.durationFrom(dateObs1) / T, dateObs2.durationFrom(dateObs1) / T, - 0, - true, + nRev, + direction, lineOfSight1, lineOfSight2, lineOfSight3, maxiter); @@ -180,6 +183,32 @@ public class IodGooding { return gibbs.estimate(frame, p1, dateObs1, p2, dateObs2, p3, dateObs3); } + /** Orbit got from Observed Three Lines of Sight (angles only). + * assuming there was less than an half revolution between start and final date + * + * @param O1 Observer position 1 + * @param O2 Observer position 2 + * @param O3 Observer position 3 + * @param lineOfSight1 line of sight 1 + * @param dateObs1 date of observation 1 + * @param lineOfSight2 line of sight 2 + * @param dateObs2 date of observation 1 + * @param lineOfSight3 line of sight 3 + * @param dateObs3 date of observation 1 + * @param rho1init initial guess of the range problem. range 1, in meters + * @param rho3init initial guess of the range problem. range 3, in meters + * @return an estimate of the Keplerian orbit + */ + public KeplerianOrbit estimate(final Vector3D O1, final Vector3D O2, final Vector3D O3, + final Vector3D lineOfSight1, final AbsoluteDate dateObs1, + final Vector3D lineOfSight2, final AbsoluteDate dateObs2, + final Vector3D lineOfSight3, final AbsoluteDate dateObs3, + final double rho1init, final double rho3init) { + + return this.estimate(O1, O2, O3, lineOfSight1, dateObs1, lineOfSight2, dateObs2, + lineOfSight3, dateObs3, rho1init, rho3init, 0, true); + } + /** Solve the range problem when three line of sight are given. * * @param rho1init initial value for range R1, in meters @@ -248,14 +277,17 @@ public class IodGooding { // They should be zero when line of sight 2 and current direction for 2 from O2 are aligned. final Vector3D u = lineOfSight2.crossProduct(C); final Vector3D P = (u.crossProduct(lineOfSight2)).normalize(); - final Vector3D EN = (lineOfSight2.crossProduct(P)).normalize(); + final Vector3D ENt = lineOfSight2.crossProduct(P); - // if EN is zero we have a solution! - final double ENR = EN.getNorm(); + // if ENt is zero we have a solution! + final double ENR = ENt.getNorm(); if (ENR == 0.) { return true; } + //Normalize EN + final Vector3D EN = ENt.normalize(); + // Coordinate along 'F function' final double Fc = P.dotProduct(C); //Gc = EN.dotProduct(C); @@ -385,8 +417,8 @@ public class IodGooding { final double Gp1 = EN.dotProduct(Cp1); // derivatives df/drho1 and dg/drho1 - final double Fx = (Fp1 - Fm1) / (2 * dx); - final double Gx = (Gp1 - Gm1) / (2 * dx); + final double Fx = (Fp1 - Fm1) / (2. * dx); + final double Gx = (Gp1 - Gm1) / (2. * dx); final Vector3D Cm3 = getPositionOnLoS2 (lineOfSight1, x, lineOfSight3, y - dy, @@ -408,10 +440,10 @@ public class IodGooding { final double detJac = Fx * Gy - Fy * Gx; // Coefficients for the classical Newton-Raphson iterative method - FD[0] = Fx / detJac; - FD[1] = Fy / detJac; - GD[0] = Gx / detJac; - GD[1] = Gy / detJac; + FD[0] = Fx; + FD[1] = Fy; + GD[0] = Gx; + GD[1] = Gy; // Modified Newton-Raphson process, with Halley's method to have cubic convergence. // This requires computing second order derivatives. @@ -431,17 +463,17 @@ public class IodGooding { T13, T12, nrev, direction).subtract(vObserverPosition2); // f function value at (x1+dx1, x3+dx3) - final double Fp13 = P.dotProduct(Cp13) - F; + final double Fp13 = P.dotProduct(Cp13); // g function value at (x1+dx1, x3+dx3) final double Gp13 = EN.dotProduct(Cp13); - final Vector3D Cm13 = getPositionOnLoS2 (lineOfSight1, x + dx, - lineOfSight3, y + dy, + final Vector3D Cm13 = getPositionOnLoS2 (lineOfSight1, x - dx, + lineOfSight3, y - dy, T13, T12, nrev, direction).subtract(vObserverPosition2); - // f function value at (x1+dx1, x3+dx3) - final double Fm13 = P.dotProduct(Cm13) - F; - // g function value at (x1+dx1, x3+dx3) + // f function value at (x1-dx1, x3-dx3) + final double Fm13 = P.dotProduct(Cm13); + // g function value at (x1-dx1, x3-dx3) final double Gm13 = EN.dotProduct(Cm13); // Second order derivatives: d^2f / drho1drho3 and d^2g / drho1drho3 @@ -449,8 +481,8 @@ public class IodGooding { // 0.5 * (Fxx * dx / dy + Fyy * dy / dx); //double Gxy = Gp13 / (dx * dy) - (Gx / dy + Gy / dx) - // 0.5 * (Gxx * dx / dy + Gyy * dy / dx); - final double Fxy = (Fp13 + Fm13) / (2 * dx * dy) - 1.0 * (Fxx / 2 + Fyy / 2) - F / (dx * dy); - final double Gxy = (Gp13 + Gm13) / (2 * dx * dy) - 1.0 * (Gxx / 2 + Gyy / 2) - F / (dx * dy); + final double Fxy = (Fp13 + Fm13) / (2 * dx * dy) - 0.5 * (Fxx * dx / dy + Fyy * dy / dx) - F / (dx * dy); + final double Gxy = (Gp13 + Gm13) / (2 * dx * dy) - 0.5 * (Gxx * dx / dy + Gyy * dy / dx) - F / (dx * dy); // delta Newton Raphson, 1st order step final double dx3NR = -Gy * F / detJac; @@ -464,7 +496,7 @@ public class IodGooding { final double FxH = Fx + 0.5 * (Fxx * dx3NR + Fxy * dx1NR); final double FyH = Fy + 0.5 * (Fxy * dx3NR + Fxx * dx1NR); final double GxH = Gx + 0.5 * (Gxx * dx3NR + Gxy * dx1NR); - final double GyH = Gy + 0.5 * (Gxy * dx3NR + Fxy * dx1NR); + final double GyH = Gy + 0.5 * (Gxy * dx3NR + Gyy * dx1NR); // New Halley's method "Jacobian" FD[0] = FxH; @@ -489,7 +521,7 @@ public class IodGooding { private Vector3D getPositionOnLoS2(final Vector3D E1, final double RO1, final Vector3D E3, final double RO3, final double T13, final double T12, - final double nRev, final boolean posigrade) { + final int nRev, final boolean posigrade) { final Vector3D P1 = vObserverPosition1.add(E1.scalarMultiply(RO1)); R1 = P1.getNorm(); @@ -504,14 +536,13 @@ public class IodGooding { // compute the number of revolutions if (!posigrade) { - TH = FastMath.PI - TH; + TH = 2 * FastMath.PI - TH; } - TH = TH + nRev * FastMath.PI; // Solve the Lambert's problem to get the velocities at endpoints final double[] V1 = new double[2]; // work with non-dimensional units (MU=1) - final boolean exitflag = lambert.solveLambertPb(R1, R3, TH, T13, 0, V1); + final boolean exitflag = lambert.solveLambertPb(R1, R3, TH, T13, nRev, V1); if (exitflag) { // basis vectors diff --git a/src/main/java/org/orekit/estimation/iod/IodLambert.java b/src/main/java/org/orekit/estimation/iod/IodLambert.java index 5be53e67a1e3cf96ee00a7d66d995e0fac29be71..5f081196ffb02156847a16a0c085f6d40e128927 100644 --- a/src/main/java/org/orekit/estimation/iod/IodLambert.java +++ b/src/main/java/org/orekit/estimation/iod/IodLambert.java @@ -18,6 +18,8 @@ package org.orekit.estimation.iod; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.util.FastMath; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; import org.orekit.frames.Frame; import org.orekit.orbits.KeplerianOrbit; import org.orekit.time.AbsoluteDate; @@ -51,7 +53,7 @@ public class IodLambert { *

* The logic for setting {@code posigrade} and {@code nRev} is that the * sweep angle Δυ travelled by the object between {@code t1} and {@code t2} is - * 2π {@code nRev} - α if {@code posigrade} is false and 2π {@code nRev} + α + * 2π {@code nRev +1} - α if {@code posigrade} is false and 2π {@code nRev} + α * if {@code posigrade} is true, where α is the separation angle between * {@code p1} and {@code p2}, which is always computed between 0 and π * (because in 3D without a normal reference, vector angles cannot go past π). @@ -68,7 +70,7 @@ public class IodLambert { * then {@code posigrade} should be {@code true} and {@code nRev} should be 0. * If {@code t2} is more than half a period after {@code t1} but less than * one period after {@code t1}, {@code posigrade} should be {@code false} and - * {@code nRev} should be 1. + * {@code nRev} should be 0. *

* @param frame frame * @param posigrade flag indicating the direction of motion @@ -88,6 +90,11 @@ public class IodLambert { final double r2 = p2.getNorm(); final double tau = t2.durationFrom(t1); // in seconds + // Exception if t2 < t1 + if (tau < 0.0) { + throw new OrekitException(OrekitMessages.NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS, t1, t2); + } + // normalizing constants final double R = FastMath.max(r1, r2); // in m final double V = FastMath.sqrt(mu / R); // in m/s @@ -99,7 +106,6 @@ public class IodLambert { if (!posigrade) { dth = 2 * FastMath.PI - dth; } - dth = dth + nRev * 2 * FastMath.PI; // velocity vectors in the orbital plane, in the R-T frame final double[] Vdep = new double[2]; @@ -146,18 +152,15 @@ public class IodLambert { final int mRev, final double[] V1) { // decide whether to use the left or right branch (for multi-revolution // problems), and the long- or short way. - final boolean leftbranch = FastMath.signum(mRev) > 0; - int longway = 0; - if (tau > 0) { - longway = 1; + final boolean leftbranch = dth < FastMath.PI; + int longway = 1; + if (dth > FastMath.PI) { + longway = -1; } final int m = FastMath.abs(mRev); final double rtof = FastMath.abs(tau); - double theta = dth; - if (longway < 0) { - theta = 2 * FastMath.PI - dth; - } + final double theta = dth; // non-dimensional chord ||r2-r1|| final double chord = FastMath.sqrt(r1 * r1 + r2 * r2 - 2 * r1 * r2 * FastMath.cos(theta)); @@ -169,7 +172,7 @@ public class IodLambert { final double minSma = speri / 2.; // lambda parameter (Eq 7.6) - final double lambda = FastMath.sqrt(1 - chord / speri); + final double lambda = longway * FastMath.sqrt(1 - chord / speri); // reference tof value for the Newton solver final double logt = FastMath.log(rtof); diff --git a/src/main/java/org/orekit/estimation/iod/IodLaplace.java b/src/main/java/org/orekit/estimation/iod/IodLaplace.java new file mode 100644 index 0000000000000000000000000000000000000000..ee5ea3a5afa4399156abaa19ad37b9778a1c755b --- /dev/null +++ b/src/main/java/org/orekit/estimation/iod/IodLaplace.java @@ -0,0 +1,157 @@ +/* Copyright 2002-2019 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.estimation.iod; + +import org.hipparchus.analysis.solvers.LaguerreSolver; +import org.hipparchus.complex.Complex; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.linear.Array2DRowRealMatrix; +import org.hipparchus.linear.LUDecomposition; +import org.hipparchus.util.FastMath; +import org.orekit.frames.Frame; +import org.orekit.orbits.CartesianOrbit; +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.PVCoordinates; + +/** + * Laplace angles-only initial orbit determination, assuming Keplerian motion. + * An orbit is determined from three angular observations from the same site. + * + * + * Reference: + * Bate, R., Mueller, D. D., & White, J. E. (1971). Fundamentals of astrodynamics. + * New York: Dover Publications. + * + * @author Shiva Iyer + * @since 10.1 + */ +public class IodLaplace { + + /** Gravitational constant. */ + private final double mu; + + /** Constructor. + * + * @param mu gravitational constant + */ + public IodLaplace(final double mu) { + this.mu = mu; + } + + /** Estimate orbit from three line of sight angles from the same location. + * + * @param frame Intertial frame for observer coordinates and orbit estimate + * @param obsPva Observer coordinates at time obsDate2 + * @param obsDate1 date of observation 1 + * @param los1 line of sight unit vector 1 + * @param obsDate2 date of observation 2 + * @param los2 line of sight unit vector 2 + * @param obsDate3 date of observation 3 + * @param los3 line of sight unit vector 3 + * @return estimate of the orbit at the central date dateObs2 or null if + * no estimate is possible with the given data + */ + public CartesianOrbit estimate(final Frame frame, final PVCoordinates obsPva, + final AbsoluteDate obsDate1, final Vector3D los1, + final AbsoluteDate obsDate2, final Vector3D los2, + final AbsoluteDate obsDate3, final Vector3D los3) { + // The first observation is taken as t1 = 0 + final double t2 = obsDate2.durationFrom(obsDate1); + final double t3 = obsDate3.durationFrom(obsDate1); + + // Calculate the first and second derivatives of the Line Of Sight vector at t2 + final Vector3D Ldot = los1.scalarMultiply((t2 - t3) / (t2 * t3)). + add(los2.scalarMultiply((2.0 * t2 - t3) / (t2 * (t2 - t3)))). + add(los3.scalarMultiply(t2 / (t3 * (t3 - t2)))); + final Vector3D Ldotdot = los1.scalarMultiply(2.0 / (t2 * t3)). + add(los2.scalarMultiply(2.0 / (t2 * (t2 - t3)))). + add(los3.scalarMultiply(2.0 / (t3 * (t3 - t2)))); + + // The determinant will vanish if the observer lies in the plane of the orbit at t2 + final double D = 2.0 * getDeterminant(los2, Ldot, Ldotdot); + if (FastMath.abs(D) < 1.0E-14) { + return null; + } + + final double Dsq = D * D; + final double R = obsPva.getPosition().getNorm(); + final double RdotL = obsPva.getPosition().dotProduct(los2); + + final double D1 = getDeterminant(los2, Ldot, obsPva.getAcceleration()); + final double D2 = getDeterminant(los2, Ldot, obsPva.getPosition()); + + // Coefficients of the 8th order polynomial we need to solve to determine "r" + final double[] coeff = new double[] {-4.0 * mu * mu * D2 * D2 / Dsq, + 0.0, + 0.0, + 4.0 * mu * D2 * (RdotL / D - 2.0 * D1 / Dsq), + 0.0, + 0.0, + 4.0 * D1 * RdotL / D - 4.0 * D1 * D1 / Dsq - R * R, 0.0, + 1.0}; + + // Use the Laguerre polynomial solver and take the initial guess to be + // 5 times the observer's position magnitude + final LaguerreSolver solver = new LaguerreSolver(1E-10, 1E-10, 1E-10); + final Complex[] roots = solver.solveAllComplex(coeff, 5.0 * R); + + // We consider "r" to be the positive real root with the largest magnitude + double rMag = 0.0; + for (int i = 0; i < roots.length; i++) { + if (roots[i].getReal() > rMag && + FastMath.abs(roots[i].getImaginary()) < solver.getAbsoluteAccuracy()) { + rMag = roots[i].getReal(); + } + } + if (rMag == 0.0) { + return null; + } + + // Calculate rho, the slant range from the observer to the satellite at t2. + // This yields the "r" vector, which is the satellite's position vector at t2. + final double rCubed = rMag * rMag * rMag; + final double rho = -2.0 * D1 / D - 2.0 * mu * D2 / (D * rCubed); + final Vector3D posVec = los2.scalarMultiply(rho).add(obsPva.getPosition()); + + // Calculate rho_dot at t2, which will yield the satellite's velocity vector at t2 + final double D3 = getDeterminant(los2, obsPva.getAcceleration(), Ldotdot); + final double D4 = getDeterminant(los2, obsPva.getPosition(), Ldotdot); + final double rhoDot = -D3 / D - mu * D4 / (D * rCubed); + final Vector3D velVec = los2.scalarMultiply(rhoDot). + add(Ldot.scalarMultiply(rho)). + add(obsPva.getVelocity()); + + // Return the estimated orbit + return new CartesianOrbit(new PVCoordinates(posVec, velVec), frame, obsDate2, mu); + } + + /** Calculate the determinant of the matrix with given column vectors. + * + * @param col0 Matrix column 0 + * @param col1 Matrix column 1 + * @param col2 Matrix column 2 + * @return matrix determinant + * + */ + private double getDeterminant(final Vector3D col0, final Vector3D col1, final Vector3D col2) { + final Array2DRowRealMatrix mat = new Array2DRowRealMatrix(3, 3); + mat.setColumn(0, col0.toArray()); + mat.setColumn(1, col1.toArray()); + mat.setColumn(2, col2.toArray()); + return new LUDecomposition(mat).getDeterminant(); + } +} diff --git a/src/main/java/org/orekit/estimation/leastsquares/BatchLSEstimator.java b/src/main/java/org/orekit/estimation/leastsquares/BatchLSEstimator.java index f13e2eb2c5d7326c65d34a99b70f3d10db13432a..50d55680a90a7ecb56b0811567f06e4e58a1acda 100644 --- a/src/main/java/org/orekit/estimation/leastsquares/BatchLSEstimator.java +++ b/src/main/java/org/orekit/estimation/leastsquares/BatchLSEstimator.java @@ -72,8 +72,8 @@ public class BatchLSEstimator { /** Solver for least squares problem. */ private final LeastSquaresOptimizer optimizer; - /** Convergence threshold on normalized parameters. */ - private double parametersConvergenceThreshold; + /** Convergence checker. */ + private ConvergenceChecker convergenceChecker; /** Builder for the least squares problem. */ private final LeastSquaresBuilder lsBuilder; @@ -121,12 +121,13 @@ public class BatchLSEstimator { this.builders = propagatorBuilder; this.measurements = new ArrayList>(); this.optimizer = optimizer; - this.parametersConvergenceThreshold = Double.NaN; this.lsBuilder = new LeastSquaresBuilder(); this.observer = null; this.estimations = null; this.orbits = new Orbit[builders.length]; + setParametersConvergenceThreshold(Double.NaN); + // our model computes value and Jacobian in one call, // so we don't use the lazy evaluation feature lsBuilder.lazyEvaluation(false); @@ -286,13 +287,35 @@ public class BatchLSEstimator { * the scale is often small (typically about 1 m for orbital positions * for example), then the threshold should not be too small. A value * of 10⁻³ is often quite accurate. + *

+ *

+ * Calling this method overrides any checker that could have been set + * beforehand by calling {@link #setConvergenceChecker(ConvergenceChecker)}. + * Both methods are mutually exclusive. + *

* * @param parametersConvergenceThreshold convergence threshold on * normalized parameters (dimensionless, related to parameters scales) + * @see #setConvergenceChecker(ConvergenceChecker) * @see EvaluationRmsChecker */ public void setParametersConvergenceThreshold(final double parametersConvergenceThreshold) { - this.parametersConvergenceThreshold = parametersConvergenceThreshold; + setConvergenceChecker((iteration, previous, current) -> + current.getPoint().getLInfDistance(previous.getPoint()) <= parametersConvergenceThreshold); + } + + /** Set a custom convergence checker. + *

+ * Calling this method overrides any checker that could have been set + * beforehand by calling {@link #setParametersConvergenceThreshold(double)}. + * Both methods are mutually exclusive. + *

+ * @param convergenceChecker convergence checker to set + * @see #setParametersConvergenceThreshold(double) + * @since 10.1 + */ + public void setConvergenceChecker(final ConvergenceChecker convergenceChecker) { + this.convergenceChecker = convergenceChecker; } /** Estimate the orbital, propagation and measurements parameters. @@ -398,16 +421,7 @@ public class BatchLSEstimator { estimatedPropagatorParameters, estimatedMeasurementsParameters)); - lsBuilder.checker(new ConvergenceChecker() { - /** {@inheritDoc} */ - @Override - public boolean converged(final int iteration, - final LeastSquaresProblem.Evaluation previous, - final LeastSquaresProblem.Evaluation current) { - final double lInf = current.getPoint().getLInfDistance(previous.getPoint()); - return lInf <= parametersConvergenceThreshold; - } - }); + lsBuilder.checker(convergenceChecker); // set up the problem to solve final LeastSquaresProblem problem = new TappedLSProblem(lsBuilder.build(), diff --git a/src/main/java/org/orekit/estimation/leastsquares/MeasurementHandler.java b/src/main/java/org/orekit/estimation/leastsquares/MeasurementHandler.java index bd911179bb276a460b0204e327334a1de3c7d217..0958e526230828f4bef4ef06c8cfb04745bf3c4e 100644 --- a/src/main/java/org/orekit/estimation/leastsquares/MeasurementHandler.java +++ b/src/main/java/org/orekit/estimation/leastsquares/MeasurementHandler.java @@ -20,6 +20,7 @@ import java.util.List; import org.orekit.errors.OrekitInternalError; import org.orekit.estimation.measurements.EstimatedMeasurement; +import org.orekit.estimation.measurements.ObservableSatellite; import org.orekit.estimation.measurements.ObservedMeasurement; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.sampling.MultiSatStepHandler; @@ -90,7 +91,8 @@ class MeasurementHandler implements MultiSatStepHandler { // estimate the theoretical measurement final SpacecraftState[] states = new SpacecraftState[observed.getSatellites().size()]; for (int i = 0; i < states.length; ++i) { - states[i] = interpolators.get(i).getInterpolatedState(next.getDate()); + final ObservableSatellite satellite = observed.getSatellites().get(i); + states[i] = interpolators.get(satellite.getPropagatorIndex()).getInterpolatedState(next.getDate()); } final EstimatedMeasurement estimated = observed.estimate(model.getIterationsCount(), model.getEvaluationsCount(), diff --git a/src/main/java/org/orekit/estimation/measurements/AngularAzEl.java b/src/main/java/org/orekit/estimation/measurements/AngularAzEl.java index f6bbcca186fbe6b33b6c10873628cceb056a882a..4392e8a59ea2878326b261d47ff56d6ed632eee1 100644 --- a/src/main/java/org/orekit/estimation/measurements/AngularAzEl.java +++ b/src/main/java/org/orekit/estimation/measurements/AngularAzEl.java @@ -84,8 +84,7 @@ public class AngularAzEl extends AbstractMeasurement { protected EstimatedMeasurement theoreticalEvaluation(final int iteration, final int evaluation, final SpacecraftState[] states) { - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState state = states[0]; // Azimuth/elevation derivatives are computed with respect to spacecraft state in inertial frame // and station parameters diff --git a/src/main/java/org/orekit/estimation/measurements/AngularRaDec.java b/src/main/java/org/orekit/estimation/measurements/AngularRaDec.java index a11c6019ff490d45d34fd40097a9ee0323313b7c..44d1695e9387ec3dae50bee37186b88760357f6b 100644 --- a/src/main/java/org/orekit/estimation/measurements/AngularRaDec.java +++ b/src/main/java/org/orekit/estimation/measurements/AngularRaDec.java @@ -99,8 +99,7 @@ public class AngularRaDec extends AbstractMeasurement { protected EstimatedMeasurement theoreticalEvaluation(final int iteration, final int evaluation, final SpacecraftState[] states) { - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState state = states[0]; // Right Ascension/elevation (in reference frame )derivatives are computed with respect to spacecraft state in inertial frame // and station parameters diff --git a/src/main/java/org/orekit/estimation/measurements/EstimatedMeasurement.java b/src/main/java/org/orekit/estimation/measurements/EstimatedMeasurement.java index 09b663a362aaebba05f27a8fb7d384afc9913436..dec91692e2c7f22bc32a128183e2066f58444328 100644 --- a/src/main/java/org/orekit/estimation/measurements/EstimatedMeasurement.java +++ b/src/main/java/org/orekit/estimation/measurements/EstimatedMeasurement.java @@ -179,6 +179,18 @@ public class EstimatedMeasurement> implements C this.status = status; } + /** Get state size. + *

+ * Warning, the {@link #setStateDerivatives(int, double[][])} + * method must have been called before this method is called. + *

+ * @return state size + * @since 10.1 + */ + public int getStateSize() { + return stateDerivatives[0][0].length; + } + /** Get the partial derivatives of the {@link #getEstimatedValue() * simulated measurement} with respect to state Cartesian coordinates. * @param index index of the state, according to the {@code states} diff --git a/src/main/java/org/orekit/estimation/measurements/InterSatellitesRange.java b/src/main/java/org/orekit/estimation/measurements/InterSatellitesRange.java index 83aeb1124a6491df46d06669b1cbd4155e5060a1..80366e6c50a6b805dfd2128128b4991b967ad14e 100644 --- a/src/main/java/org/orekit/estimation/measurements/InterSatellitesRange.java +++ b/src/main/java/org/orekit/estimation/measurements/InterSatellitesRange.java @@ -124,19 +124,17 @@ public class InterSatellitesRange extends AbstractMeasurement pvaL = getCoordinates(stateL, 0, factory); - final ObservableSatellite remote = getSatellites().get(1); - final SpacecraftState stateR = states[remote.getPropagatorIndex()]; - final TimeStampedFieldPVCoordinates pvaR = getCoordinates(stateR, 6, factory); + final SpacecraftState local = states[0]; + final TimeStampedFieldPVCoordinates pvaL = getCoordinates(local, 0, factory); + final SpacecraftState remote = states[1]; + final TimeStampedFieldPVCoordinates pvaR = getCoordinates(remote, 6, factory); // compute propagation times // (if state has already been set up to pre-compensate propagation delay, // we will have delta == tauD and transitState will be the same as state) // downlink delay - final DerivativeStructure dtl = local.getClockOffsetDriver().getValue(factory, indices); + final DerivativeStructure dtl = getSatellites().get(0).getClockOffsetDriver().getValue(factory, indices); final FieldAbsoluteDate arrivalDate = new FieldAbsoluteDate(getDate(), dtl.negate()); @@ -145,7 +143,7 @@ public class InterSatellitesRange extends AbstractMeasurement(this, iteration, evaluation, new SpacecraftState[] { - stateL.shiftedBy(deltaMTauD.getValue()), - stateR.shiftedBy(deltaMTauD.getValue()) + local.shiftedBy(deltaMTauD.getValue()), + remote.shiftedBy(deltaMTauD.getValue()) }, new TimeStampedPVCoordinates[] { - stateL.shiftedBy(delta - tauD.getValue() - tauU.getValue()).getPVCoordinates(), - stateR.shiftedBy(delta - tauD.getValue()).getPVCoordinates(), - stateL.shiftedBy(delta).getPVCoordinates() + local.shiftedBy(delta - tauD.getValue() - tauU.getValue()).getPVCoordinates(), + remote.shiftedBy(delta - tauD.getValue()).getPVCoordinates(), + local.shiftedBy(delta).getPVCoordinates() }); // Range value @@ -177,15 +175,15 @@ public class InterSatellitesRange extends AbstractMeasurement(this, iteration, evaluation, new SpacecraftState[] { - stateL.shiftedBy(deltaMTauD.getValue()), - stateR.shiftedBy(deltaMTauD.getValue()) + local.shiftedBy(deltaMTauD.getValue()), + remote.shiftedBy(deltaMTauD.getValue()) }, new TimeStampedPVCoordinates[] { - stateR.shiftedBy(delta - tauD.getValue()).getPVCoordinates(), - stateL.shiftedBy(delta).getPVCoordinates() + remote.shiftedBy(delta - tauD.getValue()).getPVCoordinates(), + local.shiftedBy(delta).getPVCoordinates() }); // Clock offsets - final DerivativeStructure dtr = remote.getClockOffsetDriver().getValue(factory, indices); + final DerivativeStructure dtr = getSatellites().get(1).getClockOffsetDriver().getValue(factory, indices); // Range value range = tauD.add(dtl).subtract(dtr).multiply(Constants.SPEED_OF_LIGHT); diff --git a/src/main/java/org/orekit/estimation/measurements/MultiplexedMeasurement.java b/src/main/java/org/orekit/estimation/measurements/MultiplexedMeasurement.java new file mode 100644 index 0000000000000000000000000000000000000000..ae097af5b944de0021bedf80bff95e8380df1f6f --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/MultiplexedMeasurement.java @@ -0,0 +1,277 @@ +/* Copyright 2002-2019 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.estimation.measurements; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import org.orekit.propagation.SpacecraftState; +import org.orekit.utils.ParameterDriver; +import org.orekit.utils.ParameterDriversList; +import org.orekit.utils.TimeStampedPVCoordinates; + +/** Class multiplexing several measurements as one. + *

+ * Date comes from the first measurement, observed and estimated + * values result from gathering all underlying measurements values. + * + * @author Luc Maisonobe + * @since 10.1 + */ +public class MultiplexedMeasurement extends AbstractMeasurement { + + /** Multiplexed measurements. */ + private final List> observedMeasurements; + + /** Multiplexed measurements. */ + private final List> estimatedMeasurements; + + /** Multiplexed parameters drivers. */ + private ParameterDriversList parametersDrivers; + + /** Total dimension. */ + private final int dimension; + + /** Total number of satellites involved. */ + private final int nbSat; + + /** States mapping. */ + private final int[][] mapping; + + /** Simple constructor. + * @param measurements measurements to multiplex + * @since 10.1 + */ + public MultiplexedMeasurement(final List> measurements) { + super(measurements.get(0).getDate(), + multiplex(measurements, m -> m.getObservedValue()), + multiplex(measurements, m -> m.getTheoreticalStandardDeviation()), + multiplex(measurements, m -> m.getBaseWeight()), + multiplex(measurements)); + + this.observedMeasurements = measurements; + this.estimatedMeasurements = new ArrayList<>(); + this.parametersDrivers = new ParameterDriversList(); + + // gather parameters drivers + int dim = 0; + for (final ObservedMeasurement m : measurements) { + for (final ParameterDriver driver : m.getParametersDrivers()) { + parametersDrivers.add(driver); + } + dim += m.getDimension(); + } + parametersDrivers.sort(); + for (final ParameterDriver driver : parametersDrivers.getDrivers()) { + addParameterDriver(driver); + } + this.dimension = dim; + + // set up states mappings for observed satellites + final List deduplicated = getSatellites(); + this.nbSat = deduplicated.size(); + this.mapping = new int[measurements.size()][]; + for (int i = 0; i < mapping.length; ++i) { + final List satellites = measurements.get(i).getSatellites(); + mapping[i] = new int[satellites.size()]; + for (int j = 0; j < mapping[i].length; ++j) { + final int index = satellites.get(j).getPropagatorIndex(); + for (int k = 0; k < nbSat; ++k) { + if (deduplicated.get(k).getPropagatorIndex() == index) { + mapping[i][j] = k; + break; + } + } + } + } + + } + + /** Get the underlying measurements. + * @return underlying measurements + */ + public List> getMeasurements() { + return observedMeasurements; + } + + /** Get the underlying estimated measurements. + * @return underlying estimated measurements + */ + public List> getEstimatedMeasurements() { + return estimatedMeasurements; + } + + /** {@inheritDoc} */ + @Override + protected EstimatedMeasurement theoreticalEvaluation(final int iteration, final int evaluation, + final SpacecraftState[] states) { + + final SpacecraftState[] evaluationStates = new SpacecraftState[nbSat]; + final List participants = new ArrayList<>(); + final double[] value = new double[dimension]; + + // loop over all multiplexed measurements + estimatedMeasurements.clear(); + int index = 0; + for (int i = 0; i < observedMeasurements.size(); ++i) { + + // filter states involved in the current measurement + final SpacecraftState[] filteredStates = new SpacecraftState[mapping[i].length]; + for (int j = 0; j < mapping[i].length; ++j) { + filteredStates[j] = states[mapping[i][j]]; + } + + // perform evaluation + final EstimatedMeasurement eI = observedMeasurements.get(i).estimate(iteration, evaluation, filteredStates); + estimatedMeasurements.add(eI); + + // extract results + final double[] valueI = eI.getEstimatedValue(); + System.arraycopy(valueI, 0, value, index, valueI.length); + index += valueI.length; + + // extract states + final SpacecraftState[] statesI = eI.getStates(); + for (int j = 0; j < mapping[i].length; ++j) { + evaluationStates[mapping[i][j]] = statesI[j]; + } + + } + + // create multiplexed estimation + final EstimatedMeasurement multiplexed = + new EstimatedMeasurement<>(this, iteration, evaluation, + evaluationStates, + participants.toArray(new TimeStampedPVCoordinates[0])); + + // copy multiplexed value + multiplexed.setEstimatedValue(value); + + // combine derivatives + final int stateSize = estimatedMeasurements.get(0).getStateSize(); + final double[] zeroDerivative = new double[stateSize]; + final double[][][] stateDerivatives = new double[nbSat][dimension][]; + for (final double[][] m : stateDerivatives) { + Arrays.fill(m, zeroDerivative); + } + + final Map parametersDerivatives = new IdentityHashMap<>(); + index = 0; + for (int i = 0; i < observedMeasurements.size(); ++i) { + + final EstimatedMeasurement eI = estimatedMeasurements.get(i); + final int idx = index; + final int dimI = eI.getObservedMeasurement().getDimension(); + + // state derivatives + for (int j = 0; j < mapping[i].length; ++j) { + System.arraycopy(eI.getStateDerivatives(j), 0, + stateDerivatives[mapping[i][j]], index, + dimI); + } + + // parameters derivatives + eI.getDerivativesDrivers().forEach(driver -> { + final ParameterDriversList.DelegatingDriver delegating = parametersDrivers.findByName(driver.getName()); + double[] derivatives = parametersDerivatives.get(delegating); + if (derivatives == null) { + derivatives = new double[dimension]; + parametersDerivatives.put(delegating, derivatives); + } + System.arraycopy(eI.getParameterDerivatives(driver), 0, derivatives, idx, dimI); + }); + + index += dimI; + + } + + // set states derivatives + for (int i = 0; i < nbSat; ++i) { + multiplexed.setStateDerivatives(i, stateDerivatives[i]); + } + + // set parameters derivatives + parametersDerivatives. + entrySet(). + stream(). + forEach(e -> multiplexed.setParameterDerivatives(e.getKey(), e.getValue())); + + return multiplexed; + + } + + /** Multiplex measurements data. + * @param measurements measurements to multiplex + * @param extractor data extraction function + * @return multiplexed data + */ + private static double[] multiplex(final List> measurements, + final Function, double[]> extractor) { + + // gather individual parts + final List parts = new ArrayList<> (measurements.size()); + int n = 0; + for (final ObservedMeasurement measurement : measurements) { + final double[] p = extractor.apply(measurement); + parts.add(p); + n += p.length; + } + + // create multiplexed data + final double[] multiplexed = new double[n]; + int index = 0; + for (final double[] p : parts) { + System.arraycopy(p, 0, multiplexed, index, p.length); + index += p.length; + } + + return multiplexed; + + } + + /** Multiplex satellites data. + * @param measurements measurements to multiplex + * @return multiplexed satellites data + */ + private static List multiplex(final List> measurements) { + + final List satellites = new ArrayList<>(); + + // gather all satellites, removing duplicates + for (final ObservedMeasurement measurement : measurements) { + for (final ObservableSatellite satellite : measurement.getSatellites()) { + boolean searching = true; + for (int i = 0; i < satellites.size() && searching; ++i) { + // check if we already know this satellite + searching = satellite.getPropagatorIndex() != satellites.get(i).getPropagatorIndex(); + } + if (searching) { + // this is a new satellite, add it to the global list + satellites.add(satellite); + } + } + } + + return satellites; + + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/ObservedMeasurement.java b/src/main/java/org/orekit/estimation/measurements/ObservedMeasurement.java index 56107969a528891d3f2d9cf92ee5326fe11eba04..618e176c4f315ee622e7913d89875031a4bbf42d 100644 --- a/src/main/java/org/orekit/estimation/measurements/ObservedMeasurement.java +++ b/src/main/java/org/orekit/estimation/measurements/ObservedMeasurement.java @@ -131,7 +131,7 @@ public interface ObservedMeasurement> extends C *

* @param iteration iteration number * @param evaluation evaluations number - * @param states orbital states at measurement date + * @param states orbital states corresponding to {@link #getSatellites()} at measurement date * @return estimated measurement */ EstimatedMeasurement estimate(int iteration, int evaluation, SpacecraftState[] states); diff --git a/src/main/java/org/orekit/estimation/measurements/PV.java b/src/main/java/org/orekit/estimation/measurements/PV.java index 0440bd16a4a1bbe1013266c1206e3114d7bfdf06..733158e8060072831644870f6460527d09840eb1 100644 --- a/src/main/java/org/orekit/estimation/measurements/PV.java +++ b/src/main/java/org/orekit/estimation/measurements/PV.java @@ -226,9 +226,7 @@ public class PV extends AbstractMeasurement { final SpacecraftState[] states) { // PV value - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; - final TimeStampedPVCoordinates pv = state.getPVCoordinates(); + final TimeStampedPVCoordinates pv = states[0].getPVCoordinates(); // prepare the evaluation final EstimatedMeasurement estimated = diff --git a/src/main/java/org/orekit/estimation/measurements/Position.java b/src/main/java/org/orekit/estimation/measurements/Position.java index 624f82a8b76e00f3bdd55e96c7cb29431058d5e8..f0b589a463482a4030ac049d5b72c45b0ba98d7d 100644 --- a/src/main/java/org/orekit/estimation/measurements/Position.java +++ b/src/main/java/org/orekit/estimation/measurements/Position.java @@ -159,9 +159,7 @@ public class Position extends AbstractMeasurement { final SpacecraftState[] states) { // PV value - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; - final TimeStampedPVCoordinates pv = state.getPVCoordinates(); + final TimeStampedPVCoordinates pv = states[0].getPVCoordinates(); // prepare the evaluation final EstimatedMeasurement estimated = diff --git a/src/main/java/org/orekit/estimation/measurements/Range.java b/src/main/java/org/orekit/estimation/measurements/Range.java index de8819c7c3bcde7e53ef606d10bf0da05f1abfec..09523bac350dc770fbf78fb93a52b5ef058d5e30 100644 --- a/src/main/java/org/orekit/estimation/measurements/Range.java +++ b/src/main/java/org/orekit/estimation/measurements/Range.java @@ -135,8 +135,7 @@ public class Range extends AbstractMeasurement { final int evaluation, final SpacecraftState[] states) { - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState state = states[0]; // Range derivatives are computed with respect to spacecraft state in inertial frame // and station parameters @@ -225,8 +224,9 @@ public class Range extends AbstractMeasurement { }); // Clock offsets - final DerivativeStructure dtg = station.getClockOffsetDriver().getValue(factory, indices); - final DerivativeStructure dts = satellite.getClockOffsetDriver().getValue(factory, indices); + final ObservableSatellite satellite = getSatellites().get(0); + final DerivativeStructure dts = satellite.getClockOffsetDriver().getValue(factory, indices); + final DerivativeStructure dtg = station.getClockOffsetDriver().getValue(factory, indices); // Range value range = tauD.add(dtg).subtract(dts).multiply(Constants.SPEED_OF_LIGHT); diff --git a/src/main/java/org/orekit/estimation/measurements/RangeRate.java b/src/main/java/org/orekit/estimation/measurements/RangeRate.java index 58da995067c5ebcc31d34a48b1eeb4bf836e4ca4..5ccc27d44c6dd45bd58a75bdb016e5c0a724fd60 100644 --- a/src/main/java/org/orekit/estimation/measurements/RangeRate.java +++ b/src/main/java/org/orekit/estimation/measurements/RangeRate.java @@ -101,8 +101,7 @@ public class RangeRate extends AbstractMeasurement { protected EstimatedMeasurement theoreticalEvaluation(final int iteration, final int evaluation, final SpacecraftState[] states) { - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState state = states[0]; // Range-rate derivatives are computed with respect to spacecraft state in inertial frame // and station position in station's offset frame diff --git a/src/main/java/org/orekit/estimation/measurements/TurnAroundRange.java b/src/main/java/org/orekit/estimation/measurements/TurnAroundRange.java index d84e41cd8206a2f9615cfca906eaa70a8ccf8902..137987a41fb69b1759ca9951015470b03ce4e767 100644 --- a/src/main/java/org/orekit/estimation/measurements/TurnAroundRange.java +++ b/src/main/java/org/orekit/estimation/measurements/TurnAroundRange.java @@ -122,8 +122,7 @@ public class TurnAroundRange extends AbstractMeasurement { protected EstimatedMeasurement theoreticalEvaluation(final int iteration, final int evaluation, final SpacecraftState[] states) { - final ObservableSatellite satellite = getSatellites().get(0); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState state = states[0]; // Turn around range derivatives are computed with respect to: // - Spacecraft state in inertial frame diff --git a/src/main/java/org/orekit/estimation/measurements/generation/AngularAzElBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/AngularAzElBuilder.java index 7d37f45875438d67ed1ae5a04c796b437ae548e2..8d3d8abee73f6d4e55a78ba844091dc35722db22 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/AngularAzElBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/AngularAzElBuilder.java @@ -57,10 +57,10 @@ public class AngularAzElBuilder extends AbstractMeasurementBuilder final ObservableSatellite satellite = getSatellites()[0]; final double[] sigma = getTheoreticalStandardDeviation(); final double[] baseWeight = getBaseWeight(); - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState[] relevant = new SpacecraftState[] { states[satellite.getPropagatorIndex()] }; // create a dummy measurement - final AngularAzEl dummy = new AngularAzEl(station, state.getDate(), + final AngularAzEl dummy = new AngularAzEl(station, relevant[0].getDate(), new double[] { 0.0, 0.0 }, sigma, baseWeight, satellite); @@ -78,7 +78,7 @@ public class AngularAzElBuilder extends AbstractMeasurementBuilder } // estimate the perfect value of the measurement - final double[] angular = dummy.estimate(0, 0, states).getEstimatedValue(); + final double[] angular = dummy.estimate(0, 0, relevant).getEstimatedValue(); // add the noise final double[] noise = getNoise(); @@ -88,7 +88,7 @@ public class AngularAzElBuilder extends AbstractMeasurementBuilder } // generate measurement - final AngularAzEl measurement = new AngularAzEl(station, state.getDate(), angular, + final AngularAzEl measurement = new AngularAzEl(station, relevant[0].getDate(), angular, sigma, baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { measurement.addModifier(modifier); diff --git a/src/main/java/org/orekit/estimation/measurements/generation/AngularRaDecBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/AngularRaDecBuilder.java index 2557dccfbc8255f4329f90204754c46bcb4a8820..26ce4c7e0647b361ff3e5194e19c67351ad7e1a5 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/AngularRaDecBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/AngularRaDecBuilder.java @@ -63,10 +63,10 @@ public class AngularRaDecBuilder extends AbstractMeasurementBuilder modifier : getModifiers()) { measurement.addModifier(modifier); diff --git a/src/main/java/org/orekit/estimation/measurements/generation/InterSatellitesRangeBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/InterSatellitesRangeBuilder.java index 11f05116921799a94c823d1ca369edf2ab236eff..5cad3e7a51616afc4c182a1b0c15bf8906459d29 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/InterSatellitesRangeBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/InterSatellitesRangeBuilder.java @@ -57,6 +57,10 @@ public class InterSatellitesRangeBuilder extends AbstractMeasurementBuilder> { List> getModifiers(); /** Generate a single measurement. - * @param states spacecraft states + * @param states all spacecraft states (i.e. including ones that may not be relevant for the current builder) * @return generated measurement */ T build(SpacecraftState[] states); diff --git a/src/main/java/org/orekit/estimation/measurements/generation/PVBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/PVBuilder.java index 2a56a109b28d50a01ad03db24940ee20524c36f8..9d24f739876b889cca9d2d027928f840eaab4b29 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/PVBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/PVBuilder.java @@ -57,10 +57,10 @@ public class PVBuilder extends AbstractMeasurementBuilder { final ObservableSatellite satellite = getSatellites()[0]; final double[] sigma = getTheoreticalStandardDeviation(); final double baseWeight = getBaseWeight()[0]; - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState[] relevant = new SpacecraftState[] { states[satellite.getPropagatorIndex()] }; // create a dummy measurement - final PV dummy = new PV(state.getDate(), Vector3D.NaN, Vector3D.NaN, + final PV dummy = new PV(relevant[0].getDate(), Vector3D.NaN, Vector3D.NaN, sigma[0], sigma[1], baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { dummy.addModifier(modifier); @@ -76,7 +76,7 @@ public class PVBuilder extends AbstractMeasurementBuilder { } // estimate the perfect value of the measurement - final double[] pv = dummy.estimate(0, 0, states).getEstimatedValue(); + final double[] pv = dummy.estimate(0, 0, relevant).getEstimatedValue(); // add the noise final double[] noise = getNoise(); @@ -90,7 +90,7 @@ public class PVBuilder extends AbstractMeasurementBuilder { } // generate measurement - final PV measurement = new PV(state.getDate(), + final PV measurement = new PV(relevant[0].getDate(), new Vector3D(pv[0], pv[1], pv[2]), new Vector3D(pv[3], pv[4], pv[5]), sigma[0], sigma[1], baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { diff --git a/src/main/java/org/orekit/estimation/measurements/generation/PositionBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/PositionBuilder.java index f4b4434684532640159c377f298bf010d08ca006..04b655ec90cc23463de9447f9f726de5866a4ec8 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/PositionBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/PositionBuilder.java @@ -51,10 +51,10 @@ public class PositionBuilder extends AbstractMeasurementBuilder { final ObservableSatellite satellite = getSatellites()[0]; final double sigma = getTheoreticalStandardDeviation()[0]; final double baseWeight = getBaseWeight()[0]; - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState[] relevant = new SpacecraftState[] { states[satellite.getPropagatorIndex()] }; // create a dummy measurement - final Position dummy = new Position(state.getDate(), Vector3D.NaN, sigma, baseWeight, satellite); + final Position dummy = new Position(relevant[0].getDate(), Vector3D.NaN, sigma, baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { dummy.addModifier(modifier); } @@ -69,7 +69,7 @@ public class PositionBuilder extends AbstractMeasurementBuilder { } // estimate the perfect value of the measurement - final double[] position = dummy.estimate(0, 0, states).getEstimatedValue(); + final double[] position = dummy.estimate(0, 0, relevant).getEstimatedValue(); // add the noise final double[] noise = getNoise(); @@ -80,7 +80,7 @@ public class PositionBuilder extends AbstractMeasurementBuilder { } // generate measurement - final Position measurement = new Position(state.getDate(), new Vector3D(position), + final Position measurement = new Position(relevant[0].getDate(), new Vector3D(position), sigma, baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { measurement.addModifier(modifier); diff --git a/src/main/java/org/orekit/estimation/measurements/generation/RangeBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/RangeBuilder.java index f3c5d205f84dbab0b8cc19cbd2fa37f98ffb5920..c0f54a109b86750038f87a860094a760ca9c4e42 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/RangeBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/RangeBuilder.java @@ -62,10 +62,10 @@ public class RangeBuilder extends AbstractMeasurementBuilder { final ObservableSatellite satellite = getSatellites()[0]; final double sigma = getTheoreticalStandardDeviation()[0]; final double baseWeight = getBaseWeight()[0]; - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState[] relevant = new SpacecraftState[] { states[satellite.getPropagatorIndex()] }; // create a dummy measurement - final Range dummy = new Range(station, twoway, state.getDate(), Double.NaN, sigma, baseWeight, satellite); + final Range dummy = new Range(station, twoway, relevant[0].getDate(), Double.NaN, sigma, baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { dummy.addModifier(modifier); } @@ -80,7 +80,7 @@ public class RangeBuilder extends AbstractMeasurementBuilder { } // estimate the perfect value of the measurement - double range = dummy.estimate(0, 0, states).getEstimatedValue()[0]; + double range = dummy.estimate(0, 0, relevant).getEstimatedValue()[0]; // add the noise final double[] noise = getNoise(); @@ -89,7 +89,7 @@ public class RangeBuilder extends AbstractMeasurementBuilder { } // generate measurement - final Range measurement = new Range(station, twoway, state.getDate(), range, sigma, baseWeight, satellite); + final Range measurement = new Range(station, twoway, relevant[0].getDate(), range, sigma, baseWeight, satellite); for (final EstimationModifier modifier : getModifiers()) { measurement.addModifier(modifier); } diff --git a/src/main/java/org/orekit/estimation/measurements/generation/RangeRateBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/RangeRateBuilder.java index 4a653e3f3162b38cd4781814fd3dd1ce215d36ab..571365a510d165e928a35f971c333b70dbf09f68 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/RangeRateBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/RangeRateBuilder.java @@ -62,10 +62,10 @@ public class RangeRateBuilder extends AbstractMeasurementBuilder { final ObservableSatellite satellite = getSatellites()[0]; final double sigma = getTheoreticalStandardDeviation()[0]; final double baseWeight = getBaseWeight()[0]; - final SpacecraftState state = states[satellite.getPropagatorIndex()]; + final SpacecraftState[] relevant = new SpacecraftState[] { states[satellite.getPropagatorIndex()] }; // create a dummy measurement - final RangeRate dummy = new RangeRate(station, state.getDate(), Double.NaN, sigma, baseWeight, twoway, satellite); + final RangeRate dummy = new RangeRate(station, relevant[0].getDate(), Double.NaN, sigma, baseWeight, twoway, satellite); for (final EstimationModifier modifier : getModifiers()) { dummy.addModifier(modifier); } @@ -80,7 +80,7 @@ public class RangeRateBuilder extends AbstractMeasurementBuilder { } // estimate the perfect value of the measurement - double rangeRate = dummy.estimate(0, 0, states).getEstimatedValue()[0]; + double rangeRate = dummy.estimate(0, 0, relevant).getEstimatedValue()[0]; // add the noise final double[] noise = getNoise(); @@ -89,7 +89,7 @@ public class RangeRateBuilder extends AbstractMeasurementBuilder { } // generate measurement - final RangeRate measurement = new RangeRate(station, state.getDate(), rangeRate, + final RangeRate measurement = new RangeRate(station, relevant[0].getDate(), rangeRate, sigma, baseWeight, twoway, satellite); for (final EstimationModifier modifier : getModifiers()) { measurement.addModifier(modifier); diff --git a/src/main/java/org/orekit/estimation/measurements/generation/TurnAroundRangeBuilder.java b/src/main/java/org/orekit/estimation/measurements/generation/TurnAroundRangeBuilder.java index bbb6621c487618f8a20a5b85e95cd19cead6ca1a..cbbdf8643cbca80c28aedf5e78d5c6c25808d099 100644 --- a/src/main/java/org/orekit/estimation/measurements/generation/TurnAroundRangeBuilder.java +++ b/src/main/java/org/orekit/estimation/measurements/generation/TurnAroundRangeBuilder.java @@ -62,10 +62,10 @@ public class TurnAroundRangeBuilder extends AbstractMeasurementBuilder modifier : getModifiers()) { dummy.addModifier(modifier); @@ -81,7 +81,7 @@ public class TurnAroundRangeBuilder extends AbstractMeasurementBuilder modifier : getModifiers()) { measurement.addModifier(modifier); diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/AbstractDualFrequencyCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/AbstractDualFrequencyCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..f8f0add36e7da4052c22030df80893dbbeb96a60 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/AbstractDualFrequencyCombination.java @@ -0,0 +1,198 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.gnss.CombinedObservationData; +import org.orekit.gnss.CombinedObservationDataSet; +import org.orekit.gnss.Frequency; +import org.orekit.gnss.MeasurementType; +import org.orekit.gnss.ObservationData; +import org.orekit.gnss.ObservationDataSet; +import org.orekit.gnss.ObservationType; +import org.orekit.gnss.SatelliteSystem; + +/** Base class for dual frequency combination of measurements. + * @author Bryan Cazabonne + * @since 10.1 + */ +public abstract class AbstractDualFrequencyCombination implements MeasurementCombination { + + /** Type of combination of measurements. */ + private final CombinationType type; + + /** Satellite system used for the combination. */ + private final SatelliteSystem system; + + /** + * Constructor. + * @param type combination of measurements type + * @param system satellite system + */ + protected AbstractDualFrequencyCombination(final CombinationType type, final SatelliteSystem system) { + this.type = type; + this.system = system; + } + + /** {@inheritDoc} */ + @Override + public String getName() { + return type.getName(); + } + + /** + * Combines observation data using a dual frequency combination of measurements. + * @param od1 first observation data to combined + * @param od2 second observation data to combined + * @return a combined observation data + */ + public CombinedObservationData combine(final ObservationData od1, final ObservationData od2) { + + // Observation types + final ObservationType obsType1 = od1.getObservationType(); + final ObservationType obsType2 = od2.getObservationType(); + + // Frequencies + final Frequency freq1 = obsType1.getFrequency(system); + final Frequency freq2 = obsType2.getFrequency(system); + // Check if the combination of measurements if performed for two different frequencies + if (freq1 == freq2) { + throw new OrekitException(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS, + freq1, freq2, getName()); + } + + // Measurements types + final MeasurementType measType1 = obsType1.getMeasurementType(); + final MeasurementType measType2 = obsType2.getMeasurementType(); + + // Check if measurement types are the same + if (measType1 != measType2) { + // If the measurement types are differents, an exception is thrown + throw new OrekitException(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS, + measType1, measType2, getName()); + } + + // Combined value + final double combinedValue = getCombinedValue(od1.getValue(), freq1, od2.getValue(), freq2); + + // Combined frequency + final double combinedFrequency = getCombinedFrequency(freq1, freq2); + + // Combined observation data + return new CombinedObservationData(type, measType1, combinedValue, combinedFrequency, Arrays.asList(od1, od2)); + + } + + /** {@inheritDoc} */ + @Override + public CombinedObservationDataSet combine(final ObservationDataSet observations) { + + // Initialize list of measurements + final List pseudoRanges = new ArrayList<>(); + final List phases = new ArrayList<>(); + + // Loop on observation data to fill lists + for (final ObservationData od : observations.getObservationData()) { + if (!Double.isNaN(od.getValue())) { + if (od.getObservationType().getMeasurementType() == MeasurementType.PSEUDO_RANGE) { + pseudoRanges.add(od); + } else if (od.getObservationType().getMeasurementType() == MeasurementType.CARRIER_PHASE) { + phases.add(od); + } + } + } + + // Initialize list of combined observation data + final List combined = new ArrayList<>(); + // Combine pseudo-ranges + for (int i = 0; i < pseudoRanges.size() - 1; i++) { + for (int j = 1; j < pseudoRanges.size(); j++) { + final boolean combine = isCombinationPossible(pseudoRanges.get(i), pseudoRanges.get(j)); + if (combine) { + combined.add(combine(pseudoRanges.get(i), pseudoRanges.get(j))); + } + } + } + // Combine carrier-phases + for (int i = 0; i < phases.size() - 1; i++) { + for (int j = 1; j < phases.size(); j++) { + final boolean combine = isCombinationPossible(phases.get(i), phases.get(j)); + if (combine) { + combined.add(combine(phases.get(i), phases.get(j))); + } + } + } + + return new CombinedObservationDataSet(observations.getHeader(), observations.getSatelliteSystem(), + observations.getPrnNumber(), observations.getDate(), + observations.getRcvrClkOffset(), combined); + } + + /** + * Get the combined observed value of two measurements. + * @param obs1 observed value of the first measurement + * @param f1 frequency of the first measurement + * @param obs2 observed value of the second measurement + * @param f2 frequency of the second measurement + * @return combined observed value + */ + protected abstract double getCombinedValue(double obs1, Frequency f1, double obs2, Frequency f2); + + /** + * Get the combined frequency of two measurements. + * @param f1 frequency of the first measurement + * @param f2 frequency of the second measurement + * @return combined frequency in MHz + */ + protected abstract double getCombinedFrequency(Frequency f1, Frequency f2); + + /** + * Verifies if two observation data can be combine. + * @param data1 first observation data + * @param data2 second observation data + * @return true if observation data can be combined + */ + private boolean isCombinationPossible(final ObservationData data1, final ObservationData data2) { + + // Observation types + final ObservationType obsType1 = data1.getObservationType(); + final ObservationType obsType2 = data2.getObservationType(); + + // Geometry-Free combination is possible only if data frequencies are diffrents + if (obsType1.getFrequency(system) != obsType2.getFrequency(system)) { + + if (obsType1.getSignalCode() == obsType2.getSignalCode()) { + // Observation code is the same. Combination of measurements can be performed + return true; + } else { + // Observation code is not the same. Combination of measurements can not be performed + return false; + } + + } else { + // False because observation data have the same frequency + return false; + } + + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/AbstractSingleFrequencyCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/AbstractSingleFrequencyCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..727ae73d97868eaf01d6d844c5f3084b3bb3a974 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/AbstractSingleFrequencyCombination.java @@ -0,0 +1,197 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.gnss.CombinedObservationData; +import org.orekit.gnss.CombinedObservationDataSet; +import org.orekit.gnss.Frequency; +import org.orekit.gnss.MeasurementType; +import org.orekit.gnss.ObservationData; +import org.orekit.gnss.ObservationDataSet; +import org.orekit.gnss.ObservationType; +import org.orekit.gnss.RinexHeader; +import org.orekit.gnss.SatelliteSystem; + +/** Base class for single frequency combination of measurements. + * @author Bryan Cazabonne + * @since 10.1 + */ +public abstract class AbstractSingleFrequencyCombination implements MeasurementCombination { + + /** Type of combination of measurements. */ + private final CombinationType type; + + /** Satellite system used for the combination. */ + private final SatelliteSystem system; + + /** + * Constructor. + * @param type combination of measurements type + * @param system satellite system + */ + protected AbstractSingleFrequencyCombination(final CombinationType type, final SatelliteSystem system) { + this.type = type; + this.system = system; + } + + /** {@inheritDoc} */ + @Override + public String getName() { + return type.getName(); + } + + /** {@inheritDoc} */ + @Override + public CombinedObservationDataSet combine(final ObservationDataSet observations) { + + // Rinex file header + final RinexHeader header = observations.getHeader(); + // Rinex version to integer + final int version = (int) header.getRinexVersion(); + + // Initialize list of measurements + final List pseudoRanges = new ArrayList<>(); + final List phases = new ArrayList<>(); + + // Loop on observation data to fill lists + for (final ObservationData od : observations.getObservationData()) { + if (!Double.isNaN(od.getValue())) { + if (od.getObservationType().getMeasurementType() == MeasurementType.PSEUDO_RANGE) { + pseudoRanges.add(od); + } else if (od.getObservationType().getMeasurementType() == MeasurementType.CARRIER_PHASE) { + phases.add(od); + } + } + } + + // Initialize list of combined observation data + final List combined = new ArrayList<>(); + + for (int i = 0; i < phases.size(); i++) { + for (int j = 0; j < pseudoRanges.size(); j++) { + final boolean combine = isCombinationPossible(version, phases.get(i), pseudoRanges.get(j)); + if (combine) { + combined.add(combine(phases.get(i), pseudoRanges.get(j))); + } + } + } + + return new CombinedObservationDataSet(observations.getHeader(), observations.getSatelliteSystem(), + observations.getPrnNumber(), observations.getDate(), + observations.getRcvrClkOffset(), combined); + } + + /** + * Combines observation data using a single frequency combination of measurements. + * @param phase phase measurement + * @param pseudoRange pseudoRange measurement + * @return a combined observation data + */ + public CombinedObservationData combine(final ObservationData phase, final ObservationData pseudoRange) { + + // Observation types + final ObservationType obsType1 = phase.getObservationType(); + final ObservationType obsType2 = pseudoRange.getObservationType(); + + // Frequencies + final Frequency freq1 = obsType1.getFrequency(system); + final Frequency freq2 = obsType2.getFrequency(system); + // Check if the combination of measurements if performed for two different frequencies + if (freq1 != freq2) { + throw new OrekitException(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS, + freq1, freq2, getName()); + } + + // Measurements types + final MeasurementType measType1 = obsType1.getMeasurementType(); + final MeasurementType measType2 = obsType2.getMeasurementType(); + + // Check if measurement types are the same + if (measType1 == measType2) { + // If the measurement types are the same, an exception is thrown + throw new OrekitException(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS, + measType1, measType2, getName()); + } + + // Frequency + final double f = freq1.getMHzFrequency(); + + // Combined value + final double combinedValue = getCombinedValue(phase.getValue(), pseudoRange.getValue(), f); + + // Combined observation data + return new CombinedObservationData(CombinationType.PHASE_MINUS_CODE, MeasurementType.COMBINED_RANGE_PHASE, + combinedValue, f, Arrays.asList(phase, pseudoRange)); + } + + /** + * Get the combined observed value of two measurements. + * @param phase observed value of the phase measurement + * @param pseudoRange observed value of the range measurement + * @param f frequency of both measurements in MHz + * @return combined observed value + */ + protected abstract double getCombinedValue(double phase, double pseudoRange, double f); + + /** + * Verifies if two observation data can be combine. + * @param version Rinex file version (integer part) + * @param phase phase measurement + * @param pseudoRange pseudoRange measurement + * @return true if observation data can be combined + */ + private boolean isCombinationPossible(final int version, final ObservationData phase, final ObservationData pseudoRange) { + + // Observation types + final ObservationType obsType1 = phase.getObservationType(); + final ObservationType obsType2 = pseudoRange.getObservationType(); + + // Phase minus Code combination is possible only if data frequencies are the same + if (obsType1.getFrequency(system) == obsType2.getFrequency(system)) { + + // Switch on Rinex version + switch (version) { + case 2: + // Rinex 2 version + return true; + case 3: + if (obsType1.getSignalCode() == obsType2.getSignalCode()) { + // Observation code is the same. Combination of measurements can be performed + return true; + } else { + // Observation code is not the same. Combination of measurements can not be performed + return false; + } + default: + // Not supported Rinex version. Combination is not possible + return false; + } + + } else { + // False because observation data have different frequency + return false; + } + + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/CombinationType.java b/src/main/java/org/orekit/estimation/measurements/gnss/CombinationType.java new file mode 100644 index 0000000000000000000000000000000000000000..cf339b819e796b0f7e3a98be7f29f909046f7016 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/CombinationType.java @@ -0,0 +1,67 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +/** + * Enumerate for combination of measurements types. + * + * @author Bryan Cazabonne + * @since 10.1 + */ +public enum CombinationType { + + /** Phase minus code combination. */ + PHASE_MINUS_CODE("Phase minus code"), + + /** GRoup And Phase Ionospheric Calibration (GRAPHIC) combination. */ + GRAPHIC("GRAPHIC"), + + /** Geometry-free combination. */ + GEOMETRY_FREE("Geometry Free"), + + /** Ionosphere-free combination. */ + IONO_FREE("Ionosphere Free"), + + /** Narrow-lane combination. */ + NARROW_LANE("Narrow Lane"), + + /** Wide-lane combination. */ + WIDE_LANE("Wide Lane"), + + /** Melbourne-Wübbena combination. */ + MELBOURNE_WUBBENA("Melbourne Wubbena"); + + /** Name of the combination of measurements. */ + private final String name; + + /** + * Constructor. + * @param name name of the combination of measurements + */ + CombinationType(final String name) { + this.name = name; + } + + /** + * Get the name of the combination of measurements. + * @return the name + */ + public String getName() { + return name; + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/GRAPHICCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/GRAPHICCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..50847ac0f8b9f69518cb9197a14f779060e5745c --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/GRAPHICCombination.java @@ -0,0 +1,57 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.orekit.gnss.SatelliteSystem; + +/** + * GRoup And Phase Ionospheric Calibration (GRAPHIC) combination. + *

+ * This combination is a ionosphere-free single frequency + * combination of measurements. + *

+ *
+ *    mf =  0.5 * (Φf + Rf)
+ * 
+ * With: + *
    + *
  • mf : GRAPHIC measurement.
  • + *
  • Φf : Phase measurement.
  • + *
  • Rf : Code measurement.
  • + *
  • f : Frequency.
  • + *
+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class GRAPHICCombination extends AbstractSingleFrequencyCombination { + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + GRAPHICCombination(final SatelliteSystem system) { + super(CombinationType.GRAPHIC, system); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedValue(final double phase, final double pseudoRange, final double f) { + // Combination does not depend on the frequency + return 0.5 * (phase + pseudoRange); + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/GeometryFreeCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/GeometryFreeCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..1e733c2840029b3e132b36734084aaf1fe7aced6 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/GeometryFreeCombination.java @@ -0,0 +1,72 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.hipparchus.util.FastMath; +import org.orekit.gnss.Frequency; +import org.orekit.gnss.MeasurementType; +import org.orekit.gnss.SatelliteSystem; + +/** + * Geometry-free combination. + *

+ * This combination removes the geometry part of the measurement. + * It can be used to estimate the ionospheric electron content or to detect + * cycle slips in the carrier phase, as well. + *

+ *
+ *    mGF =  m2 - m1
+ * 
+ * With: + *
    + *
  • mGF: Geometry-free measurement.
  • + *
  • m1 : First measurement.
  • + *
  • m1 : Second measurement.
  • + *
+ *

+ * Geometry-Free combination is a dual frequency combination. + * The two measurements shall have different frequencies but they must have the same {@link MeasurementType}. + *

+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class GeometryFreeCombination extends AbstractDualFrequencyCombination { + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + GeometryFreeCombination(final SatelliteSystem system) { + super(CombinationType.GEOMETRY_FREE, system); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedValue(final double obs1, final Frequency f1, + final double obs2, final Frequency f2) { + // Combined observed value does not depend on frequency for the Geometry-Free combination + return FastMath.abs(obs2 - obs1); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedFrequency(final Frequency f1, final Frequency f2) { + // There is not combined frequency for the Geometry-Free combination + return Double.NaN; + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/IntegerLeastSquareSolution.java b/src/main/java/org/orekit/estimation/measurements/gnss/IntegerLeastSquareSolution.java index bcb5fb40a32864f51a00e3a7be8fc81490f32b63..57f2d5887000b992684edb99a918338288f0d861 100644 --- a/src/main/java/org/orekit/estimation/measurements/gnss/IntegerLeastSquareSolution.java +++ b/src/main/java/org/orekit/estimation/measurements/gnss/IntegerLeastSquareSolution.java @@ -57,4 +57,29 @@ public class IntegerLeastSquareSolution implements Comparable + * This combination removes the first order (up to 99.9%) + * ionospheric effect. + *

+ *
+ *             f1² * m1 - f2² * m2
+ *    mIF =  -----------------------
+ *                  f1² - f2²
+ * 
+ * With: + *
    + *
  • mIF: Ionosphere-free measurement.
  • + *
  • f1 : Frequency of the first measurement.
  • + *
  • m1 : First measurement.
  • + *
  • f2 : Frequency of the second measurement.
  • + *
  • m1 : Second measurement.
  • + *
+ *

+ * Ionosphere-free combination is a dual frequency combination. + * The two measurements shall have different frequencies but they must have the same {@link MeasurementType}. + *

+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class IonosphereFreeCombination extends AbstractDualFrequencyCombination { + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + IonosphereFreeCombination(final SatelliteSystem system) { + super(CombinationType.IONO_FREE, system); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedValue(final double obs1, final Frequency f1, + final double obs2, final Frequency f2) { + // Get the ration f/f0 + final double ratioF1 = f1.getRatio(); + final double ratioF2 = f2.getRatio(); + final double ratioF1Sq = ratioF1 * ratioF1; + final double ratioF2Sq = ratioF2 * ratioF2; + // Perform combination + return MathArrays.linearCombination(ratioF1Sq, obs1, -ratioF2Sq, obs2) / (ratioF1Sq - ratioF2Sq); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedFrequency(final Frequency f1, final Frequency f2) { + // Get the ratios f/f0 + final double ratioF1 = f1.getRatio(); + final double ratioF2 = f2.getRatio(); + // Multiplication factor used to compute the combined frequency + int k = 1; + // Get the integer part of the ratios + final int ratioF1Int = (int) ratioF1; + final int ratioF2Int = (int) ratioF2; + // Check if the ratios are composed of a decimal part + if (ratioF1 - ratioF1Int > 0.0 || ratioF2 - ratioF2Int > 0.0) { + // Do nothing, k remains equal to 1 + } else { + // k is the GCD of the interger ratio + k = ArithmeticUtils.gcd(ratioF1Int, ratioF2Int); + } + // Combined frequency + return MathArrays.linearCombination(ratioF1, ratioF1, -ratioF2, ratioF2) * (Frequency.F0 / k); + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/MeasurementCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/MeasurementCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..44c078f86bb7b4e491ec3d0ab1b2419f0f52c30b --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/MeasurementCombination.java @@ -0,0 +1,42 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.orekit.gnss.CombinedObservationDataSet; +import org.orekit.gnss.ObservationDataSet; + +/** + * Interface for combination of measurements. + * @author Bryan Cazabonne + * @since 10.1 + */ +public interface MeasurementCombination { + + /** + * Combines observation data using a combination of measurements. + * @param observations observation data set + * @return a combined observation data set + */ + CombinedObservationDataSet combine(ObservationDataSet observations); + + /** + * Get the name of the combination of measurements. + * @return name of the combination of measurements + */ + String getName(); + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactory.java b/src/main/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..bc2c0ebeaf537dccd479c7622edd8cc867ddd602 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/MeasurementCombinationFactory.java @@ -0,0 +1,101 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.orekit.gnss.SatelliteSystem; + +/** Factory for predefined combination of measurements. + *

+ * This is a utility class, so its constructor is private. + *

+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class MeasurementCombinationFactory { + + /** Private constructor. + *

This class is a utility class, it should neither have a public + * nor a default constructor. This private constructor prevents + * the compiler from generating one automatically.

+ */ + private MeasurementCombinationFactory() { + } + + /** + * Get the Wide-Lane combination of measurements. + * @param system satellite system + * @return Wide-Lane combination + */ + public static WideLaneCombination getWideLaneCombination(final SatelliteSystem system) { + return new WideLaneCombination(system); + } + + /** + * Get the Narrow-Lane combination of measurements. + * @param system satellite system + * @return Narrow-Lane combination + */ + public static NarrowLaneCombination getNarrowLaneCombination(final SatelliteSystem system) { + return new NarrowLaneCombination(system); + } + + /** + * Get the Ionosphere-Free combination of measurements. + * @param system satellite system + * @return Ionosphere-Lane combination + */ + public static IonosphereFreeCombination getIonosphereFreeCombination(final SatelliteSystem system) { + return new IonosphereFreeCombination(system); + } + + /** + * Get the Geometry-Free combination of measurements. + * @param system satellite system + * @return Geometry-Free combination + */ + public static GeometryFreeCombination getGeometryFreeCombination(final SatelliteSystem system) { + return new GeometryFreeCombination(system); + } + + /** + * Get the Melbourne-Wübbena combination of measurements. + * @param system satellite system + * @return Melbourne-Wübbena combination + */ + public static MelbourneWubbenaCombination getMelbourneWubbenaCombination(final SatelliteSystem system) { + return new MelbourneWubbenaCombination(system); + } + + /** + * Get the phase minus code combination of measurements. + * @param system satellite system + * @return phase minus code combination + */ + public static PhaseMinusCodeCombination getPhaseMinusCodeCombination(final SatelliteSystem system) { + return new PhaseMinusCodeCombination(system); + } + + /** + * Get the GRAPHIC combination of measurements. + * @param system satellite system + * @return phase minus code combination + */ + public static GRAPHICCombination getGRAPHICCombination(final SatelliteSystem system) { + return new GRAPHICCombination(system); + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/MelbourneWubbenaCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/MelbourneWubbenaCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..4cb9403aa1146b6a2c0e3af192e6f5982ea3f0d5 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/MelbourneWubbenaCombination.java @@ -0,0 +1,166 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import java.util.ArrayList; +import java.util.List; + +import org.hipparchus.util.FastMath; +import org.orekit.gnss.CombinedObservationData; +import org.orekit.gnss.CombinedObservationDataSet; +import org.orekit.gnss.MeasurementType; +import org.orekit.gnss.ObservationData; +import org.orekit.gnss.ObservationDataSet; +import org.orekit.gnss.SatelliteSystem; + +/** + * Melbourne-Wübbena combination. + *

+ * This combination allows, thanks to the wide-lane combination, a larger wavelength + * than each signal individually. Moreover, the measurement noise is reduced by the + * narrow-lane combination of code measurements. + *

+ *
+ *    mMW =  ΦWL - RNL
+ *    mMW =  λWL * NWL + b + ε
+ * 
+ * With: + *
    + *
  • mMW : Melbourne-Wübbena measurement.
  • + *
  • ΦWL : Wide-Lane phase measurement.
  • + *
  • RNL : Narrow-Lane code measurement.
  • + *
  • λWL : Wide-Lane wavelength.
  • + *
  • NWL : Wide-Lane ambiguity (Nf1 - Nf2).
  • + *
  • b : Satellite and receiver instrumental delays.
  • + *
  • ε : Measurement noise.
  • + *
+ *

+ * {@link NarrowLaneCombination Narrow-Lane} and {@link WideLaneCombination Wide-Lane} + * combinations shall be performed with the same pair of frequencies. + *

+ * + * @see "Detector based in code and carrier phase data: The Melbourne-Wübbena combination, + * J. Sanz Subirana, J.M. Juan Zornoza and M. Hernández-Pajares, 2011" + * + * @author Bryan Cazabonne + * @since 10.1 + */ +public class MelbourneWubbenaCombination implements MeasurementCombination { + + /** Threshold for frequency comparison. */ + private static final double THRESHOLD = 1.0e-10; + + /** Satellite system used for the combination. */ + private final SatelliteSystem system; + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + MelbourneWubbenaCombination(final SatelliteSystem system) { + this.system = system; + } + + /** {@inheritDoc} */ + @Override + public CombinedObservationDataSet combine(final ObservationDataSet observations) { + + // Wide-Lane combination + final WideLaneCombination wideLane = MeasurementCombinationFactory.getWideLaneCombination(system); + final CombinedObservationDataSet combinedWL = wideLane.combine(observations); + + // Narrow-Lane combination + final NarrowLaneCombination narrowLane = MeasurementCombinationFactory.getNarrowLaneCombination(system); + final CombinedObservationDataSet combinedNL = narrowLane.combine(observations); + + // Initialize list of combined observation data + final List combined = new ArrayList<>(); + + // Loop on Wide-Lane measurements + for (CombinedObservationData odWL : combinedWL.getObservationData()) { + // Only consider combined phase measurements + if (odWL.getMeasurementType() == MeasurementType.CARRIER_PHASE) { + // Loop on Narrow-Lane measurements + for (CombinedObservationData odNL : combinedNL.getObservationData()) { + // Only consider combined range measurements + if (odNL.getMeasurementType() == MeasurementType.PSEUDO_RANGE) { + // Verify if the combinations have used the same frequencies + final boolean isCombinationPossible = isCombinationPossible(odWL, odNL); + if (isCombinationPossible) { + // Combined value and frequency + final double combinedValue = odWL.getValue() - odNL.getValue(); + final double combinedFrequency = odWL.getCombinedMHzFrequency(); + // Used observation data to build the Melbourn-Wübbena measurement + final List usedData = new ArrayList(4); + usedData.add(0, odWL.getUsedObservationData().get(0)); + usedData.add(1, odWL.getUsedObservationData().get(1)); + usedData.add(2, odNL.getUsedObservationData().get(0)); + usedData.add(3, odNL.getUsedObservationData().get(1)); + // Update the combined observation data list + combined.add(new CombinedObservationData(CombinationType.MELBOURNE_WUBBENA, + MeasurementType.COMBINED_RANGE_PHASE, + combinedValue, combinedFrequency, usedData)); + } + } + } + } + } + + return new CombinedObservationDataSet(observations.getHeader(), observations.getSatelliteSystem(), + observations.getPrnNumber(), observations.getDate(), + observations.getRcvrClkOffset(), combined); + } + + /** + * Verifies if the Melbourne-Wübbena combination is possible between both combined observation data. + *

+ * This method compares the frequencies of the combined measurement to decide + * if the combination of measurements is possible. + * The combination is possible if : + *

+     *    abs(f1WL - f2WL) = abs(f1NL - f2NL)
+     * 
+ *

+ * @param odWL Wide-Lane measurement + * @param odNL Narrow-Lane measurement + * @return true if the Melbourne-Wübbena combination is possible + */ + private boolean isCombinationPossible(final CombinedObservationData odWL, final CombinedObservationData odNL) { + // Frequencies + final double[] frequency = new double[4]; + int j = 0; + for (int i = 0; i < odWL.getUsedObservationData().size(); i++) { + frequency[j++] = odWL.getUsedObservationData().get(i).getObservationType().getFrequency(system).getMHzFrequency(); + frequency[j++] = odNL.getUsedObservationData().get(i).getObservationType().getFrequency(system).getMHzFrequency(); + } + // Verify if used frequencies are the same. + // Possible numerical error is taken into account by using a threshold of acceptance + if (FastMath.abs(frequency[0] - frequency[2]) - FastMath.abs(frequency[1] - frequency[3]) < THRESHOLD) { + // Frequencies used for the combinations are the same + return true; + } else { + return false; + } + } + + /** {@inheritDoc} */ + @Override + public String getName() { + return CombinationType.MELBOURNE_WUBBENA.getName(); + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/NarrowLaneCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/NarrowLaneCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..19272d390625483c103ca9246022e06e8816672e --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/NarrowLaneCombination.java @@ -0,0 +1,78 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.hipparchus.util.MathArrays; +import org.orekit.gnss.Frequency; +import org.orekit.gnss.MeasurementType; +import org.orekit.gnss.SatelliteSystem; + +/** + * Narrow-Lane combination. + *

+ * This combination create signal with a narrow wavelength. + * The signal in this combination has a lower noise than each + * separated separeted component. + *

+ *
+ *              f1 * m1 + f2 * m2
+ *    mNL =  -----------------------
+ *                   f1 + f2
+ * 
+ * With: + *
    + *
  • mNL : Narrow-laning measurement.
  • + *
  • f1 : Frequency of the first measurement.
  • + *
  • pr1 : First measurement.
  • + *
  • f2 : Frequency of the second measurement.
  • + *
  • m1 : Second measurement.
  • + *
+ *

+ * Narrow-Lane combination is a dual frequency combination. + * The two measurements shall have different frequencies but they must have the same {@link MeasurementType}. + *

+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class NarrowLaneCombination extends AbstractDualFrequencyCombination { + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + NarrowLaneCombination(final SatelliteSystem system) { + super(CombinationType.NARROW_LANE, system); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedValue(final double obs1, final Frequency f1, + final double obs2, final Frequency f2) { + // Get the ration f/f0 + final double ratioF1 = f1.getRatio(); + final double ratioF2 = f2.getRatio(); + // Perform combination + return MathArrays.linearCombination(ratioF1, obs1, ratioF2, obs2) / (ratioF1 + ratioF2); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedFrequency(final Frequency f1, final Frequency f2) { + return f1.getMHzFrequency() + f2.getMHzFrequency(); + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/Phase.java b/src/main/java/org/orekit/estimation/measurements/gnss/Phase.java index fca415614c1ec766fef5bb671125208caf2ad6df..5191b9d5507c3c3793b202139ec2b3bf7814d5d0 100644 --- a/src/main/java/org/orekit/estimation/measurements/gnss/Phase.java +++ b/src/main/java/org/orekit/estimation/measurements/gnss/Phase.java @@ -69,7 +69,7 @@ public class Phase extends AbstractMeasurement { /** Simple constructor. * @param station ground station from which measurement is performed * @param date date of the measurement - * @param phase observed value + * @param phase observed value (cycles) * @param wavelength phase observed value wavelength (m) * @param sigma theoretical standard deviation * @param baseWeight base weight diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/PhaseBuilder.java b/src/main/java/org/orekit/estimation/measurements/gnss/PhaseBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..0e3c245766ab171d380e9ed787dfdbf710cb349e --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/PhaseBuilder.java @@ -0,0 +1,100 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.hipparchus.random.CorrelatedRandomVectorGenerator; +import org.orekit.estimation.measurements.EstimationModifier; +import org.orekit.estimation.measurements.GroundStation; +import org.orekit.estimation.measurements.ObservableSatellite; +import org.orekit.estimation.measurements.generation.AbstractMeasurementBuilder; +import org.orekit.propagation.SpacecraftState; +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.ParameterDriver; + + +/** Builder for {@link Phase} measurements. + * @author Luc Maisonobe + * @since 10.1 + */ +public class PhaseBuilder extends AbstractMeasurementBuilder { + + /** Ground station from which measurement is performed. */ + private final GroundStation station; + + /** Wavelength of the phase observed value [m]. */ + private final double wavelength; + + /** Simple constructor. + * @param noiseSource noise source, may be null for generating perfect measurements + * @param station ground station from which measurement is performed + * @param wavelength phase observed value wavelength (m) + * @param sigma theoretical standard deviation + * @param baseWeight base weight + * @param satellite satellite related to this builder + */ + public PhaseBuilder(final CorrelatedRandomVectorGenerator noiseSource, + final GroundStation station, final double wavelength, + final double sigma, final double baseWeight, + final ObservableSatellite satellite) { + super(noiseSource, sigma, baseWeight, satellite); + this.station = station; + this.wavelength = wavelength; + } + + /** {@inheritDoc} */ + @Override + public Phase build(final SpacecraftState[] states) { + + final ObservableSatellite satellite = getSatellites()[0]; + final double sigma = getTheoreticalStandardDeviation()[0]; + final double baseWeight = getBaseWeight()[0]; + final SpacecraftState[] relevant = new SpacecraftState[] { states[satellite.getPropagatorIndex()] }; + + // create a dummy measurement + final Phase dummy = new Phase(station, relevant[0].getDate(), Double.NaN, wavelength, sigma, baseWeight, satellite); + for (final EstimationModifier modifier : getModifiers()) { + dummy.addModifier(modifier); + } + + // set a reference date for parameters missing one + for (final ParameterDriver driver : dummy.getParametersDrivers()) { + if (driver.getReferenceDate() == null) { + final AbsoluteDate start = getStart(); + final AbsoluteDate end = getEnd(); + driver.setReferenceDate(start.durationFrom(end) <= 0 ? start : end); + } + } + + // estimate the perfect value of the measurement + double phase = dummy.estimate(0, 0, relevant).getEstimatedValue()[0]; + + // add the noise + final double[] noise = getNoise(); + if (noise != null) { + phase += noise[0]; + } + + // generate measurement + final Phase measurement = new Phase(station, relevant[0].getDate(), phase, wavelength, sigma, baseWeight, satellite); + for (final EstimationModifier modifier : getModifiers()) { + measurement.addModifier(modifier); + } + return measurement; + + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/PhaseMinusCodeCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/PhaseMinusCodeCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..7c1df7d3f9619d7ac235f36d7c48bc6495701992 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/PhaseMinusCodeCombination.java @@ -0,0 +1,57 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.orekit.gnss.SatelliteSystem; + +/** + * Phase minus Code combination. + *

+ * This combination is a single frequency combination of + * measurements that can be used for cycle-slip detection. + *

+ *
+ *    mf =  Φf - Rf
+ * 
+ * With: + *
    + *
  • mf : Phase minus Code measurement.
  • + *
  • Φf : Phase measurement.
  • + *
  • Rf : Code measurement.
  • + *
  • f : Frequency.
  • + *
+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class PhaseMinusCodeCombination extends AbstractSingleFrequencyCombination { + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + PhaseMinusCodeCombination(final SatelliteSystem system) { + super(CombinationType.PHASE_MINUS_CODE, system); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedValue(final double phase, final double pseudoRange, final double f) { + // Combination does not depend on the frequency + return phase - pseudoRange; + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/WideLaneCombination.java b/src/main/java/org/orekit/estimation/measurements/gnss/WideLaneCombination.java new file mode 100644 index 0000000000000000000000000000000000000000..519bea981563c2320692b2f1b0f508ba6cdbfb97 --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/WideLaneCombination.java @@ -0,0 +1,79 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import org.hipparchus.util.MathArrays; +import org.orekit.gnss.Frequency; +import org.orekit.gnss.MeasurementType; +import org.orekit.gnss.SatelliteSystem; + +/** + * Wide-Lane combination. + *

+ * This combination are used to create a signal + * with a significantly wide wavelength. + * This longer wavelength is useful for cycle-slips + * detection and ambiguity fixing + *

+ *
+ *              f1 * m1 - f2 * m2
+ *    mWL =  -----------------------
+ *                   f1 - f2
+ * 
+ * With: + *
    + *
  • mWL: Wide-laning measurement.
  • + *
  • f1 : Frequency of the first measurement.
  • + *
  • m1 : First measurement.
  • + *
  • f2 : Frequency of the second measurement.
  • + *
  • m1 : Second measurement.
  • + *
+ *

+ * Wide-Lane combination is a dual frequency combination. + * The two measurements shall have different frequencies but they must have the same {@link MeasurementType}. + *

+ * @author Bryan Cazabonne + * @since 10.1 + */ +public class WideLaneCombination extends AbstractDualFrequencyCombination { + + /** + * Package private constructor for the factory. + * @param system satellite system for wich the combination is applied + */ + WideLaneCombination(final SatelliteSystem system) { + super(CombinationType.WIDE_LANE, system); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedValue(final double obs1, final Frequency f1, + final double obs2, final Frequency f2) { + // Get the ration f/f0 + final double ratioF1 = f1.getRatio(); + final double ratioF2 = f2.getRatio(); + // Perform combination + return MathArrays.linearCombination(ratioF1, obs1, -ratioF2, obs2) / (ratioF1 - ratioF2); + } + + /** {@inheritDoc} */ + @Override + protected double getCombinedFrequency(final Frequency f1, final Frequency f2) { + return f1.getMHzFrequency() - f2.getMHzFrequency(); + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/WindUp.java b/src/main/java/org/orekit/estimation/measurements/gnss/WindUp.java new file mode 100644 index 0000000000000000000000000000000000000000..c32bc4e618c95cb74992cb2bfef83276021462bd --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/WindUp.java @@ -0,0 +1,106 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import java.util.Collections; +import java.util.List; + +import org.hipparchus.geometry.euclidean.threed.Rotation; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.MathUtils; +import org.orekit.estimation.measurements.EstimatedMeasurement; +import org.orekit.estimation.measurements.EstimationModifier; +import org.orekit.estimation.measurements.GroundStation; +import org.orekit.frames.Frame; +import org.orekit.utils.ParameterDriver; +import org.orekit.utils.TimeStampedPVCoordinates; + +/** Modifier for wind-up effect in GNSS {@link Phase phase measurements}. + * @see Carrier Phase Wind-up Effect + * @see WindUpFactory + * @author Luc Maisonobe + * @since 10.1 + */ +public class WindUp implements EstimationModifier { + + /** Cached angular value of wind-up. */ + private double angularWindUp; + + /** Simple constructor. + *

+ * The constructor is package protected to enforce use of {@link WindUpFactory} + * and preserve phase continuity for successive measurements involving the same + * satellite/receiver pair. + *

+ */ + WindUp() { + angularWindUp = 0.0; + } + + /** {@inheritDoc} + *

+ * Wind-up effect has no parameters, the returned list is always empty. + *

+ */ + @Override + public List getParametersDrivers() { + return Collections.emptyList(); + } + + /** {@inheritDoc} */ + @Override + public void modify(final EstimatedMeasurement estimated) { + + // signal line of sight + final TimeStampedPVCoordinates[] participants = estimated.getParticipants(); + final Vector3D los = participants[1].getPosition().subtract(participants[0].getPosition()).normalize(); + + // get ground antenna dipole + final Frame inertial = estimated.getStates()[0].getFrame(); + final GroundStation station = estimated.getObservedMeasurement().getStation(); + final Rotation offsetToInert = station.getOffsetToInertial(inertial, estimated.getDate()).getRotation(); + final Vector3D iGround = offsetToInert.applyTo(Vector3D.PLUS_I); + final Vector3D jGround = offsetToInert.applyTo(Vector3D.PLUS_J); + final Vector3D dGround = new Vector3D(1.0, iGround, -Vector3D.dotProduct(iGround, los), los). + add(Vector3D.crossProduct(los, jGround)); + + // get satellite dipole + // we don't use the basic yaw steering attitude model from ESA navipedia page + // but rely on the attitude that was computed by the propagator, which takes + // into account the proper noon and midnight turns for each satellite model + final Rotation satToInert = estimated.getStates()[0].toTransform().getRotation().revert(); + final Vector3D iSat = satToInert.applyTo(Vector3D.PLUS_I); + final Vector3D jSat = satToInert.applyTo(Vector3D.PLUS_J); + final Vector3D dSat = new Vector3D(1.0, iSat, -Vector3D.dotProduct(iSat, los), los). + subtract(Vector3D.crossProduct(los, jSat)); + + // raw correction + final double correction = FastMath.copySign(Vector3D.angle(dSat, dGround), + Vector3D.dotProduct(los, Vector3D.crossProduct(dSat, dGround))); + + // ensure continuity accross measurements + // we assume the various measurements are close enough in time + // (less the one satellite half-turn) so the angles remain close + angularWindUp = MathUtils.normalizeAngle(correction, angularWindUp); + + // update estimate + estimated.setEstimatedValue(estimated.getEstimatedValue()[0] + angularWindUp / MathUtils.TWO_PI); + + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/gnss/WindUpFactory.java b/src/main/java/org/orekit/estimation/measurements/gnss/WindUpFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..a7e2889d4a79e87e21186fec4f01fb70f22e1def --- /dev/null +++ b/src/main/java/org/orekit/estimation/measurements/gnss/WindUpFactory.java @@ -0,0 +1,80 @@ +/* Copyright 2002-2019 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.estimation.measurements.gnss; + +import java.util.HashMap; +import java.util.Map; + +import org.orekit.gnss.SatelliteSystem; + +/** Factory for {@link WindUp wind-up} modifiers. + *

+ * The factory ensures the same instance is returned for all + * satellite/receiver pair, thus preserving phase continuity + * for successive measurements involving the same pair. + *

+ * @author Luc Maisonobe + * @since 10.1 + */ +public class WindUpFactory { + + /** Modifiers cache. */ + private final Map>> modifiers; + + /** Simple constructor. + */ + WindUpFactory() { + this.modifiers = new HashMap<>(); + } + + /** Get a modifier for a satellite/receiver pair. + * @param system system the satellite belongs to + * @param prnNumber PRN number + * @param receiverName name of the receiver + * @return modifier for the satellite/receiver pair + */ + public WindUp getWindUp(final SatelliteSystem system, final int prnNumber, final String receiverName) { + + // select satellite system + Map> systemModifiers = modifiers.get(system); + if (systemModifiers == null) { + // build a new map for this satellite system + systemModifiers = new HashMap<>(); + modifiers.put(system, systemModifiers); + } + + // select satellite + Map satelliteModifiers = systemModifiers.get(prnNumber); + if (satelliteModifiers == null) { + // build a new map for this satellite + satelliteModifiers = new HashMap<>(); + systemModifiers.put(prnNumber, satelliteModifiers); + } + + // select receiver + WindUp receiverModifier = satelliteModifiers.get(receiverName); + if (receiverModifier == null) { + // build a new wind-up modifier + receiverModifier = new WindUp(); + satelliteModifiers.put(receiverName, receiverModifier); + } + + return receiverModifier; + + } + +} diff --git a/src/main/java/org/orekit/estimation/measurements/modifiers/DynamicOutlierFilter.java b/src/main/java/org/orekit/estimation/measurements/modifiers/DynamicOutlierFilter.java index f43c68e0ba4d51e51e0c5e7c9d6013e331e2946d..17d1ea3fff2da1973742ec32f54166c3fb73d029 100644 --- a/src/main/java/org/orekit/estimation/measurements/modifiers/DynamicOutlierFilter.java +++ b/src/main/java/org/orekit/estimation/measurements/modifiers/DynamicOutlierFilter.java @@ -32,8 +32,7 @@ import org.orekit.estimation.measurements.ObservedMeasurement; * @author Luc Maisonobe * @since 9.2 */ -public class DynamicOutlierFilter> extends OutlierFilter -{ +public class DynamicOutlierFilter> extends OutlierFilter { /** Current value of sigma. */ private double[] sigma; diff --git a/src/main/java/org/orekit/estimation/measurements/modifiers/IonosphericDSConverter.java b/src/main/java/org/orekit/estimation/measurements/modifiers/IonosphericDSConverter.java index dc4d853c5a8b74a42d9343a607d731a7a85844a5..d543bfdb769b0d2cc3520d3997c30db4ee5fe6d7 100644 --- a/src/main/java/org/orekit/estimation/measurements/modifiers/IonosphericDSConverter.java +++ b/src/main/java/org/orekit/estimation/measurements/modifiers/IonosphericDSConverter.java @@ -89,11 +89,10 @@ public class IonosphericDSConverter { // mass never has derivatives final DerivativeStructure dsM = factory.constant(state.getMass()); - final DerivativeStructure dsMu = factory.constant(state.getMu()); - final FieldOrbit dsOrbit = new FieldCartesianOrbit<>(new TimeStampedFieldPVCoordinates<>(state.getDate(), posDS, velDS, accDS), - state.getFrame(), dsMu); + state.getFrame(), + factory.getDerivativeField().getZero().add(state.getMu())); final FieldAttitude dsAttitude; if (freeStateParameters > 3) { @@ -149,7 +148,7 @@ public class IonosphericDSConverter { extend(pv0.getPosition(), factory), extend(pv0.getVelocity(), factory), extend(pv0.getAcceleration(), factory)), - s0.getFrame(), s0.getMu()); + s0.getFrame(), extend(s0.getMu(), factory)); // attitude final FieldAngularCoordinates ac0 = s0.getAttitude().getOrientation(); diff --git a/src/main/java/org/orekit/estimation/sequential/DSSTKalmanModel.java b/src/main/java/org/orekit/estimation/sequential/DSSTKalmanModel.java index decd8d753cbfbbaa97a259be0673d589b9dae848..506420ab87f3d32c3c3105acf753ed4e2d719c6f 100644 --- a/src/main/java/org/orekit/estimation/sequential/DSSTKalmanModel.java +++ b/src/main/java/org/orekit/estimation/sequential/DSSTKalmanModel.java @@ -35,6 +35,7 @@ import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitMessages; import org.orekit.estimation.measurements.EstimatedMeasurement; import org.orekit.estimation.measurements.EstimationModifier; +import org.orekit.estimation.measurements.ObservableSatellite; import org.orekit.estimation.measurements.ObservedMeasurement; import org.orekit.estimation.measurements.modifiers.DynamicOutlierFilter; import org.orekit.orbits.Orbit; @@ -931,7 +932,7 @@ public class DSSTKalmanModel implements KalmanODModel { // so far. We use this to be able to apply the OutlierFilter modifiers on the predicted measurement. predictedMeasurement = observedMeasurement.estimate(currentMeasurementNumber, currentMeasurementNumber, - predictedSpacecraftStates); + filterRelevant(observedMeasurement, predictedSpacecraftStates)); // Normalized measurement matrix (nxm) final RealMatrix measurementMatrix = getMeasurementMatrix(); @@ -1008,13 +1009,28 @@ public class DSSTKalmanModel implements KalmanODModel { // Compute the estimated measurement using estimated spacecraft state correctedMeasurement = observedMeasurement.estimate(currentMeasurementNumber, currentMeasurementNumber, - correctedSpacecraftStates); + filterRelevant(observedMeasurement, correctedSpacecraftStates)); // Update the trajectory // --------------------- updateReferenceTrajectories(estimatedPropagators); } + /** Filter relevant states for a measurement. + * @param observedMeasurement measurement to consider + * @param allStates all states + * @return array containing only the states relevant to the measurement + * @since 10.1 + */ + private SpacecraftState[] filterRelevant(final ObservedMeasurement observedMeasurement, final SpacecraftState[] allStates) { + final List satellites = observedMeasurement.getSatellites(); + final SpacecraftState[] relevantStates = new SpacecraftState[satellites.size()]; + for (int i = 0; i < relevantStates.length; ++i) { + relevantStates[i] = allStates[satellites.get(i).getPropagatorIndex()]; + } + return relevantStates; + } + /** Set the predicted normalized state vector. * The predicted/propagated orbit is used to update the state vector * @param date prediction date diff --git a/src/main/java/org/orekit/estimation/sequential/KalmanModel.java b/src/main/java/org/orekit/estimation/sequential/KalmanModel.java index 93ec68ab54c42ac43b490f1a0e8863d11c2c333e..c9c0a011e8da431b8753cc21d665c2bd27cbde79 100644 --- a/src/main/java/org/orekit/estimation/sequential/KalmanModel.java +++ b/src/main/java/org/orekit/estimation/sequential/KalmanModel.java @@ -35,6 +35,7 @@ import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitMessages; import org.orekit.estimation.measurements.EstimatedMeasurement; import org.orekit.estimation.measurements.EstimationModifier; +import org.orekit.estimation.measurements.ObservableSatellite; import org.orekit.estimation.measurements.ObservedMeasurement; import org.orekit.estimation.measurements.modifiers.DynamicOutlierFilter; import org.orekit.orbits.Orbit; @@ -909,7 +910,7 @@ public class KalmanModel implements KalmanODModel { // so far. We use this to be able to apply the OutlierFilter modifiers on the predicted measurement. predictedMeasurement = observedMeasurement.estimate(currentMeasurementNumber, currentMeasurementNumber, - predictedSpacecraftStates); + filterRelevant(observedMeasurement, predictedSpacecraftStates)); // Normalized measurement matrix (nxm) final RealMatrix measurementMatrix = getMeasurementMatrix(); @@ -986,13 +987,28 @@ public class KalmanModel implements KalmanODModel { // Compute the estimated measurement using estimated spacecraft state correctedMeasurement = observedMeasurement.estimate(currentMeasurementNumber, currentMeasurementNumber, - correctedSpacecraftStates); + filterRelevant(observedMeasurement, correctedSpacecraftStates)); // Update the trajectory // --------------------- updateReferenceTrajectories(estimatedPropagators); } + /** Filter relevant states for a measurement. + * @param observedMeasurement measurement to consider + * @param allStates all states + * @return array containing only the states relevant to the measurement + * @since 10.1 + */ + private SpacecraftState[] filterRelevant(final ObservedMeasurement observedMeasurement, final SpacecraftState[] allStates) { + final List satellites = observedMeasurement.getSatellites(); + final SpacecraftState[] relevantStates = new SpacecraftState[satellites.size()]; + for (int i = 0; i < relevantStates.length; ++i) { + relevantStates[i] = allStates[satellites.get(i).getPropagatorIndex()]; + } + return relevantStates; + } + /** Set the predicted normalized state vector. * The predicted/propagated orbit is used to update the state vector * @param date prediction date diff --git a/src/main/java/org/orekit/files/ccsds/CcsdsModifiedFrame.java b/src/main/java/org/orekit/files/ccsds/CcsdsModifiedFrame.java index 5f8d5b828bc6f86e17d451379e6cd3537844c08f..dde964f91fad98aaba98128f45ad4248fe506f54 100644 --- a/src/main/java/org/orekit/files/ccsds/CcsdsModifiedFrame.java +++ b/src/main/java/org/orekit/files/ccsds/CcsdsModifiedFrame.java @@ -110,7 +110,7 @@ public class CcsdsModifiedFrame extends Frame { @Override public Transform getTransform(final AbsoluteDate date) { - return new Transform(date, body.getPVCoordinates(date, frame)); + return new Transform(date, body.getPVCoordinates(date, frame).negate()); } @Override @@ -118,7 +118,7 @@ public class CcsdsModifiedFrame extends Frame { final FieldAbsoluteDate date) { return new FieldTransform<>( date, - body.getPVCoordinates(date, frame)); + body.getPVCoordinates(date, frame).negate()); } } diff --git a/src/main/java/org/orekit/files/ccsds/OEMParser.java b/src/main/java/org/orekit/files/ccsds/OEMParser.java index 9ac51ea1099578cda85d41f72990ad7b5ed93286..b5b6eca31eb4db72650ba5835348824f4da83889 100644 --- a/src/main/java/org/orekit/files/ccsds/OEMParser.java +++ b/src/main/java/org/orekit/files/ccsds/OEMParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Scanner; @@ -138,7 +139,7 @@ public class OEMParser extends ODMParser implements EphemerisFileParser { /** {@inheritDoc} */ public OEMFile parse(final InputStream stream, final String fileName) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { return parse(reader, fileName); } catch (IOException ioe) { throw new OrekitException(ioe, new DummyLocalizable(ioe.getMessage())); diff --git a/src/main/java/org/orekit/files/ccsds/OEMWriter.java b/src/main/java/org/orekit/files/ccsds/OEMWriter.java index 71fa0048e201bd194687fd417b9935d9c73c1ae7..53bb84e29aaab60a1382ad5d3c3b172056df0472 100644 --- a/src/main/java/org/orekit/files/ccsds/OEMWriter.java +++ b/src/main/java/org/orekit/files/ccsds/OEMWriter.java @@ -23,6 +23,8 @@ import java.util.Map; import org.orekit.errors.OrekitIllegalArgumentException; import org.orekit.errors.OrekitMessages; +import org.orekit.files.ccsds.OEMFile.CovarianceMatrix; +import org.orekit.files.ccsds.OEMFile.EphemeridesBlock; import org.orekit.files.ccsds.StreamingOemWriter.Segment; import org.orekit.files.general.EphemerisFile; import org.orekit.files.general.EphemerisFile.EphemerisSegment; @@ -163,11 +165,20 @@ public class OEMWriter implements EphemerisFileWriter { metadata.put(Keyword.STOP_TIME, segment.getStop().toString(timeScale)); metadata.put(Keyword.INTERPOLATION_DEGREE, String.valueOf(segment.getInterpolationSamples() - 1)); + final Segment segmentWriter = oemWriter.newSegment(null, metadata); segmentWriter.writeMetadata(); for (final TimeStampedPVCoordinates coordinates : segment.getCoordinates()) { segmentWriter.writeEphemerisLine(coordinates); } + + if (segment instanceof EphemeridesBlock) { + final EphemeridesBlock curr_ephem_block = (EphemeridesBlock) segment; + final List covarianceMatrices = curr_ephem_block.getCovarianceMatrices(); + if (!covarianceMatrices.isEmpty()) { + segmentWriter.writeCovarianceMatrices(covarianceMatrices); + } + } } } diff --git a/src/main/java/org/orekit/files/ccsds/OMMParser.java b/src/main/java/org/orekit/files/ccsds/OMMParser.java index d3dd6fa5a1c35009da9b99159c984bfb9663cc1f..c195c1b0ca1f3560cc01f57e484f7e0d635fbc04 100644 --- a/src/main/java/org/orekit/files/ccsds/OMMParser.java +++ b/src/main/java/org/orekit/files/ccsds/OMMParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -139,7 +140,7 @@ public class OMMParser extends ODMParser { try { final BufferedReader reader = - new BufferedReader(new InputStreamReader(stream, "UTF-8")); + new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); // initialize internal data structures final ParseInfo pi = new ParseInfo(); diff --git a/src/main/java/org/orekit/files/ccsds/OPMParser.java b/src/main/java/org/orekit/files/ccsds/OPMParser.java index 24632228bb9944715a7db3e88a1eba1d2426de4e..ba96adf6e98a24b9482125b5adeed9992323be2d 100644 --- a/src/main/java/org/orekit/files/ccsds/OPMParser.java +++ b/src/main/java/org/orekit/files/ccsds/OPMParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -132,7 +133,7 @@ public class OPMParser extends ODMParser { public OPMFile parse(final InputStream stream, final String fileName) { try { - final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)); // initialize internal data structures final ParseInfo pi = new ParseInfo(); pi.fileName = fileName; diff --git a/src/main/java/org/orekit/files/ccsds/StreamingOemWriter.java b/src/main/java/org/orekit/files/ccsds/StreamingOemWriter.java index 8709523cc4dd02d3531789c9eebb08a762b9cac2..79c4614512eee5620cd307c4f2c18e68a34bbdcc 100644 --- a/src/main/java/org/orekit/files/ccsds/StreamingOemWriter.java +++ b/src/main/java/org/orekit/files/ccsds/StreamingOemWriter.java @@ -20,16 +20,22 @@ import java.io.IOException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.LinkedHashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import org.hipparchus.exception.LocalizedCoreFormats; +import org.hipparchus.linear.RealMatrix; import org.orekit.bodies.CelestialBodyFactory; import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.files.ccsds.OEMFile.CovarianceMatrix; import org.orekit.frames.FactoryManagedFrame; import org.orekit.frames.Frame; +import org.orekit.frames.LOFType; import org.orekit.frames.Predefined; import org.orekit.frames.VersionedITRF; import org.orekit.propagation.Propagator; @@ -495,6 +501,46 @@ public class StreamingOemWriter { writer.append(NEW_LINE); } + /** + * Write covariance matrices of the segment according to section 5.2.5. + * + * @param covarianceMatrices the list of covariance matrices related to the segment. + * @throws IOException if the output stream throws one while writing. + */ + public void writeCovarianceMatrices(final List covarianceMatrices) + throws IOException { + writer.append("COVARIANCE_START").append(NEW_LINE); + // Sort to ensure having the matrices in chronological order when + // they are in the same data section (see section 5.2.5.7) + Collections.sort(covarianceMatrices, (mat1, mat2)->mat1.getEpoch().compareTo(mat2.getEpoch())); + for (final CovarianceMatrix covarianceMatrix : covarianceMatrices) { + final String epoch = dateToString(covarianceMatrix.getEpoch().getComponents(timeScale)); + writeKeyValue(Keyword.EPOCH, epoch); + + if (covarianceMatrix.getFrame() != null ) { + writeKeyValue(Keyword.COV_REF_FRAME, guessFrame(covarianceMatrix.getFrame())); + } else if (covarianceMatrix.getLofType() != null) { + if (covarianceMatrix.getLofType() == LOFType.QSW) { + writeKeyValue(Keyword.COV_REF_FRAME, "RTN"); + } else if (covarianceMatrix.getLofType() == LOFType.TNW) { + writeKeyValue(Keyword.COV_REF_FRAME, covarianceMatrix.getLofType().name()); + } else { + throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, toString()); + } + } + + final RealMatrix covRealMatrix = covarianceMatrix.getMatrix(); + for (int i = 0; i < covRealMatrix.getRowDimension(); i++) { + writer.append(Double.toString(covRealMatrix.getEntry(i, 0))); + for (int j = 1; j < i + 1; j++) { + writer.append(" ").append(Double.toString(covRealMatrix.getEntry(i, j))); + } + writer.append(NEW_LINE); + } + } + writer.append("COVARIANCE_STOP").append(NEW_LINE).append(NEW_LINE); + } + /** * {@inheritDoc} * diff --git a/src/main/java/org/orekit/files/ccsds/TDMParser.java b/src/main/java/org/orekit/files/ccsds/TDMParser.java index 4effd3901a7de59ab627be009708d7ebdafd74f0..ac235760b297bbbcaf1b565ccc27ce387dad4641 100644 --- a/src/main/java/org/orekit/files/ccsds/TDMParser.java +++ b/src/main/java/org/orekit/files/ccsds/TDMParser.java @@ -21,6 +21,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -643,7 +644,7 @@ public class TDMParser extends DefaultHandler { * @return parsed file content in a TDMFile object */ public TDMFile parse(final InputStream stream, final String fileName) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { try { // Initialize internal TDMFile final TDMFile tdmFile = parseInfo.tdmFile; diff --git a/src/main/java/org/orekit/forces/gravity/potential/AstronomicalAmplitudeReader.java b/src/main/java/org/orekit/forces/gravity/potential/AstronomicalAmplitudeReader.java index 101ede303ac63aea613cee480989eb7684b07fa8..27ed1505deefe76a469cda5c017bdc77b7982103 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/AstronomicalAmplitudeReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/AstronomicalAmplitudeReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -122,7 +123,7 @@ public class AstronomicalAmplitudeReader implements DataLoader { throws IOException { // parse the file - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; for (String line = r.readLine(); line != null; line = r.readLine()) { ++lineNumber; diff --git a/src/main/java/org/orekit/forces/gravity/potential/EGMFormatReader.java b/src/main/java/org/orekit/forces/gravity/potential/EGMFormatReader.java index ba48deba478a4bf8cabb17ef62df70ef52bd945b..92e2662ae9335a706a0d14e6ea65273e6ecc9d8a 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/EGMFormatReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/EGMFormatReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -94,7 +95,7 @@ public class EGMFormatReader extends PotentialCoefficientsReader { setTideSystem(TideSystem.TIDE_FREE); } - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); final List> c = new ArrayList>(); final List> s = new ArrayList>(); boolean okFields = true; diff --git a/src/main/java/org/orekit/forces/gravity/potential/FESCHatEpsilonReader.java b/src/main/java/org/orekit/forces/gravity/potential/FESCHatEpsilonReader.java index e457ac41b790b29f1e03b0861292d93fa90b226d..44d44e597f08e21e8d41caa55393f3d0c482f3df 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/FESCHatEpsilonReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/FESCHatEpsilonReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -128,7 +129,7 @@ public class FESCHatEpsilonReader extends OceanTidesReader { // parse the file startParse(name); - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; for (String line = r.readLine(); line != null; line = r.readLine()) { ++lineNumber; diff --git a/src/main/java/org/orekit/forces/gravity/potential/FESCnmSnmReader.java b/src/main/java/org/orekit/forces/gravity/potential/FESCnmSnmReader.java index 0cc1286fcf16e4f09d27083bcaa37ceb8185598a..7772e8fd00124c12b7e00de4baa4ee1d589490a0 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/FESCnmSnmReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/FESCnmSnmReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -92,7 +93,7 @@ public class FESCnmSnmReader extends OceanTidesReader { // parse the file startParse(name); - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; boolean dataStarted = false; for (String line = r.readLine(); line != null; line = r.readLine()) { diff --git a/src/main/java/org/orekit/forces/gravity/potential/GRGSFormatReader.java b/src/main/java/org/orekit/forces/gravity/potential/GRGSFormatReader.java index 4fd4d519acf32bf876bbaeb29d4ec76fab08e069..5e8e37ecb22be34bcb78209a728a4daf5418a37d 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/GRGSFormatReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/GRGSFormatReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -121,7 +122,7 @@ public class GRGSFormatReader extends PotentialCoefficientsReader { // 0 0 .99999999988600E+00 .00000000000000E+00 .153900E-09 .000000E+00 // 2 0 -0.48416511550920E-03 0.00000000000000E+00 .204904E-10 .000000E+00 - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; double[][] c = null; double[][] s = null; diff --git a/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java b/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java index 630226b21f790fb39154ccec94f509c5253f17d8..75a64c35536f9ec3be089a9380c8c06f049ff116 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/ICGEMFormatReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; @@ -202,7 +203,7 @@ public class ICGEMFormatReader extends PotentialCoefficientsReader { normalized = true; tideSystem = TideSystem.UNKNOWN; - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); boolean inHeader = true; double[][] c = null; double[][] s = null; diff --git a/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java b/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java index f102b959504d9dfea315cc805ee46ed88e312240..bf7d6fd3e2ed1ed35bdfac8318da89c4cb57030f 100644 --- a/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java +++ b/src/main/java/org/orekit/forces/gravity/potential/SHMFormatReader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -90,7 +91,7 @@ public class SHMFormatReader extends PotentialCoefficientsReader { boolean normalized = false; TideSystem tideSystem = TideSystem.UNKNOWN; - final BufferedReader r = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader r = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); boolean okEarth = false; boolean okSHM = false; boolean okCoeffs = false; diff --git a/src/main/java/org/orekit/frames/BulletinAFilesLoader.java b/src/main/java/org/orekit/frames/BulletinAFilesLoader.java index 7d3f250af972d2155ba0f05b429ad163835a7289..102876fa04e86490c276f8e01e0be56d02b7b96b 100644 --- a/src/main/java/org/orekit/frames/BulletinAFilesLoader.java +++ b/src/main/java/org/orekit/frames/BulletinAFilesLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -422,7 +423,7 @@ class BulletinAFilesLoader implements EOPHistoryLoader { this.fileName = name; // set up a reader for line-oriented bulletin A files - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); lineNumber = 0; firstMJD = -1; diff --git a/src/main/java/org/orekit/frames/BulletinBFilesLoader.java b/src/main/java/org/orekit/frames/BulletinBFilesLoader.java index b8e5e74797f441d573f223e359c3b04e5dcca123..1a48a80b340b382a8240c2098d64c7c4f2649ce3 100644 --- a/src/main/java/org/orekit/frames/BulletinBFilesLoader.java +++ b/src/main/java/org/orekit/frames/BulletinBFilesLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -293,7 +294,7 @@ class BulletinBFilesLoader implements EOPHistoryLoader { configuration = null; // set up a reader for line-oriented bulletin B files - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); // reset parse info to start new file (do not clear history!) fieldsMap.clear(); diff --git a/src/main/java/org/orekit/frames/EOPC04FilesLoader.java b/src/main/java/org/orekit/frames/EOPC04FilesLoader.java index 481d14fa69f5a1b1cd75cafdff2e3f7f446aa6b5..a59ddae5feb4ebfdbbaa290618783f17515b1375 100644 --- a/src/main/java/org/orekit/frames/EOPC04FilesLoader.java +++ b/src/main/java/org/orekit/frames/EOPC04FilesLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; @@ -206,7 +207,7 @@ class EOPC04FilesLoader implements EOPHistoryLoader { ITRFVersionLoader.ITRFVersionConfiguration configuration = null; // set up a reader for line-oriented bulletin B files - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); // reset parse info to start new file (do not clear history!) lineNumber = 0; diff --git a/src/main/java/org/orekit/frames/ITRFVersionLoader.java b/src/main/java/org/orekit/frames/ITRFVersionLoader.java index 26eaa53a12282ef3079c2bf43cff04f96bc7aed5..fe622d8dd221fc317a9d3f218dbe737ddd2ec5a6 100644 --- a/src/main/java/org/orekit/frames/ITRFVersionLoader.java +++ b/src/main/java/org/orekit/frames/ITRFVersionLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; @@ -146,7 +147,7 @@ public class ITRFVersionLoader { final Pattern patternDD = Pattern.compile(START + NON_BLANK_FIELD + CALENDAR_DATE + CALENDAR_DATE + ITRF + END); // set up a reader for line-oriented bulletin A files - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; String line = null; diff --git a/src/main/java/org/orekit/frames/RapidDataAndPredictionColumnsLoader.java b/src/main/java/org/orekit/frames/RapidDataAndPredictionColumnsLoader.java index fec515f471461b1c927d47bced54f5f9d02d6a21..36c91dbf6a7eb667631b11c76d076b581751d2f3 100644 --- a/src/main/java/org/orekit/frames/RapidDataAndPredictionColumnsLoader.java +++ b/src/main/java/org/orekit/frames/RapidDataAndPredictionColumnsLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; @@ -201,7 +202,7 @@ class RapidDataAndPredictionColumnsLoader implements EOPHistoryLoader { ITRFVersionLoader.ITRFVersionConfiguration configuration = null; // set up a reader for line-oriented bulletin B files - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); // reset parse info to start new file (do not clear history!) lineNumber = 0; diff --git a/src/main/java/org/orekit/frames/RapidDataAndPredictionXMLLoader.java b/src/main/java/org/orekit/frames/RapidDataAndPredictionXMLLoader.java index 579e82b471f809abde704154af6df8ad6032fcdf..15e8abd69816c5f137bb044a8b65447e7a2957cc 100644 --- a/src/main/java/org/orekit/frames/RapidDataAndPredictionXMLLoader.java +++ b/src/main/java/org/orekit/frames/RapidDataAndPredictionXMLLoader.java @@ -19,6 +19,7 @@ package org.orekit.frames; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.SortedSet; @@ -121,7 +122,7 @@ class RapidDataAndPredictionXMLLoader implements EOPHistoryLoader { reader.setEntityResolver((publicId, systemId) -> new InputSource()); // read all file, ignoring header - reader.parse(new InputSource(new InputStreamReader(input, "UTF-8"))); + reader.parse(new InputSource(new InputStreamReader(input, StandardCharsets.UTF_8))); } catch (SAXException se) { if ((se.getCause() != null) && (se.getCause() instanceof OrekitException)) { diff --git a/src/main/java/org/orekit/geometry/fov/AbstractFieldOfView.java b/src/main/java/org/orekit/geometry/fov/AbstractFieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..6fb16775bf6de838e6e640f5740face5394f8a4a --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/AbstractFieldOfView.java @@ -0,0 +1,44 @@ +/* Copyright 2002-2019 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.geometry.fov; + +/** Abstract class representing a spacecraft sensor Field Of View. + * @author Luc Maisonobe + * @since 10.1 + */ +public abstract class AbstractFieldOfView implements FieldOfView { + + /** Margin to apply to the zone. */ + private final double margin; + + /** Build a new instance. + * @param margin angular margin to apply to the zone (if positive, + * points outside of the raw FoV but close enough to the boundary are + * considered visible; if negative, points inside of the raw FoV + * but close enough to the boundary are considered not visible) + */ + protected AbstractFieldOfView(final double margin) { + this.margin = margin; + } + + /** {@inheritDoc} */ + @Override + public double getMargin() { + return margin; + } + +} diff --git a/src/main/java/org/orekit/geometry/fov/CircularFieldOfView.java b/src/main/java/org/orekit/geometry/fov/CircularFieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..72702692eeef5ef50a7089e615b0038adbc03fd8 --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/CircularFieldOfView.java @@ -0,0 +1,93 @@ +/* Copyright 2002-2019 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.geometry.fov; + +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.SinCos; +import org.orekit.propagation.events.VisibilityTrigger; + +/** Class representing a spacecraft sensor Field Of View with circular shape. + *

The field of view is defined by an axis and an half-aperture angle.

+ * @author Luc Maisonobe + * @since 10.1 + */ +public class CircularFieldOfView extends SmoothFieldOfView { + + /** FOV half aperture angle. */ + private final double halfAperture; + + /** Scaled X axis defining FoV boundary. */ + private final Vector3D scaledX; + + /** Scaled Y axis defining FoV boundary. */ + private final Vector3D scaledY; + + /** Scaled Z axis defining FoV boundary. */ + private final Vector3D scaledZ; + + /** Build a new instance. + * @param center direction of the FOV center, in spacecraft frame + * @param halfAperture FOV half aperture angle + * @param margin angular margin to apply to the zone (if positive, + * the Field Of View will consider points slightly outside of the + * zone are still visible) + */ + public CircularFieldOfView(final Vector3D center, final double halfAperture, + final double margin) { + + super(center, center.orthogonal(), margin); + this.halfAperture = halfAperture; + + // precompute utility vectors for walking around the FoV + final SinCos sc = FastMath.sinCos(halfAperture); + scaledX = new Vector3D(sc.sin(), getX()); + scaledY = new Vector3D(sc.sin(), getY()); + scaledZ = new Vector3D(sc.cos(), getZ()); + + } + + /** get the FOV half aperture angle. + * @return FOV half aperture angle + */ + public double getHalfAperture() { + return halfAperture; + } + + /** {@inheritDoc} */ + @Override + public double offsetFromBoundary(final Vector3D lineOfSight, final double angularRadius, + final VisibilityTrigger trigger) { + return Vector3D.angle(getCenter(), lineOfSight) - halfAperture + + trigger.radiusCorrection(angularRadius) - getMargin(); + } + + /** {@inheritDoc} */ + @Override + public Vector3D projectToBoundary(final Vector3D lineOfSight) { + return directionAt(FastMath.atan2(Vector3D.dotProduct(lineOfSight, getY()), + Vector3D.dotProduct(lineOfSight, getX()))); + } + + /** {@inheritDoc} */ + @Override + protected Vector3D directionAt(final double angle) { + final SinCos sc = FastMath.sinCos(angle); + return new Vector3D(sc.cos(), scaledX, sc.sin(), scaledY, 1.0, scaledZ); + } + +} diff --git a/src/main/java/org/orekit/geometry/fov/DoubleDihedraFieldOfView.java b/src/main/java/org/orekit/geometry/fov/DoubleDihedraFieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..2fbce4ad17bbc5a18e24f93f32bd6bffc0ab2753 --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/DoubleDihedraFieldOfView.java @@ -0,0 +1,109 @@ +/* Copyright 2002-2019 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.geometry.fov; + +import org.hipparchus.exception.LocalizedCoreFormats; +import org.hipparchus.geometry.euclidean.threed.Rotation; +import org.hipparchus.geometry.euclidean.threed.RotationConvention; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.geometry.partitioning.Region; +import org.hipparchus.geometry.partitioning.RegionFactory; +import org.hipparchus.geometry.spherical.twod.Sphere2D; +import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet; +import org.hipparchus.util.FastMath; +import org.orekit.errors.OrekitException; + +/** Class representing a spacecraft sensor Field Of View with dihedral shape (i.e. rectangular shape). + * @author Luc Maisonobe + * @since 10.1 + */ +public class DoubleDihedraFieldOfView extends PolygonalFieldOfView { + + /** Build a Field Of View with dihedral shape (i.e. rectangular shape). + * @param center Direction of the FOV center, in spacecraft frame + * @param axis1 FOV dihedral axis 1, in spacecraft frame + * @param halfAperture1 FOV dihedral half aperture angle 1, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @param axis2 FOV dihedral axis 2, in spacecraft frame + * @param halfAperture2 FOV dihedral half aperture angle 2, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @param margin angular margin to apply to the zone (if positive, + * points outside of the raw FoV but close enough to the boundary are + * considered visible; if negative, points inside of the raw FoV + * but close enough to the boundary are considered not visible) + */ + public DoubleDihedraFieldOfView(final Vector3D center, + final Vector3D axis1, final double halfAperture1, + final Vector3D axis2, final double halfAperture2, + final double margin) { + super(createPolygon(center, axis1, halfAperture1, axis2, halfAperture2), margin); + } + + /** Create polygon. + * @param center Direction of the FOV center, in spacecraft frame + * @param axis1 FOV dihedral axis 1, in spacecraft frame + * @param halfAperture1 FOV dihedral half aperture angle 1, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @param axis2 FOV dihedral axis 2, in spacecraft frame + * @param halfAperture2 FOV dihedral half aperture angle 2, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @return built polygon + */ + private static SphericalPolygonsSet createPolygon(final Vector3D center, + final Vector3D axis1, final double halfAperture1, + final Vector3D axis2, final double halfAperture2) { + final RegionFactory factory = new RegionFactory(); + final double tolerance = FastMath.max(FastMath.ulp(2.0 * FastMath.PI), + 1.0e-12 * FastMath.max(halfAperture1, halfAperture2)); + final Region dihedra1 = buildDihedra(factory, tolerance, center, axis1, halfAperture1); + final Region dihedra2 = buildDihedra(factory, tolerance, center, axis2, halfAperture2); + return (SphericalPolygonsSet) factory.intersection(dihedra1, dihedra2); + } + + /** Build a dihedra. + * @param factory factory for regions + * @param tolerance tolerance below which points are considered equal + * @param center Direction of the FOV center, in spacecraft frame + * @param axis FOV dihedral axis, in spacecraft frame + * @param halfAperture FOV dihedral half aperture angle, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @return dihedra + */ + private static Region buildDihedra(final RegionFactory factory, + final double tolerance, final Vector3D center, + final Vector3D axis, final double halfAperture) { + if (halfAperture > 0.5 * FastMath.PI) { + throw new OrekitException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, + halfAperture, 0.0, 0.5 * FastMath.PI); + } + + final Rotation r = new Rotation(axis, halfAperture, RotationConvention.VECTOR_OPERATOR); + final Vector3D normalCenterPlane = Vector3D.crossProduct(axis, center); + final Vector3D normalSidePlus = r.applyInverseTo(normalCenterPlane); + final Vector3D normalSideMinus = r.applyTo(normalCenterPlane.negate()); + + return factory.intersection(new SphericalPolygonsSet(normalSidePlus, tolerance), + new SphericalPolygonsSet(normalSideMinus, tolerance)); + + } + +} diff --git a/src/main/java/org/orekit/geometry/fov/EllipticalFieldOfView.java b/src/main/java/org/orekit/geometry/fov/EllipticalFieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..ec28282d4a60bb942653d663d43e14ab4b9d206a --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/EllipticalFieldOfView.java @@ -0,0 +1,409 @@ +/* Copyright 2002-2019 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.geometry.fov; + +import org.hipparchus.RealFieldElement; +import org.hipparchus.analysis.differentiation.DSFactory; +import org.hipparchus.analysis.differentiation.DerivativeStructure; +import org.hipparchus.geometry.euclidean.threed.FieldVector3D; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.SinCos; +import org.orekit.propagation.events.VisibilityTrigger; + +/** Class representing a spacecraft sensor Field Of View with elliptical shape. + *

+ * There are several ways to define an elliptical shape on the unit sphere. + *

+ *

+ * Without loss of generality, one can assume that with a suitable rotation + * the ellipse center is along the Zell axis and the ellipse principal axes + * are along the Xell and Yell axes. The first defining + * elements for an ellipse are these canonical axes. This class allows specifying + * them by giving directly the Zell axis as the {@code center} of + * the ellipse, and giving a {@code primaryMeridian} vector in the (+Xell, + * Zell) half-plane. It is allowed to have {@code primaryMeridian} not + * orthogonal to {@code center} as orthogonality will be fixed internally. + *

+ *

+ * We can define angular coordinates \((\alpha, \beta)\) as dihedra angles around the + * +Yell and -Xell axes respectively to specify points on the + * unit sphere. The corresponding Cartesian coordinates will be + * \[P_{\alpha,\beta}\left(\begin{gather*} + * \frac{\sin\alpha\cos\beta}{\sqrt{1-\sin^2\alpha\sin^2\beta}}\\ + * \frac{\cos\alpha\sin\beta}{\sqrt{1-\sin^2\alpha\sin^2\beta}}\\ + * \frac{\cos\alpha\cos\beta}{\sqrt{1-\sin^2\alpha\sin^2\beta}} + * \end{gather*}\right)\] + * which shows that angle \(\beta=0\) corresponds to the (Xell, Zell) + * plane and that angle \(\alpha=0\) corresponds to the (Yell, Zell) + * plane. Note that at least one of the angles must be different from \(\pm\frac{\pi}{2}\), + * which means that the expression above is singular for points in the (Xell, + * Yell) plane. + *

+ *

+ * The size of the ellipse is defined by its half aperture angles \(\lambda\) along the + * Xell axis and \(\mu\) along the Yell axis. + * For points belonging to the ellipse, we always have \(-\lambda \le \alpha \le +\lambda\) + * and \(-\mu \le \beta \le +\mu\), equalities being reached at the end of principal axes. + * An ellipse defined on the sphere is not a planar ellipse because the four endpoints + * \((\alpha=\pm\lambda, \beta=0)\) and \((\alpha=0, \beta=\pm\mu)\) are not coplanar + * when \(\lambda\neq\mu\). + *

+ *

+ * We define an ellipse on the sphere as the locus of points \(P\) such that the sum of + * their angular distance to two foci \(F_+\) and \(F_-\) is constant, all points being on + * the sphere. The relationship between the foci and the two half aperture angles \(\lambda\) + * and \(\mu\) with: + * \[\lambda \ge \mu \Rightarrow F_\pm\left(\begin{gather*} + * \pm\sin\delta\\ + * 0\\ + * \cos\delta + * \end{gather*}\right) + * \quad\text{with}\quad + * \cos\delta = \frac{\cos\lambda}{\cos\mu}\] + *

+ *

+ * and + * \[\mu \ge \lambda \Rightarrow F_\pm\left(\begin{gather*} + * 0\\ + * \pm\sin\delta\\ + * \cos\delta + * \end{gather*}\right) + * \quad\text{with}\quad + * \cos\delta = \frac{\cos\mu}{\cos\lambda}\] + *

+ *

+ * It can be shown that the previous definition is equivalent to define first a regular + * planar ellipse drawn on a plane \(z = z_0\) (\(z_0\) being an arbitrary strictly positive + * number, \(z_0=1\) being the simplest choice) with semi major axis \(a=z_0\tan\lambda\) + * and semi minor axis \(b=z_0\tan\mu\) and then to project it onto the sphere using a + * central projection: + * \[\left\{\begin{align*} + * \left(\frac{x}{z_0\tan\lambda}\right)^2 + \left(\frac{y}{z_0\tan\mu}\right)^2 &= \left(\frac{z}{z_0}\right)^2\\ + * x^2 + y^2 + z^2 &= 1 + * \end{align*}\right.\] + *

+ *

+ * Simplifying first equation by \(z_0\) and eliminating \(z^2\) in it using the second equation gives: + * \[\left\{\begin{align*} + * \left(\frac{x}{\sin\lambda}\right)^2 + \left(\frac{y}{\sin\mu}\right)^2 &= 1\\ + * x^2 + y^2 + z^2 &= 1 + * \end{align*}\right.\] + * which shows that the previous definition is also equivalent to define first a + * dimensionless planar ellipse on the \((x, y)\) plane and to project it onto the sphere + * using a projection along \(z\). + *

+ *

+ * Note however that despite the ellipse on the sphere can be computed as a projection + * of an ellipse on the \((x, y)\) plane, the foci of one ellipse are not the projection of the + * foci of the other ellipse. The foci on the plane are closer to each other by a factor + * \(\cos\mu\) than the projection of the foci \(F_+\) and \(F_-\)). + *

+ * @author Luc Maisonobe + * @since 10.1 + */ +public class EllipticalFieldOfView extends SmoothFieldOfView { + + /** Factory for derivatives. */ + private static final DSFactory FACTORY = new DSFactory(1, 3); + + /** FOV half aperture angle for spreading along X (i.e. rotation around +Y). */ + private final double halfApertureAlongX; + + /** FOV half aperture angle for spreading along Y (i.e. rotation around -X). */ + private final double halfApertureAlongY; + + /** tan(halfApertureAlongX). */ + private final double tanX; + + /** tan(halfApertureAlongX). */ + private final double tanY; + + /** Unit vector along major axis. */ + private final Vector3D u; + + /** First focus. */ + private final Vector3D focus1; + + /** Second focus. */ + private final Vector3D focus2; + + /** Cross product of foci. */ + private final Vector3D crossF1F2; + + /** Dot product of foci. */ + private final double dotF1F2; + + /** Half angle between foci. */ + private final double gamma; + + /** Scaling factor for normalizing ellipse points. */ + private final double d; + + /** Angular semi major axis. */ + private double a; + + /** Build a new instance. + *

+ * Using a suitable rotation, an elliptical Field Of View can be oriented such + * that the ellipse center is along the Zell axis, one of its principal + * axes is in the (Xell, Zell) plane and the other principal + * axis is in the (Yell, Zell) plane. Beware that the ellipse + * principal axis that spreads along the Yell direction corresponds to a + * rotation around -Xell axis and that the ellipse principal axis that + * spreads along the Xell direction corresponds to a rotation around + * +Yell axis. The naming convention used here is that the angles are + * named after the spreading axis. + *

+ * @param center direction of the FOV center (i.e. Zell), + * in spacecraft frame + * @param primaryMeridian vector defining the (+Xell, Zell) + * half-plane (it is allowed to have {@code primaryMeridian} not orthogonal to + * {@code center} as orthogonality will be fixed internally) + * @param halfApertureAlongX FOV half aperture angle defining the ellipse spreading + * along Xell (i.e. it corresponds to a rotation around +Yell) + * @param halfApertureAlongY FOV half aperture angle defining the ellipse spreading + * along Yell (i.e. it corresponds to a rotation around -Xell) + * @param margin angular margin to apply to the zone (if positive, + * the Field Of View will consider points slightly outside of the + * zone are still visible) + */ + public EllipticalFieldOfView(final Vector3D center, final Vector3D primaryMeridian, + final double halfApertureAlongX, final double halfApertureAlongY, + final double margin) { + + super(center, primaryMeridian, margin); + + final Vector3D v; + final double b; + if (halfApertureAlongX >= halfApertureAlongY) { + u = getX(); + v = getY(); + a = halfApertureAlongX; + b = halfApertureAlongY; + } else { + u = getY(); + v = getX().negate(); + a = halfApertureAlongY; + b = halfApertureAlongX; + } + + final double cos = FastMath.cos(a) / FastMath.cos(b); + final double sin = FastMath.sqrt(1 - cos * cos); + + this.halfApertureAlongX = halfApertureAlongX; + this.halfApertureAlongY = halfApertureAlongY; + this.tanX = FastMath.tan(halfApertureAlongX); + this.tanY = FastMath.tan(halfApertureAlongY); + this.focus1 = new Vector3D(+sin, u, cos, getZ()); + this.focus2 = new Vector3D(-sin, u, cos, getZ()); + this.crossF1F2 = new Vector3D(-2 * sin * cos, v); + this.dotF1F2 = 2 * cos * cos - 1; + this.gamma = FastMath.acos(cos); + this.d = 1.0 / (1 - dotF1F2 * dotF1F2); + + } + + /** get the FOV half aperture angle for spreading along Xell (i.e. rotation around +Yell). + * @return FOV half aperture angle for spreading along Xell (i.e. rotation around +Yell + */ + public double getHalfApertureAlongX() { + return halfApertureAlongX; + } + + /** get the FOV half aperture angle for spreading along Yell (i.e. rotation around -Xell). + * @return FOV half aperture angle for spreading along Yell (i.e. rotation around -Xell) + */ + public double getHalfApertureAlongY() { + return halfApertureAlongY; + } + + /** Get first focus in spacecraft frame. + * @return first focus in spacecraft frame + */ + public Vector3D getFocus1() { + return focus1; + } + + /** Get second focus in spacecraft frame. + * @return second focus in spacecraft frame + */ + public Vector3D getFocus2() { + return focus2; + } + + /** {@inheritDoc} */ + @Override + public double offsetFromBoundary(final Vector3D lineOfSight, final double angularRadius, + final VisibilityTrigger trigger) { + + final double margin = getMargin(); + final double correctedRadius = trigger.radiusCorrection(angularRadius); + final double deadBand = margin + angularRadius; + + // for faster computation, we start using only the surrounding cap, to filter out + // far away points (which correspond to most of the points if the Field Of View is small) + final double crudeDistance = Vector3D.angle(getZ(), lineOfSight) - a; + if (crudeDistance > deadBand + 0.01) { + // we know we are strictly outside of the zone, + // use the crude distance to compute the (positive) return value + return crudeDistance + correctedRadius - margin; + } + + // we are close, we need to compute carefully the exact offset; + // we project the point to the closest zone boundary + final double d1 = Vector3D.angle(lineOfSight, focus1); + final double d2 = Vector3D.angle(lineOfSight, focus2); + final Vector3D closest = projectToBoundary(lineOfSight, d1, d2); + + // compute raw offset as an accurate signed angle + final double rawOffset = FastMath.copySign(Vector3D.angle(lineOfSight, closest), + d1 + d2 - 2 * a); + + return rawOffset + correctedRadius - getMargin(); + + } + + /** {@inheritDoc} */ + @Override + public Vector3D projectToBoundary(final Vector3D lineOfSight) { + final double d1 = Vector3D.angle(lineOfSight, focus1); + final double d2 = Vector3D.angle(lineOfSight, focus2); + return projectToBoundary(lineOfSight, d1, d2); + } + + /** Find the direction on Field Of View Boundary closest to a line of sight. + * @param lineOfSight line of sight from the center of the Field Of View support + * unit sphere to the target in spacecraft frame + * @param d1 distance to first focus + * @param d2 distance to second focus + * @return direction on Field Of View Boundary closest to a line of sight + */ + private Vector3D projectToBoundary(final Vector3D lineOfSight, final double d1, final double d2) { + + final Vector3D los = lineOfSight.normalize(); + final double side = Vector3D.dotProduct(los, crossF1F2); + if (FastMath.abs(side) < 1.0e-12) { + // the line of sight is almost along the major axis + return directionAt(Vector3D.dotProduct(los, u) > 0 ? 0.0 : FastMath.PI); + } + + // find an initial point on ellipse, that approximates closest point + final double offset0 = 0.5 * (d1 - d2); + double minOffset = -gamma; + double maxOffset = +gamma; + + // find closest ellipse point + DerivativeStructure offset = FACTORY.variable(0, offset0); + for (int i = 0; i < 100; i++) { // this loop usually converges in 1-4 iterations + + // distance function we want to minimize + final FieldVector3D pn = directionAt(offset.add(a), offset.subtract(a).negate(), side); + final DerivativeStructure yn = FieldVector3D.angle(pn, los); + if (yn.getValue() < 1.0e-12) { + // the query point is almost on the ellipse boundary + break; + } + + // Halley's iteration on the derivative (since we want the minimum of the distance function) + final double f0 = yn.getPartialDerivative(1); + final double f1 = yn.getPartialDerivative(2); + final double f2 = yn.getPartialDerivative(3); + double dx = -2 * f0 * f1 / (2 * f1 * f1 - f0 * f2); + if (dx * f0 > 0) { + // the Halley's iteration is going towards maximum, not minimum + // try to go past inflection point + dx = -1.5 * f2 / f1; + } + + // manage bounds + if (dx < 0) { + maxOffset = offset.getValue(); + if (offset.getValue() + dx <= minOffset) { + // we overshoot limit, fall back to bisection + dx = 0.5 * (minOffset - offset.getValue()); + } + } else { + minOffset = offset.getValue(); + if (offset.getValue() + dx >= maxOffset) { + // we overshoot limit, fall back to bisection + dx = 0.5 * (maxOffset - offset.getValue()); + } + } + + // apply offset change + offset = offset.add(dx); + + // check convergence + if (FastMath.abs(dx) < 1.0e-12) { + break; + } + + } + + return directionAt(a + offset.getReal(), a - offset.getReal(), side); + + } + + /** {@inheritDoc} */ + @Override + protected Vector3D directionAt(final double angle) { + final SinCos sce = FastMath.sinCos(angle); + final Vector3D dEll = new Vector3D(tanX * sce.cos(), tanY * sce.sin(), 1.0).normalize(); + return new Vector3D(dEll.getX(), getX(), dEll.getY(), getY(), dEll.getZ(), getZ()); + } + + /** Get a direction from distances to foci. + *

+ * if {@code d1} + {@code d2} = 2 max({@link #getHalfApertureAlongX()}, {@link #getHalfApertureAlongY()}), + * then the point is on the ellipse boundary + *

+ * @param d1 distance to focus 1 + * @param d2 distance to focus 2 + * @param sign sign of the ellipse point with respect to F1 ^ F2 + * @return direction + */ + private Vector3D directionAt(final double d1, final double d2, final double sign) { + final double cos1 = FastMath.cos(d1); + final double cos2 = FastMath.cos(d2); + final double a1 = (cos1 - cos2 * dotF1F2) * d; + final double a2 = (cos2 - cos1 * dotF1F2) * d; + final double ac = FastMath.sqrt((1 - (a1 * a1 + 2 * a1 * a2 * dotF1F2 + a2 * a2)) * d); + return new Vector3D(a1, focus1, a2, focus2, FastMath.copySign(ac, sign), crossF1F2); + } + + /** Get a direction from distances to foci. + *

+ * if {@code d1} + {@code d2} = 2 max({@link #getHalfApertureAlongX()}, {@link #getHalfApertureAlongY()}), + * then the point is on the ellipse boundary + *

+ * @param d1 distance to focus 1 + * @param d2 distance to focus 2 + * @param sign sign of the ellipse point with respect to F1 ^ F2 + * @param type of the field element + * @return direction + */ + private > FieldVector3D directionAt(final T d1, final T d2, final double sign) { + final T cos1 = FastMath.cos(d1); + final T cos2 = FastMath.cos(d2); + final T a1 = cos1.subtract(cos2.multiply(dotF1F2)).multiply(d); + final T a2 = cos2.subtract(cos1.multiply(dotF1F2)).multiply(d); + final T ac = FastMath.sqrt(a1.multiply(a1.add(a2.multiply(2 * dotF1F2))).add(a2.multiply(a2)).negate().add(1).multiply(d)); + return new FieldVector3D<>(a1, focus1, a2, focus2, FastMath.copySign(ac, sign), crossF1F2); + } + +} diff --git a/src/main/java/org/orekit/geometry/fov/FieldOfView.java b/src/main/java/org/orekit/geometry/fov/FieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..ddf6cbc461b70271b9f1fd58402e746feb6af807 --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/FieldOfView.java @@ -0,0 +1,150 @@ +/* Copyright 2002-2019 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.geometry.fov; + +import java.util.List; + +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.bodies.OneAxisEllipsoid; +import org.orekit.frames.Transform; +import org.orekit.propagation.events.VisibilityTrigger; + +/** Interface representing a spacecraft sensor Field Of View. + *

Fields Of View are zones defined on the unit sphere centered on the + * spacecraft. Different implementations may use specific modeling + * depending on the shape.

+ * @author Luc Maisonobe + * @since 10.1 + */ +public interface FieldOfView { + + /** Get the angular margin to apply (radians). + * If angular margin is positive, points outside of the raw FoV but close + * enough to the boundary are considered visible. If angular margin is negative, + * points inside of the raw FoV but close enough to the boundary are considered + * not visible + * @return angular margin + * @see #offsetFromBoundary(Vector3D, double, VisibilityTrigger) + */ + double getMargin(); + + /** Get the offset of target body with respect to the Field Of View Boundary. + *

+ * The offset is the signed angular distance between target body and closest boundary + * point, taking into account {@link VisibilityTrigger} and {@link #getMargin() margin}. + *

+ *

+ * As Field Of View can have complex shapes that may require long computation, + * when the target point can be proven to be outside of the Field Of View, a + * faster but approximate computation can be used. This approximation is only + * performed about 0.01 radians outside of the Field Of View augmented by the + * deadband defined by target body radius and Field Of View margin and should be + * designed to still return a positive value if the full accurate computation + * would return a positive value. When target point is close to the zone (and + * furthermore when it is inside the zone), the full accurate computation is + * performed. This design allows this offset to be used as a reliable way to + * detect Field Of View boundary crossings (taking {@link VisibilityTrigger} + * and {@link #getMargin() margin} into account), which correspond to sign + * changes of the offset. + *

+ * @param lineOfSight line of sight from the center of the Field Of View support + * unit sphere to the target in spacecraft frame + * @param angularRadius target body angular radius + * @param trigger visibility trigger for spherical bodies + * @return an offset negative if the target is visible within the Field Of + * View and positive if it is outside of the Field Of View + * (note that this cannot take into account interposing bodies) + * @see #offsetFromBoundary(Vector3D, double, VisibilityTrigger) + */ + double offsetFromBoundary(Vector3D lineOfSight, double angularRadius, VisibilityTrigger trigger); + + /** Find the direction on Field Of View Boundary closest to a line of sight. + * @param lineOfSight line of sight from the center of the Field Of View support + * unit sphere to the target in spacecraft frame + * @return direction on Field Of View Boundary closest to a line of sight + */ + Vector3D projectToBoundary(Vector3D lineOfSight); + + /** Get the footprint of the Field Of View on ground. + *

+ * This method assumes the Field Of View is centered on some carrier, + * which will typically be a spacecraft or a ground station antenna. + * The points in the footprint boundary loops are all at altitude zero + * with respect to the ellipsoid, they correspond either to projection + * on ground of the edges of the Field Of View, or to points on the body + * limb if the Field Of View goes past horizon. The points on the limb + * see the carrier origin at zero elevation. If the Field Of View is so + * large it contains entirely the body, all points will correspond to + * points at limb. If the Field Of View looks away from body, the + * boundary loops will be an empty list. The points within footprint + * loops are sorted in trigonometric order as seen from the carrier. + * This implies that someone traveling on ground from one point to the + * next one will have the points visible from the carrier on his left + * hand side, and the points not visible from the carrier on his right + * hand side. + *

+ *

+ * The truncation of Field Of View at limb can induce strange results + * for complex Fields Of View. If for example a Field Of View is a + * ring with a hole and part of the ring goes past horizon, then instead + * of having a single loop with a C-shaped boundary, the method will + * still return two loops truncated at the limb, one clockwise and one + * counterclockwise, hence "closing" the C-shape twice. This behavior + * is considered acceptable. + *

+ *

+ * If the carrier is a spacecraft, then the {@code fovToBody} transform + * can be computed from a {@link org.orekit.propagation.SpacecraftState} + * as follows: + *

+ *
+     * Transform inertToBody = state.getFrame().getTransformTo(body.getBodyFrame(), state.getDate());
+     * Transform fovToBody   = new Transform(state.getDate(),
+     *                                       state.toTransform().getInverse(),
+     *                                       inertToBody);
+     * 
+ *

+ * If the carrier is a ground station, located using a topocentric frame + * and managing its pointing direction using a transform between the + * dish frame and the topocentric frame, then the {@code fovToBody} transform + * can be computed as follows: + *

+ *
+     * Transform topoToBody = topocentricFrame.getTransformTo(body.getBodyFrame(), date);
+     * Transform topoToDish = ...
+     * Transform fovToBody  = new Transform(date,
+     *                                      topoToDish.getInverse(),
+     *                                      topoToBody);
+     * 
+ *

+ * Only the raw zone is used, the angular margin is ignored here. + *

+ * @param fovToBody transform between the frame in which the Field Of View + * is defined and body frame. + * @param body body surface the Field Of View will be projected on + * @param angularStep step used for boundary loops sampling (radians), + * beware this is generally not an angle on the unit sphere, but rather a + * phase angle used by the underlying Field Of View boundary model + * @return list footprint boundary loops (there may be several independent + * loops if the Field Of View shape is complex) + */ + List> getFootprint(Transform fovToBody, + OneAxisEllipsoid body, + double angularStep); + +} diff --git a/src/main/java/org/orekit/geometry/fov/PolygonalFieldOfView.java b/src/main/java/org/orekit/geometry/fov/PolygonalFieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..638a76933e3f323a7c0e2909575d3edfeb3e8e87 --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/PolygonalFieldOfView.java @@ -0,0 +1,333 @@ +/* Copyright 2002-2019 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.geometry.fov; + +import java.util.ArrayList; +import java.util.List; + +import org.hipparchus.geometry.enclosing.EnclosingBall; +import org.hipparchus.geometry.euclidean.threed.Line; +import org.hipparchus.geometry.euclidean.threed.Rotation; +import org.hipparchus.geometry.euclidean.threed.RotationConvention; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.geometry.partitioning.Region; +import org.hipparchus.geometry.spherical.twod.Edge; +import org.hipparchus.geometry.spherical.twod.S2Point; +import org.hipparchus.geometry.spherical.twod.Sphere2D; +import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet; +import org.hipparchus.geometry.spherical.twod.Vertex; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.MathUtils; +import org.hipparchus.util.SinCos; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.bodies.OneAxisEllipsoid; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.frames.Frame; +import org.orekit.frames.Transform; +import org.orekit.propagation.events.VisibilityTrigger; + +/** Class representing a spacecraft sensor Field Of View with polygonal shape. + *

Fields Of View are zones defined on the unit sphere centered on the + * spacecraft. They can have any shape, they can be split in several + * non-connected patches and can have holes.

+ * @author Luc Maisonobe + * @since 10.1 + */ +public class PolygonalFieldOfView extends AbstractFieldOfView { + + /** Spherical zone. */ + private final SphericalPolygonsSet zone; + + /** Spherical cap surrounding the zone. */ + private final EnclosingBall cap; + + /** Build a new instance. + * @param zone interior of the Field Of View, in spacecraft frame + * @param margin angular margin to apply to the zone (if positive, + * points outside of the raw FoV but close enough to the boundary are + * considered visible; if negative, points inside of the raw FoV + * but close enough to the boundary are considered not visible) + */ + public PolygonalFieldOfView(final SphericalPolygonsSet zone, final double margin) { + super(margin); + this.zone = zone; + this.cap = zone.getEnclosingCap(); + } + + /** Build Field Of View with a regular polygon shape. + * @param center center of the polygon (the center is in the inside part) + * @param meridian point defining the reference meridian for middle of first edge + * @param insideRadius distance of the edges middle points to the center + * (the polygon vertices will therefore be farther away from the center) + * @param n number of sides of the polygon + * @param margin angular margin to apply to the zone (if positive, + * points outside of the raw FoV but close enough to the boundary are + * considered visible; if negative, points inside of the raw FoV + * but close enough to the boundary are considered not visible) + * @deprecated as of 10.1, replaced by {@link #PolygonalFieldOfView(Vector3D, + * DefiningConeType, Vector3D, double, int, double)} + */ + @Deprecated + public PolygonalFieldOfView(final Vector3D center, final Vector3D meridian, + final double insideRadius, final int n, + final double margin) { + this(center, DefiningConeType.INSIDE_CONE_TOUCHING_POLYGON_AT_EDGES_MIDDLE, + meridian, insideRadius, n, margin); + } + + /** Build Field Of View with a regular polygon shape. + * @param center center of the polygon (the center is in the inside part) + * @param coneType type of defining cone + * @param meridian point defining the reference meridian for one contact + * point between defining cone and polygon (i.e. either a polygon edge + * middle point or a polygon vertex) + * @param radius defining cone angular radius + * @param n number of sides of the polygon + * @param margin angular margin to apply to the zone (if positive, + * points outside of the raw FoV but close enough to the boundary are + * considered visible; if negative, points inside of the raw FoV + * but close enough to the boundary are considered not visible) + * @since 10.1 + */ + public PolygonalFieldOfView(final Vector3D center, final DefiningConeType coneType, + final Vector3D meridian, final double radius, + final int n, final double margin) { + + super(margin); + + final double verticesRadius = coneType.verticesRadius(radius, n); + final Vector3D vertex = coneType.createVertex(center, meridian, verticesRadius, n); + this.zone = new SphericalPolygonsSet(center, vertex, verticesRadius, + n, 1.0e-12 * verticesRadius); + + final Rotation r = new Rotation(center, MathUtils.TWO_PI / n, RotationConvention.VECTOR_OPERATOR); + final S2Point[] support = new S2Point[n]; + support[0] = new S2Point(vertex); + for (int i = 1; i < n; ++i) { + support[i] = new S2Point(r.applyTo(support[i - 1].getVector())); + } + this.cap = new EnclosingBall<>(new S2Point(center), Vector3D.angle(center, vertex), support); + + } + + /** Get the interior zone. + * @return the interior zone + */ + public SphericalPolygonsSet getZone() { + return zone; + } + + /** {@inheritDoc} */ + @Override + public double offsetFromBoundary(final Vector3D lineOfSight, final double angularRadius, + final VisibilityTrigger trigger) { + + final S2Point los = new S2Point(lineOfSight); + final double margin = getMargin(); + final double correctedRadius = trigger.radiusCorrection(angularRadius); + final double deadBand = margin + angularRadius; + + // for faster computation, we start using only the surrounding cap, to filter out + // far away points (which correspond to most of the points if the Field Of View is small) + final double crudeDistance = cap.getCenter().distance(los) - cap.getRadius(); + if (crudeDistance > deadBand + 0.01) { + // we know we are strictly outside of the zone, + // use the crude distance to compute the (positive) return value + return crudeDistance + correctedRadius - margin; + } + + // we are close, we need to compute carefully the exact offset; + // we project the point to the closest zone boundary + return zone.projectToBoundary(los).getOffset() + correctedRadius - margin; + + } + + /** {@inheritDoc} */ + @Override + public Vector3D projectToBoundary(final Vector3D lineOfSight) { + return ((S2Point) zone.projectToBoundary(new S2Point(lineOfSight)).getProjected()).getVector(); + } + + /** {@inheritDoc} */ + @Override + public List> getFootprint(final Transform fovToBody, + final OneAxisEllipsoid body, + final double angularStep) { + + final Frame bodyFrame = body.getBodyFrame(); + final Vector3D position = fovToBody.transformPosition(Vector3D.ZERO); + final double r = position.getNorm(); + if (body.isInside(position)) { + throw new OrekitException(OrekitMessages.POINT_INSIDE_ELLIPSOID); + } + + final List> footprint = new ArrayList<>(); + + final List boundary = zone.getBoundaryLoops(); + for (final Vertex loopStart : boundary) { + int count = 0; + final List loop = new ArrayList<>(); + boolean intersectionsFound = false; + for (Edge edge = loopStart.getOutgoing(); + count == 0 || edge.getStart() != loopStart; + edge = edge.getEnd().getOutgoing()) { + ++count; + final int n = (int) FastMath.ceil(edge.getLength() / angularStep); + final double delta = edge.getLength() / n; + for (int i = 0; i < n; ++i) { + final Vector3D awaySC = new Vector3D(r, edge.getPointAt(i * delta)); + final Vector3D awayBody = fovToBody.transformPosition(awaySC); + final Line lineOfSight = new Line(position, awayBody, 1.0e-3); + GeodeticPoint gp = body.getIntersectionPoint(lineOfSight, position, + bodyFrame, null); + if (gp != null && + Vector3D.dotProduct(awayBody.subtract(position), + body.transform(gp).subtract(position)) < 0) { + // the intersection is in fact on the half-line pointing + // towards the back side, it is a spurious intersection + gp = null; + } + + if (gp != null) { + // the line of sight does intersect the body + intersectionsFound = true; + } else { + // the line of sight does not intersect body + // we use a point on the limb + gp = body.transform(body.pointOnLimb(position, awayBody), bodyFrame, null); + } + + // add the point in front of the list + // (to ensure the loop will be in trigonometric orientation) + loop.add(0, gp); + + } + } + + if (intersectionsFound) { + // at least some of the points did intersect the body, + // this loop contributes to the footprint + footprint.add(loop); + } + + } + + if (footprint.isEmpty()) { + // none of the Field Of View loops cross the body + // either the body is outside of Field Of View, or it is fully contained + // we check the center + final Vector3D bodyCenter = fovToBody.getInverse().transformPosition(Vector3D.ZERO); + if (zone.checkPoint(new S2Point(bodyCenter)) != Region.Location.OUTSIDE) { + // the body is fully contained in the Field Of View + // we use the full limb as the footprint + final Vector3D x = bodyCenter.orthogonal(); + final Vector3D y = Vector3D.crossProduct(bodyCenter, x).normalize(); + final double sinEta = body.getEquatorialRadius() / r; + final double sinEta2 = sinEta * sinEta; + final double cosAlpha = (FastMath.cos(angularStep) + sinEta2 - 1) / sinEta2; + final int n = (int) FastMath.ceil(MathUtils.TWO_PI / FastMath.acos(cosAlpha)); + final double delta = MathUtils.TWO_PI / n; + final List loop = new ArrayList<>(n); + for (int i = 0; i < n; ++i) { + final Vector3D outside = new Vector3D(r * FastMath.cos(i * delta), x, + r * FastMath.sin(i * delta), y); + loop.add(body.transform(body.pointOnLimb(position, outside), bodyFrame, null)); + } + footprint.add(loop); + } + } + + return footprint; + + } + + /** Enumerate for cone/polygon relative position. + * @since 10.1 + */ + public enum DefiningConeType { + + /** Constant for cones inside polygons and touching it at polygon edges middle points. */ + INSIDE_CONE_TOUCHING_POLYGON_AT_EDGES_MIDDLE() { + + /** {@inheritDoc}*/ + @Override + protected double verticesRadius(final double radius, final int n) { + // convert the inside (edges middle points) radius to outside (vertices) radius + return FastMath.atan(FastMath.tan(radius) / FastMath.cos(FastMath.PI / n)); + } + + /** {@inheritDoc}*/ + @Override + protected Vector3D createVertex(final Vector3D center, final Vector3D meridian, + final double verticesRadius, final int n) { + // convert the edge middle meridian to a vertex + final SinCos scA = FastMath.sinCos(FastMath.PI / n); + final SinCos scR = FastMath.sinCos(verticesRadius); + final Vector3D z = center.normalize(); + final Vector3D y = Vector3D.crossProduct(center, meridian).normalize(); + final Vector3D x = Vector3D.crossProduct(y, z); + return new Vector3D(scR.sin() * scA.cos(), x, scR.sin() * scA.sin(), y, scR.cos(), z); + } + + }, + + /** Constant for cones outside polygons and touching it at polygon vertices. */ + OUTSIDE_CONE_TOUCHING_POLYGON_AT_VERTICES() { + + /** {@inheritDoc}*/ + @Override + protected double verticesRadius(final double radius, final int n) { + return radius; + } + + /** {@inheritDoc}*/ + @Override + protected Vector3D createVertex(final Vector3D center, final Vector3D meridian, + final double verticesRadius, final int n) { + // convert the vertex meridian to a vertex + final SinCos scR = FastMath.sinCos(verticesRadius); + final Vector3D z = center.normalize(); + final Vector3D y = Vector3D.crossProduct(center, meridian).normalize(); + final Vector3D x = Vector3D.crossProduct(y, z); + return new Vector3D(scR.sin(), x, scR.cos(), z); + } + + }; + + /** Compute radius of cone going through vertices. + * @param radius defining cone angular radius + * @param n number of sides of the polygon + * @return radius of cone going through vertices + */ + protected abstract double verticesRadius(double radius, int n); + + /** Create a vertex. + * @param center center of the polygon (the center is in the inside part) + * @param meridian point defining the reference meridian for one contact + * point between defining cone and polygon (i.e. either a polygon edge + * middle point or a polygon vertex) + * @param verticesRadius defining radius of cone passing through vertices + * @param n number of sides of the polygon + * @return created vertex + */ + protected abstract Vector3D createVertex(Vector3D center, Vector3D meridian, + double verticesRadius, int n); + + } + +} diff --git a/src/main/java/org/orekit/geometry/fov/SmoothFieldOfView.java b/src/main/java/org/orekit/geometry/fov/SmoothFieldOfView.java new file mode 100644 index 0000000000000000000000000000000000000000..f85517f557444fefbd03fc8dada5a0403c61ff91 --- /dev/null +++ b/src/main/java/org/orekit/geometry/fov/SmoothFieldOfView.java @@ -0,0 +1,175 @@ +/* Copyright 2002-2019 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.geometry.fov; + +import java.util.ArrayList; +import java.util.List; + +import org.hipparchus.geometry.euclidean.threed.Line; +import org.hipparchus.geometry.euclidean.threed.Vector3D; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.MathUtils; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.bodies.OneAxisEllipsoid; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.frames.Frame; +import org.orekit.frames.Transform; +import org.orekit.propagation.events.VisibilityTrigger; + +/** Class representing a spacecraft sensor Field Of View with shape defined by a smooth single loop. + * @author Luc Maisonobe + * @since 10.1 + */ +public abstract class SmoothFieldOfView extends AbstractFieldOfView { + + /** Direction of the FOV center. */ + private final Vector3D center; + + /** X axis defining FoV boundary. */ + private final Vector3D xAxis; + + /** Y axis defining FoV boundary. */ + private final Vector3D yAxis; + + /** Z axis defining FoV boundary. */ + private final Vector3D zAxis; + + /** Build a new instance. + * @param center direction of the FOV center (Zsmooth), in spacecraft frame + * @param primaryMeridian vector defining the (+Xsmooth, Zsmooth) + * half-plane (it is allowed to have {@code primaryMeridian} not orthogonal to + * {@code center} as orthogonality will be fixed internally) + * @param margin angular margin to apply to the zone (if positive, + * the Field Of View will consider points slightly outside of the + * zone are still visible) + */ + protected SmoothFieldOfView(final Vector3D center, final Vector3D primaryMeridian, + final double margin) { + + super(margin); + + this.center = center; + this.zAxis = center.normalize(); + this.yAxis = Vector3D.crossProduct(center, primaryMeridian).normalize(); + this.xAxis = Vector3D.crossProduct(yAxis, center).normalize(); + + } + + /** Get the direction of the FOV center, in spacecraft frame. + * @return direction of the FOV center, in spacecraft frame + */ + public Vector3D getCenter() { + return center; + } + + /** Get the X axis defining FoV boundary. + * @return X axis defining FoV boundary, in spacecraft frame + */ + public Vector3D getX() { + return xAxis; + } + + /** Get the Y axis defining FoV boundary. + * @return Y axis defining FoV boundary, in spacecraft frame + */ + public Vector3D getY() { + return yAxis; + } + + /** Get the Z axis defining FoV boundary. + * @return Z axis defining FoV boundary, in spacecraft frame + */ + public Vector3D getZ() { + return zAxis; + } + + + /** {@inheritDoc} */ + @Override + public List> getFootprint(final Transform fovToBody, + final OneAxisEllipsoid body, + final double angularStep) { + + final Frame bodyFrame = body.getBodyFrame(); + final Vector3D position = fovToBody.transformPosition(Vector3D.ZERO); + final double r = position.getNorm(); + if (body.isInside(position)) { + throw new OrekitException(OrekitMessages.POINT_INSIDE_ELLIPSOID); + } + + // prepare loop around FoV + boolean intersectionsFound = false; + final int nbPoints = (int) FastMath.ceil(MathUtils.TWO_PI / angularStep); + final List loop = new ArrayList<>(nbPoints); + + // loop in inverse trigonometric order, so footprint is in trigonometric order + final double step = MathUtils.TWO_PI / nbPoints; + for (int i = 0; i < nbPoints; ++i) { + final Vector3D direction = directionAt(-i * step); + final Vector3D awaySC = new Vector3D(r, direction); + final Vector3D awayBody = fovToBody.transformPosition(awaySC); + final Line lineOfSight = new Line(position, awayBody, 1.0e-3); + GeodeticPoint gp = body.getIntersectionPoint(lineOfSight, position, bodyFrame, null); + if (gp != null && + Vector3D.dotProduct(awayBody.subtract(position), body.transform(gp).subtract(position)) < 0) { + // the intersection is in fact on the half-line pointing + // towards the back side, it is a spurious intersection + gp = null; + } + + if (gp != null) { + // the line of sight does intersect the body + intersectionsFound = true; + } else { + // the line of sight does not intersect body + // we use a point on the limb + gp = body.transform(body.pointOnLimb(position, awayBody), bodyFrame, null); + } + + // add the point + loop.add(gp); + + } + + final List> footprint = new ArrayList<>(); + if (intersectionsFound) { + // at least some of the points did intersect the body, there is a footprint + footprint.add(loop); + } else { + // the Field Of View loop does not cross the body + // either the body is outside of Field Of View, or it is fully contained + // we check the center + final Vector3D bodyCenter = fovToBody.getInverse().transformPosition(Vector3D.ZERO); + if (offsetFromBoundary(bodyCenter, 0.0, VisibilityTrigger.VISIBLE_ONLY_WHEN_FULLY_IN_FOV) < 0.0) { + // the body is fully contained in the Field Of View + // the previous loop did compute the full limb as the footprint + footprint.add(loop); + } + } + + return footprint; + + } + + /** Get boundary direction at angle. + * @param angle phase angle of the boundary direction + * @return boundary direction at phase angle in spacecraft frame + */ + protected abstract Vector3D directionAt(double angle); + +} diff --git a/src/main/java/org/orekit/gnss/CombinedObservationData.java b/src/main/java/org/orekit/gnss/CombinedObservationData.java new file mode 100644 index 0000000000000000000000000000000000000000..dd5742c017c8ce529abc434d29254110325cba71 --- /dev/null +++ b/src/main/java/org/orekit/gnss/CombinedObservationData.java @@ -0,0 +1,105 @@ +/* Copyright 2002-2019 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.gnss; + +import java.util.List; + +import org.orekit.estimation.measurements.gnss.CombinationType; + +/** + * Combined observation data. + * @author Bryan Cazabonne + * @since 10.1 + */ +public class CombinedObservationData { + + /** Type of the combination of measurements. */ + private final CombinationType combinationType; + + /** Measurement type. */ + private final MeasurementType measurementType; + + /** Combined observed value. */ + private double value; + + /** Frequency of the combined observation data [MHz]. */ + private final double combinedFrequency; + + /** Observation data used to perform the combination of measurements. */ + private final List usedData; + + /** + * Constructor. + * @param combinationType combination of measurements used to build the combined observation data + * @param measurementType measurement type used for the combination of measurement + * @param combinedValue combined observed value + * (may be {@code Double.NaN} if combined observation not available) + * @param combinedFrequency frequency of the combined observation data in MHz + * (may be {@code Double.NaN} if combined frequency is not available) + * @param usedData observation data used to perform the combination of measurements + */ + public CombinedObservationData(final CombinationType combinationType, final MeasurementType measurementType, + final double combinedValue, final double combinedFrequency, + final List usedData) { + this.combinationType = combinationType; + this.measurementType = measurementType; + this.value = combinedValue; + this.combinedFrequency = combinedFrequency; + this.usedData = usedData; + } + + /** Get the combined observed value. + * @return observed value (may be {@code Double.NaN} if observation not available) + */ + public double getValue() { + return value; + } + + /** Get the value of the combined frequency in MHz. + *

+ * For the single frequency combinations, this method returns + * the common frequency of both measurements. + *

+ * @return value of the combined frequency in MHz + */ + public double getCombinedMHzFrequency() { + return combinedFrequency; + } + + /** Get the type of the combination of measurements used to build the instance. + * @return the combination of measurements type + */ + public CombinationType getCombinationType() { + return combinationType; + } + + /** Get the measurement type. + * @return measurement type + */ + public MeasurementType getMeasurementType() { + return measurementType; + } + + /** + * Get the list of observation data used to perform the combination of measurements. + * @return a list of observation data + */ + public List getUsedObservationData() { + return usedData; + } + +} diff --git a/src/main/java/org/orekit/gnss/CombinedObservationDataSet.java b/src/main/java/org/orekit/gnss/CombinedObservationDataSet.java new file mode 100644 index 0000000000000000000000000000000000000000..7d10939a63d4e93c5c5ad553f4b39caf5eb1fecd --- /dev/null +++ b/src/main/java/org/orekit/gnss/CombinedObservationDataSet.java @@ -0,0 +1,112 @@ +/* Copyright 2002-2019 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.gnss; + +import java.util.Collections; +import java.util.List; + +import org.orekit.time.AbsoluteDate; +import org.orekit.time.TimeStamped; + +/** + * Combined observation data set. + * @author Bryan Cazabonne + * @since 10.1 + */ +public class CombinedObservationDataSet implements TimeStamped { + + /** Rinex header associated with this data set. */ + private final RinexHeader header; + + /** Satellite System. */ + private final SatelliteSystem satelliteSystem; + + /** PRN Number of the satellite observed. */ + private final int prnNumber; + + /** Date of the observation. */ + private final AbsoluteDate tObs; + + /** List of Observation data. */ + private final List observationData; + + /** Receiver clock offset (seconds). */ + private final double rcvrClkOffset; + + /** + * Simple constructor. + * @param header Rinex header associated with this data set + * @param satelliteSystem Satellite system + * @param prnNumber PRN number + * @param tObs Observation date + * @param rcvrClkOffset Receiver clock offset (optional, 0 by default) + * @param observationData List of combined observation data + */ + public CombinedObservationDataSet(final RinexHeader header, final SatelliteSystem satelliteSystem, + final int prnNumber, final AbsoluteDate tObs, + final double rcvrClkOffset, final List observationData) { + this.header = header; + this.satelliteSystem = satelliteSystem; + this.prnNumber = prnNumber; + this.tObs = tObs; + this.observationData = observationData; + this.rcvrClkOffset = rcvrClkOffset; + } + + /** Get the Rinex header associated with this data set. + * @return Rinex header associated with this data set + * @since 9.3 + */ + public RinexHeader getHeader() { + return header; + } + + /** Get Satellite System. + * @return satellite system of observed satellite + */ + public SatelliteSystem getSatelliteSystem() { + return satelliteSystem; + } + + /** Get PRN number. + * @return PRN number of the observed satellite + */ + public int getPrnNumber() { + return prnNumber; + } + + /** {@inheritDoc} */ + @Override + public AbsoluteDate getDate() { + return tObs; + } + + /** Get list of observation data. + * @return unmodifiable view of of observation data for the observed satellite + */ + public List getObservationData() { + return Collections.unmodifiableList(observationData); + } + + /** Get receiver clock offset. + * @return receiver clock offset (it is optional, may be 0) + */ + public double getRcvrClkOffset() { + return rcvrClkOffset; + } + +} diff --git a/src/main/java/org/orekit/gnss/Frequency.java b/src/main/java/org/orekit/gnss/Frequency.java index 116b742496546eb94a8c2ed20f4d2f7787038a31..8ce9ad924a4bfadd1e5d92b0bc998a72a4537621 100644 --- a/src/main/java/org/orekit/gnss/Frequency.java +++ b/src/main/java/org/orekit/gnss/Frequency.java @@ -16,6 +16,8 @@ */ package org.orekit.gnss; +import org.orekit.utils.Constants; + /** * Enumerate for GNSS frequencies. * @@ -43,6 +45,12 @@ public enum Frequency { /** GLONASS, "G3" (1202.025 MHz). */ R03(SatelliteSystem.GLONASS, "G3", 117.5), + /** GLONASS, "G1a" (1600.995 MHZ). */ + R04(SatelliteSystem.GLONASS, "G1a", 156.5), + + /** GLONASS, "G2a" (1248.06 MHz). */ + R06(SatelliteSystem.GLONASS, "G2a", 122), + /** Galileo, "E1" (1575.42 MHz). */ E01(SatelliteSystem.GALILEO, "E1", 154), @@ -151,12 +159,22 @@ public enum Frequency { } /** Get the value of the frequency in MHz. - * @return satellite system for which this frequency is defined + * @return value of the frequency in MHz * @see #F0 * @see #getRatio() + * @see #getWavelength() */ public double getMHzFrequency() { return ratio * F0; } + /** Get the wavelength in meters. + * @return wavelength in meters + * @see #getMHzFrequency() + * @since 10.1 + */ + public double getWavelength() { + return Constants.SPEED_OF_LIGHT / (1.0e6 * getMHzFrequency()); + } + } diff --git a/src/main/java/org/orekit/gnss/HatanakaCompressFilter.java b/src/main/java/org/orekit/gnss/HatanakaCompressFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..2336002c84f6ec7c3dc11f561f27ec6f1ad881f4 --- /dev/null +++ b/src/main/java/org/orekit/gnss/HatanakaCompressFilter.java @@ -0,0 +1,1038 @@ +/* Copyright 2002-2019 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.gnss; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.hipparchus.util.FastMath; +import org.orekit.data.DataFilter; +import org.orekit.data.NamedData; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; + +/** Decompression filter for Hatanaka compressed RINEX files. + * @see A + * Compression Format and Tools for GNSS Observation Data + * @since 10.1 + */ +public class HatanakaCompressFilter implements DataFilter { + + /** Pattern for rinex 2 observation files. */ + private static final Pattern RINEX_2_PATTERN = Pattern.compile("^(\\w{4}\\d{3}[0a-x](?:\\d{2})?\\.\\d{2})[dD]$"); + + /** Pattern for rinex 3 observation files. */ + private static final Pattern RINEX_3_PATTERN = Pattern.compile("^(\\w{9}_\\w{1}_\\d{11}_\\d{2}\\w_\\d{2}\\w{1}_\\w{2})\\.crx$"); + + /** {@inheritDoc} */ + @Override + public NamedData filter(final NamedData original) { + + final String oName = original.getName(); + final NamedData.StreamOpener oOpener = original.getStreamOpener(); + + final Matcher rinex2Matcher = RINEX_2_PATTERN.matcher(oName); + if (rinex2Matcher.matches()) { + // this is a rinex 2 file compressed with Hatanaka method + final String fName = rinex2Matcher.group(1) + "o"; + final NamedData.StreamOpener fOpener = () -> new HatanakaInputStream(oName, oOpener.openStream()); + return new NamedData(fName, fOpener); + } + + final Matcher rinex3Matcher = RINEX_3_PATTERN.matcher(oName); + if (rinex3Matcher.matches()) { + // this is a rinex 3 file compressed with Hatanaka method + final String fName = rinex3Matcher.group(1) + ".rnx"; + final NamedData.StreamOpener fOpener = () -> new HatanakaInputStream(oName, oOpener.openStream()); + return new NamedData(fName, fOpener); + } + + // it is not an Hatanaka compressed rinex file + return original; + + } + + /** Filtering of Hatanaka compressed stream. */ + private static class HatanakaInputStream extends InputStream { + + /** Format of the current file. */ + private final CompactRinexFormat format; + + /** Line-oriented input. */ + private final BufferedReader reader; + + /** Pending uncompressed output lines. */ + private String pending; + + /** Number of characters already output in pending lines. */ + private int countOut; + + /** Simple constructor. + * @param name file name + * @param input underlying compressed stream + * @exception IOException if first lines cannot be read + */ + HatanakaInputStream(final String name, final InputStream input) + throws IOException { + + reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + + // check header + format = CompactRinexFormat.getFormat(name, reader); + + pending = null; + + } + + /** {@inheritDoc} */ + @Override + public int read() throws IOException { + + if (pending == null) { + // we need to read another section from the underlying stream and uncompress it + countOut = 0; + final String firstLine = reader.readLine(); + if (firstLine == null) { + // there are no lines left + return -1; + } else { + pending = format.uncompressSection(firstLine); + } + } + + if (countOut == pending.length()) { + // output an end of line + pending = null; + return '\n'; + } else { + // output a character from the uncompressed line + return pending.charAt(countOut++); + } + + } + + /** {@inheritDoc} */ + @Override + public void close() throws IOException { + reader.close(); + } + + } + + /** Processor handling differential compression for one numerical data field. */ + private static class NumericDifferential { + + /** Length of the uncompressed text field. */ + private final int fieldLength; + + /** Number of decimal places uncompressed text field. */ + private final int decimalPlaces; + + /** State vector. */ + private final long[] state; + + /** Number of components in the state vector. */ + private int nbComponents; + + /** Uncompressed value. */ + private String uncompressed; + + /** Simple constructor. + * @param fieldLength length of the uncompressed text field + * @param decimalPlaces number of decimal places uncompressed text field + * @param order differential order + */ + NumericDifferential(final int fieldLength, final int decimalPlaces, final int order) { + this.fieldLength = fieldLength; + this.decimalPlaces = decimalPlaces; + this.state = new long[order + 1]; + this.nbComponents = 0; + } + + /** Handle a new compressed value. + * @param sequence sequence containing the value to consider + */ + public void accept(final CharSequence sequence) { + + // store the value as the last component of state vector + state[nbComponents] = Long.parseLong(sequence.toString()); + + // update state vector + for (int i = nbComponents; i > 0; --i) { + state[i - 1] += state[i]; + } + + if (++nbComponents == state.length) { + // the state vector is full + --nbComponents; + } + + // output uncompressed value + final String unscaled = Long.toString(FastMath.abs(state[0])); + final int length = unscaled.length(); + final int digits = FastMath.max(length, decimalPlaces); + final int padding = fieldLength - (digits + (state[0] < 0 ? 2 : 1)); + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < padding; ++i) { + builder.append(' '); + } + if (state[0] < 0) { + builder.append('-'); + } + if (length > decimalPlaces) { + builder.append(unscaled, 0, length - decimalPlaces); + } + builder.append('.'); + for (int i = decimalPlaces; i > 0; --i) { + builder.append(i > length ? '0' : unscaled.charAt(length - i)); + } + + uncompressed = builder.toString(); + + } + + /** Get a string representation of the uncompressed value. + * @return string representation of the uncompressed value + */ + public String getUncompressed() { + return uncompressed; + } + + } + + /** Processor handling text compression for one text data field. */ + private static class TextDifferential { + + /** Buffer holding the current state. */ + private CharBuffer state; + + /** Simple constructor. + * @param fieldLength length of the uncompressed text field + */ + TextDifferential(final int fieldLength) { + this.state = CharBuffer.allocate(fieldLength); + for (int i = 0; i < fieldLength; ++i) { + state.put(i, ' '); + } + } + + /** Handle a new compressed value. + * @param sequence sequence containing the value to consider + */ + public void accept(final CharSequence sequence) { + + // update state + final int length = FastMath.min(state.capacity(), sequence.length()); + for (int i = 0; i < length; ++i) { + final char c = sequence.charAt(i); + if (c == '&') { + // update state with disappearing character + state.put(i, ' '); + } else if (c != ' ') { + // update state with changed character + state.put(i, c); + } + } + + } + + /** Get a string representation of the uncompressed value. + * @return string representation of the uncompressed value + */ + public String getUncompressed() { + return state.toString(); + } + + } + + /** Container for combined observations and flags. */ + private static class CombinedDifferentials { + + /** Observation differentials. */ + private NumericDifferential[] observations; + + /** Flags differential. */ + private TextDifferential flags; + + /** Simple constructor. + * Build an empty container. + * @param nbObs number of observations + */ + CombinedDifferentials(final int nbObs) { + this.observations = new NumericDifferential[nbObs]; + this.flags = new TextDifferential(2 * nbObs); + } + + } + + /** Base class for parsing compact RINEX format. */ + private abstract static class CompactRinexFormat { + + /** Index of label in data lines. */ + private static final int LABEL_START = 60; + + /** Label for compact Rinex version. */ + private static final String CRINEX_VERSION_TYPE = "CRINEX VERS / TYPE"; + + /** Label for compact Rinex program. */ + private static final String CRINEX_PROG_DATE = "CRINEX PROG / DATE"; + + /** Label for number of satellites. */ + private static final String NB_OF_SATELLITES = "# OF SATELLITES"; + + /** Label for end of header. */ + private static final String END_OF_HEADER = "END OF HEADER"; + + /** Default number of satellites (used if not present in the file). */ + private static final int DEFAULT_NB_SAT = 500; + + /** File name. */ + private final String name; + + /** Line-oriented input. */ + private final BufferedReader reader; + + /** Current line number. */ + private int lineNumber; + + /** Maximum number of observations for one satellite. */ + private final Map maxObs; + + /** Number of satellites. */ + private int nbSat; + + /** Indicator for current section type. */ + private Section section; + + /** Satellites observed at current epoch. */ + private List satellites; + + /** Differential engine for epoch. */ + private TextDifferential epochDifferential; + + /** Receiver clock offset differential. */ + private NumericDifferential clockDifferential; + + /** Differential engine for satellites list. */ + private TextDifferential satListDifferential; + + /** Differential engines for each satellite. */ + private Map differentials; + + /** Simple constructor. + * @param name file name + * @param reader line-oriented input + */ + protected CompactRinexFormat(final String name, final BufferedReader reader) { + this.name = name; + this.reader = reader; + this.maxObs = new HashMap<>(); + for (final SatelliteSystem system : SatelliteSystem.values()) { + maxObs.put(system, 0); + } + this.nbSat = DEFAULT_NB_SAT; + this.section = Section.HEADER; + } + + /** Uncompress a section. + * @param firstLine first line of the section + * @return uncompressed section (contains several lines) + * @exception IOException if we cannot read lines from underlying stream + */ + public String uncompressSection(final String firstLine) + throws IOException { + final String uncompressed; + switch (section) { + + case HEADER : { + // header lines + final StringBuilder builder = new StringBuilder(); + String line = firstLine; + lineNumber = 3; // there are 2 CRINEX lines before the RINEX header line + while (section == Section.HEADER) { + if (builder.length() > 0) { + builder.append('\n'); + line = readLine(); + } + builder.append(parseHeaderLine(line)); + trimTrailingSpaces(builder); + } + uncompressed = builder.toString(); + section = Section.EPOCH; + break; + } + + case EPOCH : { + // epoch and receiver clock offset lines + ++lineNumber; // the caller has read one epoch line + uncompressed = parseEpochAndClockLines(firstLine, readLine().trim()); + section = Section.OBSERVATION; + break; + } + + default : { + // observation lines + final String[] lines = new String[satellites.size()]; + ++lineNumber; // the caller has read one observation line + lines[0] = firstLine; + for (int i = 1; i < lines.length; ++i) { + lines[i] = readLine(); + } + uncompressed = parseObservationLines(lines); + section = Section.EPOCH; + } + + } + + return uncompressed; + + } + + /** Parse a header line. + * @param line header line + * @return uncompressed line + */ + public String parseHeaderLine(final String line) { + + if (isHeaderLine(NB_OF_SATELLITES, line)) { + // number of satellites + nbSat = parseInt(line, 0, 6); + } else if (isHeaderLine(END_OF_HEADER, line)) { + // we have reached end of header, prepare parsing of data records + section = Section.EPOCH; + } + + // within header, lines are simply copied + return line; + + } + + /** Parse epoch and receiver clock offset lines. + * @param epochLine epoch line + * @param clockLine receiver clock offset line + * @return uncompressed line + * @exception IOException if we cannot read additional special events lines + */ + public abstract String parseEpochAndClockLines(String epochLine, String clockLine) + throws IOException; + + /** Parse epoch and receiver clock offset lines. + * @param builder builder that may used to copy special event lines + * @param epochStart start of the epoch field + * @param epochLength length of epoch field + * @param eventStart start of the special events field + * @param nbSatStart start of the number of satellites field + * @param satListStart start of the satellites list + * @param clockLength length of receiver clock field + * @param clockDecimalPlaces number of decimal places for receiver clock offset + * @param epochLine epoch line + * @param clockLine receiver clock offset line + * @param resetChar character indicating differentials reset + * @exception IOException if we cannot read additional special events lines + */ + protected void doParseEpochAndClockLines(final StringBuilder builder, + final int epochStart, final int epochLength, + final int eventStart, final int nbSatStart, final int satListStart, + final int clockLength, final int clockDecimalPlaces, + final String epochLine, + final String clockLine, final char resetChar) + throws IOException { + + boolean loop = true; + String loopEpochLine = epochLine; + String loopClockLine = clockLine; + while (loop) { + + // check if differentials should be reset + if (epochDifferential == null || loopEpochLine.charAt(0) == resetChar) { + epochDifferential = new TextDifferential(epochLength); + satListDifferential = new TextDifferential(nbSat * 3); + differentials = new HashMap<>(); + } + + // check for special events + epochDifferential.accept(loopEpochLine.subSequence(epochStart, + FastMath.min(loopEpochLine.length(), epochStart + epochLength))); + if (parseInt(epochDifferential.getUncompressed(), eventStart, 1) > 1) { + // this was not really the epoch, but rather a special event + // we just copy the lines and skip to real epoch and clock lines + builder.append(epochDifferential.getUncompressed()); + trimTrailingSpaces(builder); + builder.append('\n'); + final int skippedLines = parseInt(epochDifferential.getUncompressed(), nbSatStart, 3); + for (int i = 0; i < skippedLines; ++i) { + builder.append(loopClockLine); + trimTrailingSpaces(builder); + builder.append('\n'); + loopClockLine = readLine(); + } + + // the epoch and clock are in the next lines + loopEpochLine = loopClockLine; + loopClockLine = readLine(); + loop = true; + + } else { + loop = false; + final int n = parseInt(epochDifferential.getUncompressed(), nbSatStart, 3); + satellites = new ArrayList<>(n); + if (satListStart < loopEpochLine.length()) { + satListDifferential.accept(loopEpochLine.subSequence(satListStart, loopEpochLine.length())); + } + final String satListPart = satListDifferential.getUncompressed(); + for (int i = 0; i < n; ++i) { + satellites.add(satListPart.subSequence(i * 3, (i + 1) * 3)); + } + + // parse clock offset + if (!loopClockLine.isEmpty()) { + if (loopClockLine.length() > 2 && loopClockLine.charAt(1) == '&') { + clockDifferential = new NumericDifferential(clockLength, clockDecimalPlaces, parseInt(loopClockLine, 0, 1)); + clockDifferential.accept(loopClockLine.subSequence(2, loopClockLine.length())); + } else if (clockDifferential == null) { + throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, + lineNumber, name, loopClockLine); + } else { + clockDifferential.accept(loopClockLine); + } + } + } + } + + } + + /** Get the uncompressed epoch part. + * @return uncompressed epoch part + */ + protected String getEpochPart() { + return epochDifferential.getUncompressed(); + } + + /** Get the uncompressed clock part. + * @return uncompressed clock part + */ + protected String getClockPart() { + return clockDifferential == null ? "" : clockDifferential.getUncompressed(); + } + + /** Get the satellites for current observations. + * @return satellites for current observation + */ + protected List getSatellites() { + return satellites; + } + + /** Get the combined differentials for one satellite. + * @param sat satellite id + * @return observationDifferentials + */ + protected CombinedDifferentials getCombinedDifferentials(final CharSequence sat) { + return differentials.get(sat); + } + + /** Parse observation lines. + * @param observationLines observation lines + * @return uncompressed lines + */ + public abstract String parseObservationLines(String[] observationLines); + + /** Parse observation lines. + * @param dataLength length of data fields + * @param dataDecimalPlaces number of decimal places for data fields + * @param observationLines observation lines + */ + protected void doParseObservationLines(final int dataLength, final int dataDecimalPlaces, + final String[] observationLines) { + + for (int i = 0; i < observationLines.length; ++i) { + + final CharSequence line = observationLines[i]; + + // get the differentials associated with this observations line + final CharSequence sat = satellites.get(i); + CombinedDifferentials satDiffs = differentials.get(sat); + if (satDiffs == null) { + final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(sat.subSequence(0, 1).toString()); + satDiffs = new CombinedDifferentials(maxObs.get(system)); + differentials.put(sat, satDiffs); + } + + // parse observations + int k = 0; + for (int j = 0; j < satDiffs.observations.length; ++j) { + + if (k >= line.length() || line.charAt(k) == ' ') { + // the data field is missing + satDiffs.observations[j] = null; + } else { + // the data field is present + + if (k + 1 < line.length() && + Character.isDigit(line.charAt(k)) && + line.charAt(k + 1) == '&') { + // reinitialize differentials + satDiffs.observations[j] = new NumericDifferential(dataLength, dataDecimalPlaces, + Character.digit(line.charAt(k), 10)); + k += 2; + } + + // extract the compressed differenced value + final int start = k; + while (k < line.length() && line.charAt(k) != ' ') { + ++k; + } + try { + satDiffs.observations[j].accept(line.subSequence(start, k)); + } catch (NumberFormatException nfe) { + throw new OrekitException(nfe, + OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, + lineNumber + i - (observationLines.length - 1), + name, observationLines[i]); + } + + } + + // skip blank separator + ++k; + + } + + if (k < line.length()) { + satDiffs.flags.accept(line.subSequence(k, line.length())); + } + + } + + } + + /** Check if a line corresponds to a header. + * @param label header label + * @param line header line + * @return true if line corresponds to header + */ + protected boolean isHeaderLine(final String label, final String line) { + return label.equals(parseString(line, LABEL_START, label.length())); + } + + /** Update the max number of observations. + * @param system satellite system + * @param nbObs number of observations + */ + protected void updateMaxObs(final SatelliteSystem system, final int nbObs) { + maxObs.put(system, FastMath.max(maxObs.get(system), nbObs)); + } + + /** Read a new line. + * @return line read + * @exception IOException if a read error occurs + */ + private String readLine() + throws IOException { + final String line = reader.readLine(); + if (line == null) { + throw new OrekitException(OrekitMessages.UNEXPECTED_END_OF_FILE, name); + } + lineNumber++; + return line; + } + + /** Get the rinex format corresponding to this compact rinex format. + * @param name file name + * @param reader line-oriented input + * @return rinex format associated with this compact rinex format + * @exception IOException if first lines cannot be read + */ + public static CompactRinexFormat getFormat(final String name, final BufferedReader reader) + throws IOException { + + // read the first two lines of the file + final String line1 = reader.readLine(); + final String line2 = reader.readLine(); + if (line1 == null || line2 == null) { + throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE, name); + } + + // extract format version + final int cVersion100 = (int) FastMath.rint(100 * parseDouble(line1, 0, 9)); + if ((cVersion100 != 100) && (cVersion100 != 300)) { + throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, name); + } + if (!CRINEX_VERSION_TYPE.equals(parseString(line1, LABEL_START, CRINEX_VERSION_TYPE.length()))) { + throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE, name); + } + if (!CRINEX_PROG_DATE.equals(parseString(line2, LABEL_START, CRINEX_PROG_DATE.length()))) { + throw new OrekitException(OrekitMessages.NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE, name); + } + + // build the appropriate parser + return cVersion100 < 300 ? new CompactRinex1(name, reader) : new CompactRinex3(name, reader); + + } + + /** Extract a string from a line. + * @param line to parse + * @param start start index of the string + * @param length length of the string + * @return parsed string + */ + public static String parseString(final String line, final int start, final int length) { + if (line.length() > start) { + return line.substring(start, FastMath.min(line.length(), start + length)).trim(); + } else { + return null; + } + } + + /** Extract an integer from a line. + * @param line to parse + * @param start start index of the integer + * @param length length of the integer + * @return parsed integer + */ + public static int parseInt(final String line, final int start, final int length) { + if (line.length() > start && !parseString(line, start, length).isEmpty()) { + return Integer.parseInt(parseString(line, start, length)); + } else { + return 0; + } + } + + /** Extract a double from a line. + * @param line to parse + * @param start start index of the real + * @param length length of the real + * @return parsed real, or {@code Double.NaN} if field was empty + */ + public static double parseDouble(final String line, final int start, final int length) { + if (line.length() > start && !parseString(line, start, length).isEmpty()) { + return Double.parseDouble(parseString(line, start, length)); + } else { + return Double.NaN; + } + } + + /** Trim trailing spaces in a builder. + * @param builder builder to trim + */ + public static void trimTrailingSpaces(final StringBuilder builder) { + for (int i = builder.length() - 1; i >= 0 && builder.charAt(i) == ' '; --i) { + builder.deleteCharAt(i); + } + } + + /** Enumerate for parsing sections. */ + private enum Section { + + /** Header section. */ + HEADER, + + /** Epoch and receiver clock offset section. */ + EPOCH, + + /** Observation section. */ + OBSERVATION; + + } + + } + + /** Compact RINEX 1 format (for RINEX 2.x). */ + private static class CompactRinex1 extends CompactRinexFormat { + + /** Label for number of observations. */ + private static final String NB_TYPES_OF_OBSERV = "# / TYPES OF OBSERV"; + + /** Start of epoch field. */ + private static final int EPOCH_START = 0; + + /** Length of epoch field. */ + private static final int EPOCH_LENGTH = 32; + + /** Start of events flag. */ + private static final int EVENT_START = EPOCH_START + EPOCH_LENGTH - 4; + + /** Start of number of satellites field. */ + private static final int NB_SAT_START = EPOCH_START + EPOCH_LENGTH - 3; + + /** Start of satellites list field. */ + private static final int SAT_LIST_START = EPOCH_START + EPOCH_LENGTH; + + /** Length of satellites list field. */ + private static final int SAT_LIST_LENGTH = 36; + + /** Maximum number of satellites per epoch line. */ + private static final int MAX_SAT_EPOCH_LINE = 12; + + /** Start of receiver clock field. */ + private static final int CLOCK_START = SAT_LIST_START + SAT_LIST_LENGTH; + + /** Length of receiver clock field. */ + private static final int CLOCK_LENGTH = 12; + + /** Number of decimal places for receiver clock offset. */ + private static final int CLOCK_DECIMAL_PLACES = 9; + + /** Length of a data field. */ + private static final int DATA_LENGTH = 14; + + /** Number of decimal places for data fields. */ + private static final int DATA_DECIMAL_PLACES = 3; + + /** Simple constructor. + * @param name file name + * @param reader line-oriented input + */ + CompactRinex1(final String name, final BufferedReader reader) { + super(name, reader); + } + + @Override + /** {@inheritDoc} */ + public String parseHeaderLine(final String line) { + if (isHeaderLine(NB_TYPES_OF_OBSERV, line)) { + for (final SatelliteSystem system : SatelliteSystem.values()) { + updateMaxObs(system, parseInt(line, 0, 6)); + } + return line; + } else { + return super.parseHeaderLine(line); + } + } + + @Override + /** {@inheritDoc} */ + public String parseEpochAndClockLines(final String epochLine, final String clockLine) + throws IOException { + + final StringBuilder builder = new StringBuilder(); + doParseEpochAndClockLines(builder, + EPOCH_START, EPOCH_LENGTH, EVENT_START, NB_SAT_START, SAT_LIST_START, + CLOCK_LENGTH, CLOCK_DECIMAL_PLACES, epochLine, + clockLine, '&'); + + // build uncompressed lines, taking care of clock being put + // back in line 1 and satellites after 12th put in continuation lines + final List satellites = getSatellites(); + builder.append(getEpochPart()); + int iSat = 0; + while (iSat < FastMath.min(satellites.size(), MAX_SAT_EPOCH_LINE)) { + builder.append(satellites.get(iSat++)); + } + if (!getClockPart().isEmpty()) { + while (builder.length() < CLOCK_START) { + builder.append(' '); + } + builder.append(getClockPart()); + } + + while (iSat < satellites.size()) { + // add a continuation line + trimTrailingSpaces(builder); + builder.append('\n'); + for (int k = 0; k < SAT_LIST_START; ++k) { + builder.append(' '); + } + final int iSatStart = iSat; + while (iSat < FastMath.min(satellites.size(), iSatStart + MAX_SAT_EPOCH_LINE)) { + builder.append(satellites.get(iSat++)); + } + } + trimTrailingSpaces(builder); + return builder.toString(); + + } + + @Override + /** {@inheritDoc} */ + public String parseObservationLines(final String[] observationLines) { + + // parse the observation lines + doParseObservationLines(DATA_LENGTH, DATA_DECIMAL_PLACES, observationLines); + + // build uncompressed lines + final StringBuilder builder = new StringBuilder(); + for (final CharSequence sat : getSatellites()) { + if (builder.length() > 0) { + trimTrailingSpaces(builder); + builder.append('\n'); + } + final CombinedDifferentials cd = getCombinedDifferentials(sat); + final String flags = cd.flags.getUncompressed(); + for (int i = 0; i < cd.observations.length; ++i) { + if (i > 0 && i % 5 == 0) { + trimTrailingSpaces(builder); + builder.append('\n'); + } + if (cd.observations[i] == null) { + // missing observation + for (int j = 0; j < DATA_LENGTH + 2; ++j) { + builder.append(' '); + } + } else { + builder.append(cd.observations[i].getUncompressed()); + if (2 * i < flags.length()) { + builder.append(flags.charAt(2 * i)); + } + if (2 * i + 1 < flags.length()) { + builder.append(flags.charAt(2 * i + 1)); + } + } + } + } + trimTrailingSpaces(builder); + return builder.toString(); + + } + + } + + /** Compact RINEX 3 format (for RINEX 3.x). */ + private static class CompactRinex3 extends CompactRinexFormat { + + /** Label for number of observation types. */ + private static final String SYS_NB_OBS_TYPES = "SYS / # / OBS TYPES"; + + /** Start of epoch field. */ + private static final int EPOCH_START = 0; + + /** Length of epoch field. */ + private static final int EPOCH_LENGTH = 41; + + /** Start of receiver clock field. */ + private static final int CLOCK_START = EPOCH_START + EPOCH_LENGTH; + + /** Length of receiver clock field. */ + private static final int CLOCK_LENGTH = 15; + + /** Number of decimal places for receiver clock offset. */ + private static final int CLOCK_DECIMAL_PLACES = 12; + + /** Start of events flag. */ + private static final int EVENT_START = EPOCH_START + EPOCH_LENGTH - 10; + + /** Start of number of satellites field. */ + private static final int NB_SAT_START = EPOCH_START + EPOCH_LENGTH - 9; + + /** Start of satellites list field (only in the compact rinex). */ + private static final int SAT_LIST_START = EPOCH_START + EPOCH_LENGTH; + + /** Length of a data field. */ + private static final int DATA_LENGTH = 14; + + /** Number of decimal places for data fields. */ + private static final int DATA_DECIMAL_PLACES = 3; + + /** Simple constructor. + * @param name file name + * @param reader line-oriented input + */ + CompactRinex3(final String name, final BufferedReader reader) { + super(name, reader); + } + + @Override + /** {@inheritDoc} */ + public String parseHeaderLine(final String line) { + if (isHeaderLine(SYS_NB_OBS_TYPES, line)) { + if (line.charAt(0) != ' ') { + // it is the first line of an observation types description + // (continuation lines are ignored here) + updateMaxObs(SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)), + parseInt(line, 1, 5)); + } + return line; + } else { + return super.parseHeaderLine(line); + } + } + + @Override + /** {@inheritDoc} */ + public String parseEpochAndClockLines(final String epochLine, final String clockLine) + throws IOException { + + final StringBuilder builder = new StringBuilder(); + doParseEpochAndClockLines(builder, + EPOCH_START, EPOCH_LENGTH, EVENT_START, NB_SAT_START, SAT_LIST_START, + CLOCK_LENGTH, CLOCK_DECIMAL_PLACES, epochLine, + clockLine, '>'); + + // build uncompressed line + builder.append(getEpochPart()); + if (!getClockPart().isEmpty()) { + while (builder.length() < CLOCK_START) { + builder.append(' '); + } + builder.append(getClockPart()); + } + + trimTrailingSpaces(builder); + return builder.toString(); + + } + + @Override + /** {@inheritDoc} */ + public String parseObservationLines(final String[] observationLines) { + + // parse the observation lines + doParseObservationLines(DATA_LENGTH, DATA_DECIMAL_PLACES, observationLines); + + // build uncompressed lines + final StringBuilder builder = new StringBuilder(); + for (final CharSequence sat : getSatellites()) { + if (builder.length() > 0) { + trimTrailingSpaces(builder); + builder.append('\n'); + } + builder.append(sat); + final CombinedDifferentials cd = getCombinedDifferentials(sat); + final String flags = cd.flags.getUncompressed(); + for (int i = 0; i < cd.observations.length; ++i) { + if (cd.observations[i] == null) { + // missing observation + for (int j = 0; j < DATA_LENGTH + 2; ++j) { + builder.append(' '); + } + } else { + builder.append(cd.observations[i].getUncompressed()); + if (2 * i < flags.length()) { + builder.append(flags.charAt(2 * i)); + } + if (2 * i + 1 < flags.length()) { + builder.append(flags.charAt(2 * i + 1)); + } + } + } + } + trimTrailingSpaces(builder); + return builder.toString(); + + } + + } + +} diff --git a/src/main/java/org/orekit/gnss/IRNSSAlmanac.java b/src/main/java/org/orekit/gnss/IRNSSAlmanac.java new file mode 100644 index 0000000000000000000000000000000000000000..7887bdff40ff566ef2bb58b4f568f5af7b47e6e3 --- /dev/null +++ b/src/main/java/org/orekit/gnss/IRNSSAlmanac.java @@ -0,0 +1,212 @@ +/* Copyright 2002-2019 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.gnss; + +import org.hipparchus.util.FastMath; +import org.orekit.propagation.analytical.gnss.IRNSSOrbitalElements; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.GNSSDate; + +/** + * Class for IRNSS almanac. + * + * @see "Indian Regiona Navigation Satellite System, Signal In Space ICD + * for standard positioning service, version 1.1 - Table 28" + * + * @author Bryan Cazabonne + * @since 10.1 + * + */ +public class IRNSSAlmanac implements IRNSSOrbitalElements { + + /** PRN number. */ + private final int prn; + + /** IRNSS week. */ + private final int week; + + /** Time of applicability. */ + private final double toa; + + /** Semi-major axis. */ + private final double sma; + + /** Eccentricity. */ + private final double ecc; + + /** Inclination. */ + private final double inc; + + /** Longitude of Orbital Plane. */ + private final double om0; + + /** Rate of Right Ascension. */ + private final double dom; + + /** Argument of perigee. */ + private final double aop; + + /** Mean anomaly. */ + private final double anom; + + /** Zeroth order clock correction. */ + private final double af0; + + /** First order clock correction. */ + private final double af1; + + /** + * Constructor. + * + * @param prn the PRN number + * @param week the GPS week + * @param toa the Time of Applicability + * @param sqa the Square Root of Semi-Major Axis (m^1/2) + * @param ecc the eccentricity + * @param inc the inclination (rad) + * @param om0 the geographic longitude of the orbital plane at the weekly epoch (rad) + * @param dom the Rate of Right Ascension (rad/s) + * @param aop the Argument of Perigee (rad) + * @param anom the Mean Anomaly (rad) + * @param af0 the Zeroth Order Clock Correction (s) + * @param af1 the First Order Clock Correction (s/s) + */ + public IRNSSAlmanac(final int prn, final int week, final double toa, + final double sqa, final double ecc, final double inc, + final double om0, final double dom, final double aop, + final double anom, final double af0, final double af1) { + this.prn = prn; + this.week = week; + this.toa = toa; + this.sma = sqa * sqa; + this.ecc = ecc; + this.inc = inc; + this.om0 = om0; + this.dom = dom; + this.aop = aop; + this.anom = anom; + this.af0 = af0; + this.af1 = af1; + } + + @Override + public AbsoluteDate getDate() { + return new GNSSDate(week, toa * 1000., SatelliteSystem.IRNSS).getDate(); + } + + @Override + public int getPRN() { + return prn; + } + + @Override + public int getWeek() { + return week; + } + + @Override + public double getTime() { + return toa; + } + + @Override + public double getSma() { + return sma; + } + + @Override + public double getMeanMotion() { + final double absA = FastMath.abs(sma); + return FastMath.sqrt(IRNSS_MU / absA) / absA; + } + + @Override + public double getE() { + return ecc; + } + + @Override + public double getI0() { + return inc; + } + + @Override + public double getIDot() { + return 0; + } + + @Override + public double getOmega0() { + return om0; + } + + @Override + public double getOmegaDot() { + return dom; + } + + @Override + public double getPa() { + return aop; + } + + @Override + public double getM0() { + return anom; + } + + @Override + public double getCuc() { + return 0; + } + + @Override + public double getCus() { + return 0; + } + + @Override + public double getCrc() { + return 0; + } + + @Override + public double getCrs() { + return 0; + } + + @Override + public double getCic() { + return 0; + } + + @Override + public double getCis() { + return 0; + } + + @Override + public double getAf0() { + return af0; + } + + @Override + public double getAf1() { + return af1; + } + +} diff --git a/src/main/java/org/orekit/gnss/MeasurementType.java b/src/main/java/org/orekit/gnss/MeasurementType.java index 8cd0f4a22f0da4a419fc6396b74f213f136d7f62..8bddafe73a02bbf92628998e785224b088b35b3c 100644 --- a/src/main/java/org/orekit/gnss/MeasurementType.java +++ b/src/main/java/org/orekit/gnss/MeasurementType.java @@ -34,6 +34,9 @@ public enum MeasurementType { DOPPLER, /** Signal-strength measurement. */ - SIGNAL_STRENGTH; + SIGNAL_STRENGTH, + + /** Combined pseudo-range carrier-phase measurement. */ + COMBINED_RANGE_PHASE; } diff --git a/src/main/java/org/orekit/gnss/ObservationType.java b/src/main/java/org/orekit/gnss/ObservationType.java index 7d6fb036e64a4213504ed55f3f83121d3e00ba0a..8e56f1889ec60fc78195fe787d072947860f78af 100644 --- a/src/main/java/org/orekit/gnss/ObservationType.java +++ b/src/main/java/org/orekit/gnss/ObservationType.java @@ -30,776 +30,865 @@ import java.util.Map; public enum ObservationType { /** Pseudorange GPS L1 / GLONASS G1 / Galileo E2-L1-E1 / SBAS L1 for Rinex2. */ - C1(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), + C1(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), /** Pseudorange GPS L2 / GLONASS G2 / Beidou B02 for Rinex2. */ - C2(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.R02, Frequency.B02), + C2(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.G02, Frequency.R02, Frequency.B02), /** Pseudorange GPS L5 / Galileo E5a / SBAS L5 for Rinex2. */ - C5(MeasurementType.PSEUDO_RANGE, Frequency.G05, Frequency.E05, Frequency.S05), + C5(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.G05, Frequency.E05, Frequency.S05), /** Pseudorange Galileo E6 / Beidou B03 for Rinex2. */ - C6(MeasurementType.PSEUDO_RANGE, Frequency.E06, Frequency.B03), + C6(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.E06, Frequency.B03), /** Pseudorange Galileo E5b / Beidou B02 for Rinex2. */ - C7(MeasurementType.PSEUDO_RANGE, Frequency.E07, Frequency.B02), + C7(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.E07, Frequency.B02), /** Pseudorange Galileo E5a+b for Rinex2. */ - C8(MeasurementType.PSEUDO_RANGE, Frequency.E08), + C8(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.E08), /** Pseudorange GPS L1 / GLONASS G1 for Rinex2. */ - P1(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.R01), + P1(MeasurementType.PSEUDO_RANGE, SignalCode.P, Frequency.G01, Frequency.R01), /** Pseudorange GPS L2 / GLONASS G2 for Rinex2. */ - P2(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.R02), + P2(MeasurementType.PSEUDO_RANGE, SignalCode.P, Frequency.G02, Frequency.R02), /** Carrier-phase GPS L1 / GLONASS G1 / Galileo E2-L1-E1 / SBAS L1 for Rinex2. */ - L1(MeasurementType.CARRIER_PHASE, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), + L1(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), /** Carrier-phase GPS L2 / GLONASS G2 / Beidou B02 for Rinex2. */ - L2(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.R02, Frequency.B02), + L2(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.G02, Frequency.R02, Frequency.B02), /** Carrier-phase GPS L5 / Galileo E5a / SBAS L5 for Rinex2. */ - L5(MeasurementType.CARRIER_PHASE, Frequency.G05, Frequency.E05, Frequency.S05), + L5(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.G05, Frequency.E05, Frequency.S05), /** Carrier-phase Galileo E6 / Beidou B03 for Rinex2. */ - L6(MeasurementType.CARRIER_PHASE, Frequency.E06, Frequency.C07), + L6(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.E06, Frequency.C07), /** Carrier-phase Galileo E5b / Beidou B02 for Rinex2. */ - L7(MeasurementType.CARRIER_PHASE, Frequency.E07, Frequency.B02), + L7(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.E07, Frequency.B02), /** Carrier-phase Galileo E5a+b for Rinex2. */ - L8(MeasurementType.CARRIER_PHASE, Frequency.E08), + L8(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.E08), /** Carrier-phase GPS L1 C/A / GLONASS G1 C/A for Rinex2. */ - LA(MeasurementType.CARRIER_PHASE, Frequency.G01, Frequency.R01), + LA(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.G01, Frequency.R01), /** Carrier-phase GPS L1C for Rinex2. */ - LB(MeasurementType.CARRIER_PHASE, Frequency.G01), + LB(MeasurementType.CARRIER_PHASE, SignalCode.L, Frequency.G01), /** Carrier-phase GPS L2C for Rinex2. */ - LC(MeasurementType.CARRIER_PHASE, Frequency.G02), + LC(MeasurementType.CARRIER_PHASE, SignalCode.L, Frequency.G02), /** Carrier-phase GLONASS G2 for Rinex2. */ - LD(MeasurementType.CARRIER_PHASE, Frequency.R02), + LD(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.R02), /** Doppler GPS L1 / GLONASS G1 / Galileo E2-L1-E1 / SBAS L1 for Rinex2. */ - D1(MeasurementType.DOPPLER, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), + D1(MeasurementType.DOPPLER, SignalCode.P, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), /** Doppler GPS L2 / GLONASS G2 / Beidou BO2 for Rinex2. */ - D2(MeasurementType.DOPPLER, Frequency.G02, Frequency.R02, Frequency.B02), + D2(MeasurementType.DOPPLER, SignalCode.P, Frequency.G02, Frequency.R02, Frequency.B02), /** Doppler GPS L5 / Galileo E5a / SBAS L5 for Rinex2. */ - D5(MeasurementType.DOPPLER, Frequency.G05, Frequency.E05, Frequency.S05), + D5(MeasurementType.DOPPLER, SignalCode.P, Frequency.G05, Frequency.E05, Frequency.S05), /** Doppler Galileo E6 / Beidou B03 for Rinex2. */ - D6(MeasurementType.DOPPLER, Frequency.E06, Frequency.C07), + D6(MeasurementType.DOPPLER, SignalCode.P, Frequency.E06, Frequency.C07), /** Doppler Galileo E5b / Beidou B02 for Rinex2. */ - D7(MeasurementType.DOPPLER, Frequency.E07, Frequency.B02), + D7(MeasurementType.DOPPLER, SignalCode.P, Frequency.E07, Frequency.B02), /** Doppler Galileo E5a+b for Rinex2. */ - D8(MeasurementType.DOPPLER, Frequency.E08), + D8(MeasurementType.DOPPLER, SignalCode.P, Frequency.E08), /** Doppler GPS L1 / GLONASS G1 / Galileo E2-L1-E1 / SBAS L1 for Rinex2. */ - S1(MeasurementType.SIGNAL_STRENGTH, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), + S1(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01), /** Signal Strength GPS L2 / GLONASS G2 / Beidou B02 for Rinex2. */ - S2(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.R02, Frequency.B02), + S2(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.G02, Frequency.R02, Frequency.B02), /** Signal Strength GPS L5 / Galileo E5a / SBAS L5 for Rinex2. */ - S5(MeasurementType.SIGNAL_STRENGTH, Frequency.G05, Frequency.E05, Frequency.S05), + S5(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.G05, Frequency.E05, Frequency.S05), /** Signal Strength Galileo E6 / Beidou B03 for Rinex2. */ - S6(MeasurementType.SIGNAL_STRENGTH, Frequency.E06, Frequency.C07), + S6(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.E06, Frequency.C07), /** Signal Strength Galileo E5b / Beidou B02 for Rinex2. */ - S7(MeasurementType.SIGNAL_STRENGTH, Frequency.E07, Frequency.B02), + S7(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.E07, Frequency.B02), /** Signal Strength Galileo E5a+b for Rinex2. */ - S8(MeasurementType.SIGNAL_STRENGTH, Frequency.E08), + S8(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.E08), /** Pseudorange Galileo E1 A for Rinex3. */ - C1A(MeasurementType.PSEUDO_RANGE, Frequency.E01), + C1A(MeasurementType.PSEUDO_RANGE, SignalCode.A, Frequency.E01), /** Pseudorange Galileo E1 I/NAV OS/CS/SoL for Rinex3. */ - C1B(MeasurementType.PSEUDO_RANGE, Frequency.E01), + C1B(MeasurementType.PSEUDO_RANGE, SignalCode.B, Frequency.E01), /** Pseudorange GPS L1 C/A / GLONASS G1 C/A / Galileo E1 C / SBAS L1 C/A / QZSS L1 C/A for Rinex3. */ - C1C(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), + C1C(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), /** Pseudorange Beidou B1 I for Rinex3.02. */ - C1I(MeasurementType.PSEUDO_RANGE, Frequency.B01), + C1I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.B01), /** Pseudorange GPS L1 L1C(P) / QZSS L1 L1C(P) for Rinex3. */ - C1L(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.J01), + C1L(MeasurementType.PSEUDO_RANGE, SignalCode.L, Frequency.G01, Frequency.J01), /** Pseudorange GPS L1 M for Rinex3. */ - C1M(MeasurementType.PSEUDO_RANGE, Frequency.G01), + C1M(MeasurementType.PSEUDO_RANGE, SignalCode.M, Frequency.G01), /** Pseudorange GPS L1 P(AS off) / GLONASS G1 P for Rinex3. */ - C1P(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.R01), + C1P(MeasurementType.PSEUDO_RANGE, SignalCode.P, Frequency.G01, Frequency.R01), /** Pseudorange Beidou B1 Q for Rinex3.02. */ - C1Q(MeasurementType.PSEUDO_RANGE, Frequency.B01), + C1Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.B01), /** Pseudorange GPS L1 L1C(D) / QZSS L1 L1C(D) for Rinex3. */ - C1S(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.J01), + C1S(MeasurementType.PSEUDO_RANGE, SignalCode.S, Frequency.G01, Frequency.J01), /** Pseudorange GPS L1 Z-tracking and similar (AS on) for Rinex3. */ - C1W(MeasurementType.PSEUDO_RANGE, Frequency.G01), + C1W(MeasurementType.PSEUDO_RANGE, SignalCode.W, Frequency.G01), /** Pseudorange GPS L1 L1C (D+P) / Galileo E1 B+C / QZSS L1 L1C(D+P) for Rinex3. */ - C1X(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.E01, Frequency.J01), + C1X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.G01, Frequency.E01, Frequency.J01), /** Pseudorange GPS L1 Y for Rinex3. */ - C1Y(MeasurementType.PSEUDO_RANGE, Frequency.G01), + C1Y(MeasurementType.PSEUDO_RANGE, SignalCode.Y, Frequency.G01), /** Pseudorange Galileo E1 C1Z A+B+C / QZSS L1 L1-SAIF for Rinex3. */ - C1Z(MeasurementType.PSEUDO_RANGE, Frequency.E01, Frequency.J01), + C1Z(MeasurementType.PSEUDO_RANGE, SignalCode.Z, Frequency.E01, Frequency.J01), /** Pseudorange GPS L2 C/A / GLONASS G2 C/A for Rinex3. */ - C2C(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.R02), + C2C(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.G02, Frequency.R02), /** Pseudorange GPS L1(C/A)+(P2-P1) (semi-codeless) for Rinex3. */ - C2D(MeasurementType.PSEUDO_RANGE, Frequency.G01), + C2D(MeasurementType.PSEUDO_RANGE, SignalCode.D, Frequency.G02), /** Pseudorange Beidou B1 I for Rinex3.03. */ - C2I(MeasurementType.PSEUDO_RANGE, Frequency.B01), + C2I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.B01), /** Pseudorange GPS L2 L2C(L) / QZSS L2 L2C(2) for Rinex3. */ - C2L(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.J02), + C2L(MeasurementType.PSEUDO_RANGE, SignalCode.L, Frequency.G02, Frequency.J02), /** Pseudorange GPS L2 M for Rinex3. */ - C2M(MeasurementType.PSEUDO_RANGE, Frequency.G02), + C2M(MeasurementType.PSEUDO_RANGE, SignalCode.M, Frequency.G02), /** Pseudorange GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - C2P(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.R02), + C2P(MeasurementType.PSEUDO_RANGE, SignalCode.P, Frequency.G02, Frequency.R02), /** Pseudorange Beidou B1 Q for Rinex3.03. */ - C2Q(MeasurementType.PSEUDO_RANGE, Frequency.B01), + C2Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.B01), /** Pseudorange GPS L2 L2C(M) / QZSS L2 L2C(M) for Rinex3. */ - C2S(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.J02), + C2S(MeasurementType.PSEUDO_RANGE, SignalCode.S, Frequency.G02, Frequency.J02), /** Pseudorange GPS L2 Z-tracking and similar (AS on) for Rinex3. */ - C2W(MeasurementType.PSEUDO_RANGE, Frequency.G02), + C2W(MeasurementType.PSEUDO_RANGE, SignalCode.W, Frequency.G02), /** Pseudorange GPS L2 L2C (M+L) / QZSS L2 L2C(M+L) for Rinex3. */ - C2X(MeasurementType.PSEUDO_RANGE, Frequency.G02, Frequency.J02), + C2X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.G02, Frequency.J02), /** Pseudorange GPS L2 Y for Rinex3. */ - C2Y(MeasurementType.PSEUDO_RANGE, Frequency.G02), + C2Y(MeasurementType.PSEUDO_RANGE, SignalCode.Y, Frequency.G02), /** Pseudorange GLONASS G3 I for Rinex3. */ - C3I(MeasurementType.PSEUDO_RANGE, Frequency.R03), + C3I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.R03), /** Pseudorange GLONASS G3 Q for Rinex3. */ - C3Q(MeasurementType.PSEUDO_RANGE, Frequency.R03), + C3Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.R03), /** Pseudorange GLONASS G3 I+Q for Rinex3. */ - C3X(MeasurementType.PSEUDO_RANGE, Frequency.R03), + C3X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.R03), + + /** Pseudorange GLONASS G1a L1OCd for Rinex3. */ + C4A(MeasurementType.PSEUDO_RANGE, SignalCode.A, Frequency.R04), + + /** Pseudorange GLONASS G1a L1OCp for Rinex3. */ + C4B(MeasurementType.PSEUDO_RANGE, SignalCode.B, Frequency.R04), + + /** Pseudorange GLONASS G1a L1OCd+L1OCd for Rinex3. */ + C4X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.R04), /** Pseudorange IRNSS L5 A for Rinex3. */ - C5A(MeasurementType.PSEUDO_RANGE, Frequency.I05), + C5A(MeasurementType.PSEUDO_RANGE, SignalCode.A, Frequency.I05), /** Pseudorange IRNSS L5 B for Rinex3. */ - C5B(MeasurementType.PSEUDO_RANGE, Frequency.I05), + C5B(MeasurementType.PSEUDO_RANGE, SignalCode.B, Frequency.I05), /** Pseudorange IRNSS L5 C for Rinex3. */ - C5C(MeasurementType.PSEUDO_RANGE, Frequency.I05), + C5C(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.I05), + + /** Pseudorange QZSS L5 D for Rinex3. */ + C5D(MeasurementType.PSEUDO_RANGE, SignalCode.D, Frequency.J05), /** Pseudorange GPS L5 I/ Galileo E5a F/NAV OS / SBAS L5 I / QZSS L5 I for Rinex3. */ - C5I(MeasurementType.PSEUDO_RANGE, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + C5I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + + /** Pseudorange QZSS L5 P for Rinex3. */ + C5P(MeasurementType.PSEUDO_RANGE, SignalCode.P, Frequency.J05), /** Pseudorange GPS L5 Q/ Galileo E5a Q / SBAS L5 Q / QZSS L5 Q for Rinex3. */ - C5Q(MeasurementType.PSEUDO_RANGE, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + C5Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), /** Pseudorange GPS L5 I+Q/ Galileo E5a I+Q / SBAS L5 I+Q / QZSS L5 I+Q / IRNSS L5 B+C for Rinex3. */ - C5X(MeasurementType.PSEUDO_RANGE, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), + C5X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), + + /** Pseudorange QZSS L5 D+P for Rinex3. */ + C5Z(MeasurementType.PSEUDO_RANGE, SignalCode.Z, Frequency.J05), - /** Pseudorange Galileo E6 A PRS for Rinex3. */ - C6A(MeasurementType.PSEUDO_RANGE, Frequency.E06), + /** Pseudorange Galileo E6 A PRS / GLONASS G2a L2CSI for Rinex3. */ + C6A(MeasurementType.PSEUDO_RANGE, SignalCode.A, Frequency.E06, Frequency.R06), - /** Pseudorange Galileo E6 B C/NAV CS for Rinex3. */ - C6B(MeasurementType.PSEUDO_RANGE, Frequency.E06), + /** Pseudorange Galileo E6 B C/NAV CS / GLONASS G2a L2OCp for Rinex3. */ + C6B(MeasurementType.PSEUDO_RANGE, SignalCode.B, Frequency.E06, Frequency.R06), /** Pseudorange Galileo E6 C no data for Rinex3. */ - C6C(MeasurementType.PSEUDO_RANGE, Frequency.E06), + C6C(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.E06), + + /** Pseudorange QZSS L6E for Rinex3. */ + C6E(MeasurementType.PSEUDO_RANGE, SignalCode.E, Frequency.J06), /** Pseudorange Beidou B3 I for Rinex3. */ - C6I(MeasurementType.PSEUDO_RANGE, Frequency.B03), + C6I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.B03), /** Pseudorange Beidou B3 Q for Rinex3. */ - C6Q(MeasurementType.PSEUDO_RANGE, Frequency.B03), + C6Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.B03), /** Pseudorange QZSS LEX(6) L for Rinex3. */ - C6L(MeasurementType.PSEUDO_RANGE, Frequency.J06), + C6L(MeasurementType.PSEUDO_RANGE, SignalCode.L, Frequency.J06), /** Pseudorange QZSS LEX(6) S for Rinex3. */ - C6S(MeasurementType.PSEUDO_RANGE, Frequency.J06), + C6S(MeasurementType.PSEUDO_RANGE, SignalCode.S, Frequency.J06), - /** Pseudorange Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q for Rinex3. */ - C6X(MeasurementType.PSEUDO_RANGE, Frequency.E06, Frequency.J06, Frequency.B03), + /** Pseudorange Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q / GLONASS G2a L2CSI+L2OCp for Rinex3. */ + C6X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.E06, Frequency.J06, Frequency.B03, Frequency.R06), - /** Pseudorange Galileo E6 A+B+C for Rinex3. */ - C6Z(MeasurementType.PSEUDO_RANGE, Frequency.E06), + /** Pseudorange Galileo E6 A+B+C / QZSS L6(D+E) for Rinex3. */ + C6Z(MeasurementType.PSEUDO_RANGE, SignalCode.Z, Frequency.E06, Frequency.J06), /** Pseudorange Galileo E5b I I/NAV OS/CS/SoL / Beidou B2 I for Rinex3. */ - C7I(MeasurementType.PSEUDO_RANGE, Frequency.E07, Frequency.B02), + C7I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.E07, Frequency.B02), /** Pseudorange Galileo Q no data / Beidou B2 Q for Rinex3. */ - C7Q(MeasurementType.PSEUDO_RANGE, Frequency.E07, Frequency.B02), + C7Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.E07, Frequency.B02), /** Pseudorange Galileo E5b I+Q / Beidou B2 I+Q for Rinex3. */ - C7X(MeasurementType.PSEUDO_RANGE, Frequency.E07, Frequency.B02), + C7X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.E07, Frequency.B02), /** Pseudorange Galileo E5(E5a+E5b) I for Rinex3. */ - C8I(MeasurementType.PSEUDO_RANGE, Frequency.E08), + C8I(MeasurementType.PSEUDO_RANGE, SignalCode.I, Frequency.E08), /** Pseudorange Galileo E5(E5a+E5b) Q for Rinex3. */ - C8Q(MeasurementType.PSEUDO_RANGE, Frequency.E08), + C8Q(MeasurementType.PSEUDO_RANGE, SignalCode.Q, Frequency.E08), /** Pseudorange Galileo E5(E5a+E5b) I+Q for Rinex3. */ - C8X(MeasurementType.PSEUDO_RANGE, Frequency.E08), + C8X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.E08), /** Pseudorange IRNSS S A for Rinex3. */ - C9A(MeasurementType.PSEUDO_RANGE, Frequency.I09), + C9A(MeasurementType.PSEUDO_RANGE, SignalCode.A, Frequency.I09), /** Pseudorange IRNSS S B for Rinex3. */ - C9B(MeasurementType.PSEUDO_RANGE, Frequency.I09), + C9B(MeasurementType.PSEUDO_RANGE, SignalCode.B, Frequency.I09), /** Pseudorange IRNSS S C for Rinex3. */ - C9C(MeasurementType.PSEUDO_RANGE, Frequency.I09), + C9C(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.I09), /** Pseudorange IRNSS S B+C for Rinex3. */ - C9X(MeasurementType.PSEUDO_RANGE, Frequency.I09), + C9X(MeasurementType.PSEUDO_RANGE, SignalCode.X, Frequency.I09), /** Pseudorange GPS L1 C/A / GLONASS G1 C/A for Rinex2. */ - CA(MeasurementType.PSEUDO_RANGE, Frequency.G01, Frequency.R01), + CA(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.G01, Frequency.R01), /** Pseudorange GPS L1C for Rinex2. */ - CB(MeasurementType.PSEUDO_RANGE, Frequency.G01), + CB(MeasurementType.PSEUDO_RANGE, SignalCode.L, Frequency.G01), /** Pseudorange GPS L2C for Rinex2. */ - CC(MeasurementType.PSEUDO_RANGE, Frequency.G02), + CC(MeasurementType.PSEUDO_RANGE, SignalCode.L, Frequency.G02), /** Pseudorange GLONASS G2 for Rinex2. */ - CD(MeasurementType.PSEUDO_RANGE, Frequency.R02), + CD(MeasurementType.PSEUDO_RANGE, SignalCode.C, Frequency.R02), /** Doppler Galileo E1 A for Rinex3. */ - D1A(MeasurementType.DOPPLER, Frequency.E01), + D1A(MeasurementType.DOPPLER, SignalCode.A, Frequency.E01), /** Doppler Galileo E1 I/NAV OS/CS/SoL for Rinex3. */ - D1B(MeasurementType.DOPPLER, Frequency.E01), + D1B(MeasurementType.DOPPLER, SignalCode.B, Frequency.E01), /** Doppler GPS L1 C/A / GLONASS G1 C/A / Galileo E1 C / SBAS L1 C/A / QZSS L1 C/A for Rinex3. */ - D1C(MeasurementType.DOPPLER, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), + D1C(MeasurementType.DOPPLER, SignalCode.C, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), /** Doppler Beidou B1 I for Rinex3. */ - D1I(MeasurementType.DOPPLER, Frequency.B01), + D1I(MeasurementType.DOPPLER, SignalCode.I, Frequency.B01), /** Doppler GPS L1 L1C(P) / QZSS L1 L1C(P) for Rinex3. */ - D1L(MeasurementType.DOPPLER, Frequency.G01, Frequency.J01), + D1L(MeasurementType.DOPPLER, SignalCode.L, Frequency.G01, Frequency.J01), /** Doppler GPS L2 M for Rinex3. */ - D1M(MeasurementType.DOPPLER, Frequency.G02), + D1M(MeasurementType.DOPPLER, SignalCode.M, Frequency.G02), /** Doppler GPS L1 codeless for Rinex3. */ - D1N(MeasurementType.DOPPLER, Frequency.G01), + D1N(MeasurementType.DOPPLER, SignalCode.CODELESS, Frequency.G01), /** Doppler GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - D1P(MeasurementType.DOPPLER, Frequency.G02, Frequency.R02), + D1P(MeasurementType.DOPPLER, SignalCode.P, Frequency.G02, Frequency.R02), /** Doppler GPS L1 L1C(D) / QZSS L1 L1C(D) for Rinex3. */ - D1S(MeasurementType.DOPPLER, Frequency.G01, Frequency.J01), + D1S(MeasurementType.DOPPLER, SignalCode.S, Frequency.G01, Frequency.J01), /** Doppler GPS L1 Z-tracking and similar (AS on) for Rinex3. */ - D1W(MeasurementType.DOPPLER, Frequency.G01), + D1W(MeasurementType.DOPPLER, SignalCode.W, Frequency.G01), /** Doppler GPS L1 L1C (D+P) / Galileo E1 B+C / QZSS L1 L1C(D+P) for Rinex3. */ - D1X(MeasurementType.DOPPLER, Frequency.G01, Frequency.E01, Frequency.J01), + D1X(MeasurementType.DOPPLER, SignalCode.X, Frequency.G01, Frequency.E01, Frequency.J01), /** Doppler GPS L1 Y for Rinex3. */ - D1Y(MeasurementType.DOPPLER, Frequency.G01), + D1Y(MeasurementType.DOPPLER, SignalCode.Y, Frequency.G01), /** Doppler Galileo E1 C1Z A+B+C / QZSS L1 L1-SAIF for Rinex3. */ - D1Z(MeasurementType.DOPPLER, Frequency.E01, Frequency.J01), + D1Z(MeasurementType.DOPPLER, SignalCode.Z, Frequency.E01, Frequency.J01), /** Doppler GPS L2 C/A / GLONASS G2 C/A for Rinex3. */ - D2C(MeasurementType.DOPPLER, Frequency.G02, Frequency.R02), + D2C(MeasurementType.DOPPLER, SignalCode.C, Frequency.G02, Frequency.R02), /** Doppler GPS L1(C/A)+(P2-P1) (semi-codeless) for Rinex3. */ - D2D(MeasurementType.DOPPLER, Frequency.G01), + D2D(MeasurementType.DOPPLER, SignalCode.D, Frequency.G02), /** Doppler Beidou B1 I for Rinex3.03. */ - D2I(MeasurementType.DOPPLER, Frequency.B01), + D2I(MeasurementType.DOPPLER, SignalCode.I, Frequency.B01), /** Doppler GPS L2 L2C(L) / QZSS L2 L2C(2) for Rinex3. */ - D2L(MeasurementType.DOPPLER, Frequency.G02, Frequency.J02), + D2L(MeasurementType.DOPPLER, SignalCode.L, Frequency.G02, Frequency.J02), /** Doppler GPS L2 M for Rinex3. */ - D2M(MeasurementType.DOPPLER, Frequency.G02), + D2M(MeasurementType.DOPPLER, SignalCode.M, Frequency.G02), /** Doppler GPS L2 codeless for Rinex3. */ - D2N(MeasurementType.DOPPLER, Frequency.G02), + D2N(MeasurementType.DOPPLER, SignalCode.CODELESS, Frequency.G02), /** Doppler GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - D2P(MeasurementType.DOPPLER, Frequency.G02, Frequency.R02), + D2P(MeasurementType.DOPPLER, SignalCode.P, Frequency.G02, Frequency.R02), /** Doppler Beidou B1 Q for Rinex3.03. */ - D2Q(MeasurementType.DOPPLER, Frequency.B01), + D2Q(MeasurementType.DOPPLER, SignalCode.Q, Frequency.B01), /** Doppler GPS L2 L2C(M) / QZSS L2 L2C(M) for Rinex3. */ - D2S(MeasurementType.DOPPLER, Frequency.G02, Frequency.J02), + D2S(MeasurementType.DOPPLER, SignalCode.S, Frequency.G02, Frequency.J02), /** Doppler GPS L2 Z-tracking and similar (AS on) for Rinex3. */ - D2W(MeasurementType.DOPPLER, Frequency.G02), + D2W(MeasurementType.DOPPLER, SignalCode.W, Frequency.G02), /** Doppler GPS L2 L2C (M+L) / QZSS L2 L2C(M+L) for Rinex3. */ - D2X(MeasurementType.DOPPLER, Frequency.G02, Frequency.J02), + D2X(MeasurementType.DOPPLER, SignalCode.X, Frequency.G02, Frequency.J02), /** Doppler GPS L2 Y for Rinex3. */ - D2Y(MeasurementType.DOPPLER, Frequency.G02), + D2Y(MeasurementType.DOPPLER, SignalCode.Y, Frequency.G02), /** Doppler GLONASS G3 I for Rinex3. */ - D3I(MeasurementType.DOPPLER, Frequency.R03), + D3I(MeasurementType.DOPPLER, SignalCode.I, Frequency.R03), /** Doppler GLONASS G3 Q for Rinex3. */ - D3Q(MeasurementType.DOPPLER, Frequency.R03), + D3Q(MeasurementType.DOPPLER, SignalCode.Q, Frequency.R03), /** Doppler GLONASS G3 I+Q for Rinex3. */ - D3X(MeasurementType.DOPPLER, Frequency.R03), + D3X(MeasurementType.DOPPLER, SignalCode.X, Frequency.R03), + + /** Doppler GLONASS G1a L1OCd for Rinex3. */ + D4A(MeasurementType.DOPPLER, SignalCode.A, Frequency.R04), + + /** Doppler GLONASS G1a L1OCp for Rinex3. */ + D4B(MeasurementType.DOPPLER, SignalCode.B, Frequency.R04), + + /** Doppler GLONASS G1a L1OCd+L1OCd for Rinex3. */ + D4X(MeasurementType.DOPPLER, SignalCode.X, Frequency.R04), /** Doppler IRNSS L5 A for Rinex3. */ - D5A(MeasurementType.DOPPLER, Frequency.I05), + D5A(MeasurementType.DOPPLER, SignalCode.A, Frequency.I05), /** Doppler IRNSS L5 B for Rinex3. */ - D5B(MeasurementType.DOPPLER, Frequency.I05), + D5B(MeasurementType.DOPPLER, SignalCode.B, Frequency.I05), /** Doppler IRNSS L5 C for Rinex3. */ - D5C(MeasurementType.DOPPLER, Frequency.I05), + D5C(MeasurementType.DOPPLER, SignalCode.C, Frequency.I05), + + /** Doppler QZSS L5 D for Rinex3. */ + D5D(MeasurementType.DOPPLER, SignalCode.D, Frequency.J05), /** Doppler GPS L5 I/ Galileo E5a F/NAV OS / SBAS L5 I / QZSS L5 I for Rinex3. */ - D5I(MeasurementType.DOPPLER, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + D5I(MeasurementType.DOPPLER, SignalCode.I, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + + /** Doppler QZSS L5 P for Rinex3. */ + D5P(MeasurementType.DOPPLER, SignalCode.P, Frequency.J05), /** Doppler GPS L5 Q/ Galileo E5a Q / SBAS L5 Q / QZSS L5 Q for Rinex3. */ - D5Q(MeasurementType.DOPPLER, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + D5Q(MeasurementType.DOPPLER, SignalCode.Q, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), /** Doppler GPS L5 I+Q/ Galileo E5a I+Q / SBAS L5 I+Q / QZSS L5 I+Q / IRNSS L5 B+C for Rinex3. */ - D5X(MeasurementType.DOPPLER, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), + D5X(MeasurementType.DOPPLER, SignalCode.X, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), - /** Doppler Galileo E6 A PRS for Rinex3. */ - D6A(MeasurementType.DOPPLER, Frequency.E06), + /** Doppler QZSS L5 D+P for Rinex3. */ + D5Z(MeasurementType.DOPPLER, SignalCode.Z, Frequency.J05), - /** Doppler Galileo E6 B C/NAV CS for Rinex3. */ - D6B(MeasurementType.DOPPLER, Frequency.E06), + /** Doppler Galileo E6 A PRS / GLONASS L2CSI for Rinex3. */ + D6A(MeasurementType.DOPPLER, SignalCode.A, Frequency.E06, Frequency.R06), + + /** Doppler Galileo E6 B C/NAV CS / GLONASS L2OCp for Rinex3. */ + D6B(MeasurementType.DOPPLER, SignalCode.B, Frequency.E06, Frequency.R06), /** Doppler Galileo E6 C no data for Rinex3. */ - D6C(MeasurementType.DOPPLER, Frequency.E06), + D6C(MeasurementType.DOPPLER, SignalCode.C, Frequency.E06), + + /** Doppler QZSS L6E for Rinex3. */ + D6E(MeasurementType.DOPPLER, SignalCode.E, Frequency.J06), /** Doppler Beidou B3 I for Rinex3. */ - D6I(MeasurementType.DOPPLER, Frequency.B03), + D6I(MeasurementType.DOPPLER, SignalCode.I, Frequency.B03), /** Doppler Beidou B3 Q for Rinex3. */ - D6Q(MeasurementType.DOPPLER, Frequency.B03), + D6Q(MeasurementType.DOPPLER, SignalCode.Q, Frequency.B03), /** Doppler QZSS LEX(6) L for Rinex3. */ - D6L(MeasurementType.DOPPLER, Frequency.J06), + D6L(MeasurementType.DOPPLER, SignalCode.L, Frequency.J06), /** Doppler QZSS LEX(6) S for Rinex3. */ - D6S(MeasurementType.DOPPLER, Frequency.J06), + D6S(MeasurementType.DOPPLER, SignalCode.S, Frequency.J06), - /** Doppler Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q for Rinex3. */ - D6X(MeasurementType.DOPPLER, Frequency.E06, Frequency.J06, Frequency.B03), + /** Doppler Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q / GLONASS G2a L2CSI+L2OCp for Rinex3. */ + D6X(MeasurementType.DOPPLER, SignalCode.X, Frequency.E06, Frequency.J06, Frequency.B03, Frequency.R06), - /** Doppler Galileo E6 A+B+C for Rinex3. */ - D6Z(MeasurementType.DOPPLER, Frequency.E06), + /** Doppler Galileo E6 A+B+C / QZSS L6(D+E) for Rinex3. */ + D6Z(MeasurementType.DOPPLER, SignalCode.Z, Frequency.E06, Frequency.J06), /** Doppler Galileo E5b I I/NAV OS/CS/SoL / Beidou B2 I for Rinex3. */ - D7I(MeasurementType.DOPPLER, Frequency.E07, Frequency.B02), + D7I(MeasurementType.DOPPLER, SignalCode.I, Frequency.E07, Frequency.B02), /** Doppler Galileo Q no data / Beidou B2 Q for Rinex3. */ - D7Q(MeasurementType.DOPPLER, Frequency.E07, Frequency.B02), + D7Q(MeasurementType.DOPPLER, SignalCode.Q, Frequency.E07, Frequency.B02), /** Doppler Galileo E5b I+Q / Beidou B2 I+Q for Rinex3. */ - D7X(MeasurementType.DOPPLER, Frequency.E07, Frequency.B02), + D7X(MeasurementType.DOPPLER, SignalCode.X, Frequency.E07, Frequency.B02), /** Doppler Galileo E5(E5a+E5b) I for Rinex3. */ - D8I(MeasurementType.DOPPLER, Frequency.E08), + D8I(MeasurementType.DOPPLER, SignalCode.I, Frequency.E08), /** Doppler Galileo E5(E5a+E5b) Q for Rinex3. */ - D8Q(MeasurementType.DOPPLER, Frequency.E08), + D8Q(MeasurementType.DOPPLER, SignalCode.Q, Frequency.E08), /** Doppler Galileo E5(E5a+E5b) I+Q for Rinex3. */ - D8X(MeasurementType.DOPPLER, Frequency.E08), + D8X(MeasurementType.DOPPLER, SignalCode.X, Frequency.E08), /** Doppler IRNSS S A for Rinex3. */ - D9A(MeasurementType.DOPPLER, Frequency.I09), + D9A(MeasurementType.DOPPLER, SignalCode.A, Frequency.I09), /** Doppler IRNSS S B for Rinex3. */ - D9B(MeasurementType.DOPPLER, Frequency.I09), + D9B(MeasurementType.DOPPLER, SignalCode.B, Frequency.I09), /** Doppler IRNSS S C for Rinex3. */ - D9C(MeasurementType.DOPPLER, Frequency.I09), + D9C(MeasurementType.DOPPLER, SignalCode.C, Frequency.I09), /** Doppler IRNSS S B+C for Rinex3. */ - D9X(MeasurementType.DOPPLER, Frequency.I09), + D9X(MeasurementType.DOPPLER, SignalCode.X, Frequency.I09), /** Doppler GPS L1 C/A / GLONASS G1 C/A for Rinex2. */ - DA(MeasurementType.DOPPLER, Frequency.G01, Frequency.R01), + DA(MeasurementType.DOPPLER, SignalCode.C, Frequency.G01, Frequency.R01), /** Doppler GPS L1C for Rinex2. */ - DB(MeasurementType.DOPPLER, Frequency.G01), + DB(MeasurementType.DOPPLER, SignalCode.L, Frequency.G01), /** Doppler GPS L2C for Rinex2. */ - DC(MeasurementType.DOPPLER, Frequency.G02), + DC(MeasurementType.DOPPLER, SignalCode.L, Frequency.G02), /** Doppler GLONASS G2 for Rinex2. */ - DD(MeasurementType.DOPPLER, Frequency.R02), + DD(MeasurementType.DOPPLER, SignalCode.C, Frequency.R02), /** Carrier-phase Galileo E1 A for Rinex3. */ - L1A(MeasurementType.CARRIER_PHASE, Frequency.E01), + L1A(MeasurementType.CARRIER_PHASE, SignalCode.A, Frequency.E01), /** Carrier-phase Galileo E1 I/NAV OS/CS/SoL for Rinex3. */ - L1B(MeasurementType.CARRIER_PHASE, Frequency.E01), + L1B(MeasurementType.CARRIER_PHASE, SignalCode.B, Frequency.E01), /** Carrier-phase GPS L1 C/A / GLONASS G1 C/A / Galileo E1 C / SBAS L1 C/A / QZSS L1 C/A for Rinex3. */ - L1C(MeasurementType.CARRIER_PHASE, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), + L1C(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), /** Carrier-phase Beidou B1 I for Rinex3. */ - L1I(MeasurementType.CARRIER_PHASE, Frequency.B01), + L1I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.B01), /** Carrier-phase GPS L1 L1C(P) / QZSS L1 L1C(P) for Rinex3. */ - L1L(MeasurementType.CARRIER_PHASE, Frequency.G01, Frequency.J01), + L1L(MeasurementType.CARRIER_PHASE, SignalCode.L, Frequency.G01, Frequency.J01), /** Carrier-phase GPS L2 M for Rinex3. */ - L1M(MeasurementType.CARRIER_PHASE, Frequency.G02), + L1M(MeasurementType.CARRIER_PHASE, SignalCode.M, Frequency.G02), /** Carrier-phase GPS L1 codeless for Rinex3. */ - L1N(MeasurementType.CARRIER_PHASE, Frequency.G01), + L1N(MeasurementType.CARRIER_PHASE, SignalCode.CODELESS, Frequency.G01), /** Carrier-phase GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - L1P(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.R02), + L1P(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.G02, Frequency.R02), /** Carrier-phase GPS L1 L1C(D) / QZSS L1 L1C(D) for Rinex3. */ - L1S(MeasurementType.CARRIER_PHASE, Frequency.G01, Frequency.J01), + L1S(MeasurementType.CARRIER_PHASE, SignalCode.S, Frequency.G01, Frequency.J01), /** Carrier-phase GPS L1 Z-tracking and similar (AS on) for Rinex3. */ - L1W(MeasurementType.CARRIER_PHASE, Frequency.G01), + L1W(MeasurementType.CARRIER_PHASE, SignalCode.W, Frequency.G01), /** Carrier-phase GPS L1 L1C (D+P) / Galileo E1 B+C / QZSS L1 L1C(D+P) for Rinex3. */ - L1X(MeasurementType.CARRIER_PHASE, Frequency.G01, Frequency.E01, Frequency.J01), + L1X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.G01, Frequency.E01, Frequency.J01), /** Carrier-phase GPS L1 Y for Rinex3. */ - L1Y(MeasurementType.CARRIER_PHASE, Frequency.G01), + L1Y(MeasurementType.CARRIER_PHASE, SignalCode.Y, Frequency.G01), /** Carrier-phase Galileo E1 C1Z A+B+C / QZSS L1 L1-SAIF for Rinex3. */ - L1Z(MeasurementType.CARRIER_PHASE, Frequency.E01, Frequency.J01), + L1Z(MeasurementType.CARRIER_PHASE, SignalCode.Z, Frequency.E01, Frequency.J01), /** Carrier-phase GPS L2 C/A / GLONASS G2 C/A for Rinex3. */ - L2C(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.R02), + L2C(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.G02, Frequency.R02), /** Carrier-phase GPS L1(C/A)+(P2-P1) (semi-codeless) for Rinex3. */ - L2D(MeasurementType.CARRIER_PHASE, Frequency.G01), + L2D(MeasurementType.CARRIER_PHASE, SignalCode.D, Frequency.G02), /** Carrier-phase Beidou B1 I for Rinex3.03. */ - L2I(MeasurementType.CARRIER_PHASE, Frequency.B01), + L2I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.B01), /** Carrier-phase GPS L2 L2C(L) / QZSS L2 L2C(2) for Rinex3. */ - L2L(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.J02), + L2L(MeasurementType.CARRIER_PHASE, SignalCode.L, Frequency.G02, Frequency.J02), /** Carrier-phase GPS L2 M for Rinex3. */ - L2M(MeasurementType.CARRIER_PHASE, Frequency.G02), + L2M(MeasurementType.CARRIER_PHASE, SignalCode.M, Frequency.G02), /** Carrier-phase GPS L2 codeless for Rinex3. */ - L2N(MeasurementType.CARRIER_PHASE, Frequency.G02), + L2N(MeasurementType.CARRIER_PHASE, SignalCode.CODELESS, Frequency.G02), /** Carrier-phase GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - L2P(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.R02), + L2P(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.G02, Frequency.R02), /** Carrier-phase Beidou B1 Q for Rinex3.03. */ - L2Q(MeasurementType.CARRIER_PHASE, Frequency.B01), + L2Q(MeasurementType.CARRIER_PHASE, SignalCode.Q, Frequency.B01), /** Carrier-phase GPS L2 L2C(M) / QZSS L2 L2C(M) for Rinex3. */ - L2S(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.J02), + L2S(MeasurementType.CARRIER_PHASE, SignalCode.S, Frequency.G02, Frequency.J02), /** Carrier-phase GPS L2 Z-tracking and similar (AS on) for Rinex3. */ - L2W(MeasurementType.CARRIER_PHASE, Frequency.G02), + L2W(MeasurementType.CARRIER_PHASE, SignalCode.W, Frequency.G02), /** Carrier-phase GPS L2 L2C (M+L) / QZSS L2 L2C(M+L) for Rinex3. */ - L2X(MeasurementType.CARRIER_PHASE, Frequency.G02, Frequency.J02), + L2X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.G02, Frequency.J02), /** Carrier-phase GPS L2 Y for Rinex3. */ - L2Y(MeasurementType.CARRIER_PHASE, Frequency.G02), + L2Y(MeasurementType.CARRIER_PHASE, SignalCode.Y, Frequency.G02), /** Carrier-phase GLONASS G3 I for Rinex3. */ - L3I(MeasurementType.CARRIER_PHASE, Frequency.R03), + L3I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.R03), /** Carrier-phase GLONASS G3 Q for Rinex3. */ - L3Q(MeasurementType.CARRIER_PHASE, Frequency.R03), + L3Q(MeasurementType.CARRIER_PHASE, SignalCode.Q, Frequency.R03), /** Carrier-phase GLONASS G3 I+Q for Rinex3. */ - L3X(MeasurementType.CARRIER_PHASE, Frequency.R03), + L3X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.R03), + + /** Carrier-phase GLONASS G1a L1OCd for Rinex3. */ + L4A(MeasurementType.CARRIER_PHASE, SignalCode.A, Frequency.R04), + + /** Carrier-phase GLONASS G1a L1OCp for Rinex3. */ + L4B(MeasurementType.CARRIER_PHASE, SignalCode.B, Frequency.R04), + + /** Carrier-phase GLONASS G1a L1OCd+L1OCd for Rinex3. */ + L4X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.R04), /** Carrier-phase IRNSS L5 A for Rinex3. */ - L5A(MeasurementType.CARRIER_PHASE, Frequency.I05), + L5A(MeasurementType.CARRIER_PHASE, SignalCode.A, Frequency.I05), /** Carrier-phase IRNSS L5 B for Rinex3. */ - L5B(MeasurementType.CARRIER_PHASE, Frequency.I05), + L5B(MeasurementType.CARRIER_PHASE, SignalCode.B, Frequency.I05), /** Carrier-phase IRNSS L5 C for Rinex3. */ - L5C(MeasurementType.CARRIER_PHASE, Frequency.I05), + L5C(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.I05), + + /** Carrier-phase QZSS L5 D for Rinex3. */ + L5D(MeasurementType.CARRIER_PHASE, SignalCode.D, Frequency.J05), /** Carrier-phase GPS L5 I/ Galileo E5a F/NAV OS / SBAS L5 I / QZSS L5 I for Rinex3. */ - L5I(MeasurementType.CARRIER_PHASE, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + L5I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + + /** Carrier-phase QZSS L5 P for Rinex3. */ + L5P(MeasurementType.CARRIER_PHASE, SignalCode.P, Frequency.J05), /** Carrier-phase GPS L5 Q/ Galileo E5a Q / SBAS L5 Q / QZSS L5 Q for Rinex3. */ - L5Q(MeasurementType.CARRIER_PHASE, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + L5Q(MeasurementType.CARRIER_PHASE, SignalCode.Q, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), /** Carrier-phase GPS L5 I+Q/ Galileo E5a I+Q / SBAS L5 I+Q / QZSS L5 I+Q / IRNSS L5 B+C for Rinex3. */ - L5X(MeasurementType.CARRIER_PHASE, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), + L5X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), + + /** Carrier-phase QZSS L5 D+P for Rinex3. */ + L5Z(MeasurementType.CARRIER_PHASE, SignalCode.Z, Frequency.J05), - /** Carrier-phase Galileo E6 A PRS for Rinex3. */ - L6A(MeasurementType.CARRIER_PHASE, Frequency.E06), + /** Carrier-phase Galileo E6 A PRS / GLONASS G2a L2CSI for Rinex3. */ + L6A(MeasurementType.CARRIER_PHASE, SignalCode.A, Frequency.E06, Frequency.R06), - /** Carrier-phase Galileo E6 B C/NAV CS for Rinex3. */ - L6B(MeasurementType.CARRIER_PHASE, Frequency.E06), + /** Carrier-phase Galileo E6 B C/NAV CS / GLONASS G2a L2OCp for Rinex3. */ + L6B(MeasurementType.CARRIER_PHASE, SignalCode.B, Frequency.E06, Frequency.R06), /** Carrier-phase Galileo E6 C no data for Rinex3. */ - L6C(MeasurementType.CARRIER_PHASE, Frequency.E06), + L6C(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.E06), + + /** Carrier-phase QZSS L6E for Rinex3. */ + L6E(MeasurementType.CARRIER_PHASE, SignalCode.E, Frequency.J06), /** Carrier-phase Beidou B3 I for Rinex3. */ - L6I(MeasurementType.CARRIER_PHASE, Frequency.B03), + L6I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.B03), /** Carrier-phase Beidou B3 Q for Rinex3. */ - L6Q(MeasurementType.CARRIER_PHASE, Frequency.B03), + L6Q(MeasurementType.CARRIER_PHASE, SignalCode.Q, Frequency.B03), /** Carrier-phase QZSS LEX(6) L for Rinex3. */ - L6L(MeasurementType.CARRIER_PHASE, Frequency.J06), + L6L(MeasurementType.CARRIER_PHASE, SignalCode.L, Frequency.J06), /** Carrier-phase QZSS LEX(6) S for Rinex3. */ - L6S(MeasurementType.CARRIER_PHASE, Frequency.J06), + L6S(MeasurementType.CARRIER_PHASE, SignalCode.S, Frequency.J06), - /** Carrier-phase Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q for Rinex3. */ - L6X(MeasurementType.CARRIER_PHASE, Frequency.E06, Frequency.J06, Frequency.B03), + /** Carrier-phase Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q / GLONASS G2a L2CSI+L2OCp for Rinex3. */ + L6X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.E06, Frequency.J06, Frequency.B03, Frequency.R06), - /** Carrier-phase Galileo E6 A+B+C for Rinex3. */ - L6Z(MeasurementType.CARRIER_PHASE, Frequency.E06), + /** Carrier-phase Galileo E6 A+B+C / QZSS L6(D+E) for Rinex3. */ + L6Z(MeasurementType.CARRIER_PHASE, SignalCode.Z, Frequency.E06, Frequency.J06), /** Carrier-phase Galileo E5b I I/NAV OS/CS/SoL / Beidou B2 I for Rinex3. */ - L7I(MeasurementType.CARRIER_PHASE, Frequency.E07, Frequency.B02), + L7I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.E07, Frequency.B02), /** Carrier-phase Galileo Q no data / Beidou B2 Q for Rinex3. */ - L7Q(MeasurementType.CARRIER_PHASE, Frequency.E07, Frequency.B02), + L7Q(MeasurementType.CARRIER_PHASE, SignalCode.Q, Frequency.E07, Frequency.B02), /** Carrier-phase Galileo E5b I+Q / Beidou B2 I+Q for Rinex3. */ - L7X(MeasurementType.CARRIER_PHASE, Frequency.E07, Frequency.B02), + L7X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.E07, Frequency.B02), /** Carrier-phase Galileo E5(E5a+E5b) I for Rinex3. */ - L8I(MeasurementType.CARRIER_PHASE, Frequency.E08), + L8I(MeasurementType.CARRIER_PHASE, SignalCode.I, Frequency.E08), /** Carrier-phase Galileo E5(E5a+E5b) Q for Rinex3. */ - L8Q(MeasurementType.CARRIER_PHASE, Frequency.E08), + L8Q(MeasurementType.CARRIER_PHASE, SignalCode.Q, Frequency.E08), /** Carrier-phase Galileo E5(E5a+E5b) I+Q for Rinex3. */ - L8X(MeasurementType.CARRIER_PHASE, Frequency.E08), + L8X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.E08), /** Carrier-phase IRNSS S A for Rinex3. */ - L9A(MeasurementType.CARRIER_PHASE, Frequency.I09), + L9A(MeasurementType.CARRIER_PHASE, SignalCode.A, Frequency.I09), /** Carrier-phase IRNSS S B for Rinex3. */ - L9B(MeasurementType.CARRIER_PHASE, Frequency.I09), + L9B(MeasurementType.CARRIER_PHASE, SignalCode.B, Frequency.I09), /** Carrier-phase IRNSS S C for Rinex3. */ - L9C(MeasurementType.CARRIER_PHASE, Frequency.I09), + L9C(MeasurementType.CARRIER_PHASE, SignalCode.C, Frequency.I09), /** Carrier-phase IRNSS S B+C for Rinex3. */ - L9X(MeasurementType.CARRIER_PHASE, Frequency.I09), + L9X(MeasurementType.CARRIER_PHASE, SignalCode.X, Frequency.I09), /** Signal-strength Galileo E1 A for Rinex3. */ - S1A(MeasurementType.SIGNAL_STRENGTH, Frequency.E01), + S1A(MeasurementType.SIGNAL_STRENGTH, SignalCode.A, Frequency.E01), /** Signal-strength Galileo E1 I/NAV OS/CS/SoL for Rinex3. */ - S1B(MeasurementType.SIGNAL_STRENGTH, Frequency.E01), + S1B(MeasurementType.SIGNAL_STRENGTH, SignalCode.B, Frequency.E01), /** Signal-strength GPS L1 C/A / GLONASS G1 C/A / Galileo E1 C / SBAS L1 C/A / QZSS L1 C/A for Rinex3. */ - S1C(MeasurementType.SIGNAL_STRENGTH, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), + S1C(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.G01, Frequency.R01, Frequency.E01, Frequency.S01, Frequency.J01), /** Signal-strength Beidou B1 I for Rinex3. */ - S1I(MeasurementType.SIGNAL_STRENGTH, Frequency.B01), + S1I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.B01), /** Signal-strength GPS L1 L1C(P) / QZSS L1 L1C(P) for Rinex3. */ - S1L(MeasurementType.SIGNAL_STRENGTH, Frequency.G01, Frequency.J01), + S1L(MeasurementType.SIGNAL_STRENGTH, SignalCode.L, Frequency.G01, Frequency.J01), /** Signal-strength GPS L2 M for Rinex3. */ - S1M(MeasurementType.SIGNAL_STRENGTH, Frequency.G02), + S1M(MeasurementType.SIGNAL_STRENGTH, SignalCode.M, Frequency.G02), /** Signal-strength GPS L1 codeless for Rinex3. */ - S1N(MeasurementType.SIGNAL_STRENGTH, Frequency.G01), + S1N(MeasurementType.SIGNAL_STRENGTH, SignalCode.CODELESS, Frequency.G01), /** Signal-strength GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - S1P(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.R02), + S1P(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.G02, Frequency.R02), /** Signal-strength GPS L1 L1C(D) / QZSS L1 L1C(D) for Rinex3. */ - S1S(MeasurementType.SIGNAL_STRENGTH, Frequency.G01, Frequency.J01), + S1S(MeasurementType.SIGNAL_STRENGTH, SignalCode.S, Frequency.G01, Frequency.J01), /** Signal-strength GPS L1 Z-tracking and similar (AS on) for Rinex3. */ - S1W(MeasurementType.SIGNAL_STRENGTH, Frequency.G01), + S1W(MeasurementType.SIGNAL_STRENGTH, SignalCode.W, Frequency.G01), /** Signal-strength GPS L1 L1C (D+P) / Galileo E1 B+C / QZSS L1 L1C(D+P) for Rinex3. */ - S1X(MeasurementType.SIGNAL_STRENGTH, Frequency.G01, Frequency.E01, Frequency.J01), + S1X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.G01, Frequency.E01, Frequency.J01), /** Signal-strength GPS L1 Y for Rinex3. */ - S1Y(MeasurementType.SIGNAL_STRENGTH, Frequency.G01), + S1Y(MeasurementType.SIGNAL_STRENGTH, SignalCode.Y, Frequency.G01), /** Signal-strength Galileo E1 C1Z A+B+C / QZSS L1 L1-SAIF for Rinex3. */ - S1Z(MeasurementType.SIGNAL_STRENGTH, Frequency.E01, Frequency.J01), + S1Z(MeasurementType.SIGNAL_STRENGTH, SignalCode.Z, Frequency.E01, Frequency.J01), /** Signal-strength GPS L2 C/A / GLONASS G2 C/A for Rinex3. */ - S2C(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.R02), + S2C(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.G02, Frequency.R02), /** Signal-strength GPS L1(C/A)+(P2-P1) (semi-codeless) for Rinex3. */ - S2D(MeasurementType.SIGNAL_STRENGTH, Frequency.G01), + S2D(MeasurementType.SIGNAL_STRENGTH, SignalCode.D, Frequency.G02), /** Signal-strength Beidou B1 I for Rinex3.03. */ - S2I(MeasurementType.SIGNAL_STRENGTH, Frequency.B01), + S2I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.B01), /** Signal-strength GPS L2 L2C(L) / QZSS L2 L2C(2) for Rinex3. */ - S2L(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.J02), + S2L(MeasurementType.SIGNAL_STRENGTH, SignalCode.L, Frequency.G02, Frequency.J02), /** Signal-strength GPS L2 M for Rinex3. */ - S2M(MeasurementType.SIGNAL_STRENGTH, Frequency.G02), + S2M(MeasurementType.SIGNAL_STRENGTH, SignalCode.M, Frequency.G02), /** Signal-strength GPS L2 codeless for Rinex3. */ - S2N(MeasurementType.SIGNAL_STRENGTH, Frequency.G02), + S2N(MeasurementType.SIGNAL_STRENGTH, SignalCode.CODELESS, Frequency.G02), /** Signal-strength GPS L2 P(AS off) / GLONASS G2 P for Rinex3. */ - S2P(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.R02), + S2P(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.G02, Frequency.R02), /** Signal-strength Beidou B1 Q for Rinex3.03. */ - S2Q(MeasurementType.SIGNAL_STRENGTH, Frequency.B01), + S2Q(MeasurementType.SIGNAL_STRENGTH, SignalCode.Q, Frequency.B01), /** Signal-strength GPS L2 L2C(M) / QZSS L2 L2C(M) for Rinex3. */ - S2S(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.J02), + S2S(MeasurementType.SIGNAL_STRENGTH, SignalCode.S, Frequency.G02, Frequency.J02), /** Signal-strength GPS L2 Z-tracking and similar (AS on) for Rinex3. */ - S2W(MeasurementType.SIGNAL_STRENGTH, Frequency.G02), + S2W(MeasurementType.SIGNAL_STRENGTH, SignalCode.W, Frequency.G02), /** Signal-strength GPS L2 L2C (M+L) / QZSS L2 L2C(M+L) for Rinex3. */ - S2X(MeasurementType.SIGNAL_STRENGTH, Frequency.G02, Frequency.J02), + S2X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.G02, Frequency.J02), /** Signal-strength GPS L2 Y for Rinex3. */ - S2Y(MeasurementType.SIGNAL_STRENGTH, Frequency.G02), + S2Y(MeasurementType.SIGNAL_STRENGTH, SignalCode.Y, Frequency.G02), /** Signal-strength GLONASS G3 I for Rinex3. */ - S3I(MeasurementType.SIGNAL_STRENGTH, Frequency.R03), + S3I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.R03), /** Signal-strength GLONASS G3 Q for Rinex3. */ - S3Q(MeasurementType.SIGNAL_STRENGTH, Frequency.R03), + S3Q(MeasurementType.SIGNAL_STRENGTH, SignalCode.Q, Frequency.R03), /** Signal-strength GLONASS G3 I+Q for Rinex3. */ - S3X(MeasurementType.SIGNAL_STRENGTH, Frequency.R03), + S3X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.R03), + + /** Signal-strength GLONASS G1a L1OCd for Rinex3. */ + S4A(MeasurementType.SIGNAL_STRENGTH, SignalCode.A, Frequency.R04), + + /** Signal-strength GLONASS G1a L1OCp for Rinex3. */ + S4B(MeasurementType.SIGNAL_STRENGTH, SignalCode.B, Frequency.R04), + + /** Signal-strength GLONASS G1a L1OCd+L1OCd for Rinex3. */ + S4X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.R04), /** Signal-strength IRNSS L5 A for Rinex3. */ - S5A(MeasurementType.SIGNAL_STRENGTH, Frequency.I05), + S5A(MeasurementType.SIGNAL_STRENGTH, SignalCode.A, Frequency.I05), /** Signal-strength IRNSS L5 B for Rinex3. */ - S5B(MeasurementType.SIGNAL_STRENGTH, Frequency.I05), + S5B(MeasurementType.SIGNAL_STRENGTH, SignalCode.B, Frequency.I05), /** Signal-strength IRNSS L5 C for Rinex3. */ - S5C(MeasurementType.SIGNAL_STRENGTH, Frequency.I05), + S5C(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.I05), + + /** Signal-strength QZSS L5 D for Rinex3. */ + S5D(MeasurementType.SIGNAL_STRENGTH, SignalCode.D, Frequency.J05), /** Signal-strength GPS L5 I/ Galileo E5a F/NAV OS / SBAS L5 I / QZSS L5 I for Rinex3. */ - S5I(MeasurementType.SIGNAL_STRENGTH, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + S5I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + + /** Signal-strength QZSS L5 P for Rinex3. */ + S5P(MeasurementType.SIGNAL_STRENGTH, SignalCode.P, Frequency.J05), /** Signal-strength GPS L5 Q/ Galileo E5a Q / SBAS L5 Q / QZSS L5 Q for Rinex3. */ - S5Q(MeasurementType.SIGNAL_STRENGTH, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), + S5Q(MeasurementType.SIGNAL_STRENGTH, SignalCode.Q, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05), /** Signal-strength GPS L5 I+Q/ Galileo E5a I+Q / SBAS L5 I+Q / QZSS L5 I+Q / IRNSS L5 B+C for Rinex3. */ - S5X(MeasurementType.SIGNAL_STRENGTH, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), + S5X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.G05, Frequency.E05, Frequency.S05, Frequency.J05, Frequency.I05), - /** Signal-strength Galileo E6 A PRS for Rinex3. */ - S6A(MeasurementType.SIGNAL_STRENGTH, Frequency.E06), + /** Signal-strength QZSS L5 D+P for Rinex3. */ + S5Z(MeasurementType.SIGNAL_STRENGTH, SignalCode.Z, Frequency.J05), - /** Signal-strength Galileo E6 B C/NAV CS for Rinex3. */ - S6B(MeasurementType.SIGNAL_STRENGTH, Frequency.E06), + /** Signal-strength Galileo E6 A PRS / GLONASS G2a L2CSI for Rinex3. */ + S6A(MeasurementType.SIGNAL_STRENGTH, SignalCode.A, Frequency.E06, Frequency.R06), + + /** Signal-strength Galileo E6 B C/NAV CS / GLONASS G2a L2OCp for Rinex3. */ + S6B(MeasurementType.SIGNAL_STRENGTH, SignalCode.B, Frequency.E06, Frequency.R06), /** Signal-strength Galileo E6 C no data for Rinex3. */ - S6C(MeasurementType.SIGNAL_STRENGTH, Frequency.E06), + S6C(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.E06), + + /** Signal-strength QZSS L6E for Rinex3. */ + S6E(MeasurementType.SIGNAL_STRENGTH, SignalCode.E, Frequency.J06), /** Signal-strength Beidou B3 I for Rinex3. */ - S6I(MeasurementType.SIGNAL_STRENGTH, Frequency.B03), + S6I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.B03), /** Signal-strength Beidou B3 Q for Rinex3. */ - S6Q(MeasurementType.SIGNAL_STRENGTH, Frequency.B03), + S6Q(MeasurementType.SIGNAL_STRENGTH, SignalCode.Q, Frequency.B03), /** Signal-strength QZSS LEX(6) L for Rinex3. */ - S6L(MeasurementType.SIGNAL_STRENGTH, Frequency.J06), + S6L(MeasurementType.SIGNAL_STRENGTH, SignalCode.L, Frequency.J06), /** Signal-strength QZSS LEX(6) S for Rinex3. */ - S6S(MeasurementType.SIGNAL_STRENGTH, Frequency.J06), + S6S(MeasurementType.SIGNAL_STRENGTH, SignalCode.S, Frequency.J06), - /** Signal-strength Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q for Rinex3. */ - S6X(MeasurementType.SIGNAL_STRENGTH, Frequency.E06, Frequency.J06, Frequency.B03), + /** Signal-strength Galileo E6 B+C / QZSS LEX(6) S+L / Beidou B3 I+Q / GLONASS G2a L2CSI+L2OCp for Rinex3. */ + S6X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.E06, Frequency.J06, Frequency.B03, Frequency.R06), - /** Signal-strength Galileo E6 A+B+C for Rinex3. */ - S6Z(MeasurementType.SIGNAL_STRENGTH, Frequency.E06), + /** Signal-strength Galileo E6 A+B+C / QZSS L6(D+E) for Rinex3. */ + S6Z(MeasurementType.SIGNAL_STRENGTH, SignalCode.Z, Frequency.E06, Frequency.J06), /** Signal-strength Galileo E5b I I/NAV OS/CS/SoL / Beidou B2 I for Rinex3. */ - S7I(MeasurementType.SIGNAL_STRENGTH, Frequency.E07, Frequency.B02), + S7I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.E07, Frequency.B02), /** Signal-strength Galileo Q no data / Beidou B2 Q for Rinex3. */ - S7Q(MeasurementType.SIGNAL_STRENGTH, Frequency.E07, Frequency.B02), + S7Q(MeasurementType.SIGNAL_STRENGTH, SignalCode.Q, Frequency.E07, Frequency.B02), /** Signal-strength Galileo E5b I+Q / Beidou B2 I+Q for Rinex3. */ - S7X(MeasurementType.SIGNAL_STRENGTH, Frequency.E07, Frequency.B02), + S7X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.E07, Frequency.B02), /** Signal-strength Galileo E5(E5a+E5b) I for Rinex3. */ - S8I(MeasurementType.SIGNAL_STRENGTH, Frequency.E08), + S8I(MeasurementType.SIGNAL_STRENGTH, SignalCode.I, Frequency.E08), /** Signal-strength Galileo E5(E5a+E5b) Q for Rinex3. */ - S8Q(MeasurementType.SIGNAL_STRENGTH, Frequency.E08), + S8Q(MeasurementType.SIGNAL_STRENGTH, SignalCode.Q, Frequency.E08), /** Signal-strength Galileo E5(E5a+E5b) I+Q for Rinex3. */ - S8X(MeasurementType.SIGNAL_STRENGTH, Frequency.E08), + S8X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.E08), /** Signal-strength IRNSS S A for Rinex3. */ - S9A(MeasurementType.SIGNAL_STRENGTH, Frequency.I09), + S9A(MeasurementType.SIGNAL_STRENGTH, SignalCode.A, Frequency.I09), /** Signal-strength IRNSS S B for Rinex3. */ - S9B(MeasurementType.SIGNAL_STRENGTH, Frequency.I09), + S9B(MeasurementType.SIGNAL_STRENGTH, SignalCode.B, Frequency.I09), /** Signal-strength IRNSS S C for Rinex3. */ - S9C(MeasurementType.SIGNAL_STRENGTH, Frequency.I09), + S9C(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.I09), /** Signal-strength IRNSS S B+C for Rinex3. */ - S9X(MeasurementType.SIGNAL_STRENGTH, Frequency.I09), + S9X(MeasurementType.SIGNAL_STRENGTH, SignalCode.X, Frequency.I09), /** Signal-strength GPS L1 C/A / GLONASS G1 C/A for Rinex2. */ - SA(MeasurementType.SIGNAL_STRENGTH, Frequency.G01, Frequency.R01), + SA(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.G01, Frequency.R01), /** Signal-strength GPS L1C for Rinex2. */ - SB(MeasurementType.SIGNAL_STRENGTH, Frequency.G01), + SB(MeasurementType.SIGNAL_STRENGTH, SignalCode.L, Frequency.G01), /** Signal-strength GPS L2C for Rinex2. */ - SC(MeasurementType.SIGNAL_STRENGTH, Frequency.G02), + SC(MeasurementType.SIGNAL_STRENGTH, SignalCode.L, Frequency.G02), /** Signal-strength GLONASS G2 for Rinex2. */ - SD(MeasurementType.SIGNAL_STRENGTH, Frequency.R02); + SD(MeasurementType.SIGNAL_STRENGTH, SignalCode.C, Frequency.R02); /** Measurement type. */ private final MeasurementType type; + /** Signal code. */ + private final SignalCode code; + /** Map of ferquencies. */ private final Map frequencies; /** Simple constructor. * @param type measurement type + * @param code signal code * @param frequencies compatible frequencies */ - ObservationType(final MeasurementType type, final Frequency... frequencies) { + ObservationType(final MeasurementType type, final SignalCode code, final Frequency... frequencies) { this.type = type; + this.code = code; this.frequencies = new HashMap<>(frequencies.length); for (final Frequency f : frequencies) { this.frequencies.put(f.getSatelliteSystem(), f); @@ -813,6 +902,13 @@ public enum ObservationType { return type; } + /** Get the signal code. + * @return signal code + */ + public SignalCode getSignalCode() { + return code; + } + /** Get the frequency for a specified satellite system. * @param system satellite system * @return frequency for the satellite system, or null if satellite system not compatible diff --git a/src/main/java/org/orekit/gnss/RinexLoader.java b/src/main/java/org/orekit/gnss/RinexLoader.java index ec40540ecc7a06f3559c9deb023a17e69454c9ae..a17fb2390457d09d54d28fb551205b512b72c650 100644 --- a/src/main/java/org/orekit/gnss/RinexLoader.java +++ b/src/main/java/org/orekit/gnss/RinexLoader.java @@ -19,6 +19,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -40,7 +41,7 @@ import org.orekit.time.TimeScalesFactory; /** Loader for Rinex measurements files. *

* Supported versions are: 2.00, 2.10, 2.11, 2.12 (unofficial), 2.20 (unofficial), - * 3.00, 3.01, 3.02, and 3.03. + * 3.00, 3.01, 3.02, 3.03, and 3.04. *

* @see rinex 2.0 * @see rinex 2.10 @@ -51,6 +52,7 @@ import org.orekit.time.TimeScalesFactory; * @see rinex 3.01 * @see rinex 3.02 * @see rinex 3.03 + * @see rinex 3.04 * @since 9.2 */ public class RinexLoader { @@ -95,6 +97,7 @@ public class RinexLoader { private static final String SYS_PCVS_APPLIED = "SYS / PCVS APPLIED"; private static final String SYS_SCALE_FACTOR = "SYS / SCALE FACTOR"; private static final String SYS_PHASE_SHIFT = "SYS / PHASE SHIFT"; + private static final String SYS_PHASE_SHIFTS = "SYS / PHASE SHIFTS"; private static final String GLONASS_SLOT_FRQ_NB = "GLONASS SLOT / FRQ #"; private static final String GLONASS_COD_PHS_BIS = "GLONASS COD/PHS/BIS"; private static final String OBS_SCALE_FACTOR = "OBS SCALE FACTOR"; @@ -153,6 +156,15 @@ public class RinexLoader { /** File type accepted (only Observation Data). */ private static final String FILE_TYPE = "O"; //Only Observation Data files + /** Name of the file. */ + private String name; + + /** Current line. */ + private String line; + + /** current line number. */ + private int lineNumber; + /** {@inheritDoc} */ @Override public boolean stillAcceptsData() { @@ -162,16 +174,19 @@ public class RinexLoader { /** {@inheritDoc} */ @Override - public void loadData(final InputStream input, final String name) + public void loadData(final InputStream input, final String fileName) throws IOException, OrekitException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { + + this.name = fileName; + this.line = null; + this.lineNumber = 0; // placeholders for parsed data SatelliteSystem satelliteSystem = null; double formatVersion = Double.NaN; boolean inRinexVersion = false; - int lineNumber = 0; SatelliteSystem obsTypesSystem = null; String markerName = null; String markerNumber = null; @@ -204,14 +219,12 @@ public class RinexLoader { int leapSeconds = 0; AbsoluteDate tObs = AbsoluteDate.PAST_INFINITY; String[] satsObsList = null; - String strYear = null; int eventFlag = -1; int nbSatObs = -1; int nbLinesSat = -1; double rcvrClkOffset = 0; boolean inRunBy = false; boolean inMarkerName = false; - boolean inMarkerType = false; boolean inObserver = false; boolean inRecType = false; boolean inAntType = false; @@ -229,22 +242,22 @@ public class RinexLoader { final Map> listTypeObs = new HashMap<>(); //First line must always contain Rinex Version, File Type and Satellite Systems Observed - String line = reader.readLine(); - lineNumber++; - formatVersion = parseDouble(line, 0, 9); + readLine(reader, true); + formatVersion = parseDouble(0, 9); int format100 = (int) FastMath.rint(100 * formatVersion); if ((format100 != 200) && (format100 != 210) && (format100 != 211) && (format100 != 212) && (format100 != 220) && (format100 != 300) && - (format100 != 301) && (format100 != 302) && (format100 != 303)) { + (format100 != 301) && (format100 != 302) && (format100 != 303) && + (format100 != 304)) { throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, name); } //File Type must be Observation_Data - if (!(parseString(line, 20, 1)).equals(FILE_TYPE)) { + if (!(parseString(20, 1)).equals(FILE_TYPE)) { throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, name); } - satelliteSystem = SatelliteSystem.parseSatelliteSystem(parseString(line, 40, 1)); + satelliteSystem = SatelliteSystem.parseSatelliteSystem(parseString(40, 1)); inRinexVersion = true; switch (format100 / 100) { @@ -256,19 +269,18 @@ public class RinexLoader { final int MAX_OBS_TYPES_SCALE_FACTOR = 8; final List typesObs = new ArrayList<>(); - for (line = reader.readLine(); line != null; line = reader.readLine()) { - ++lineNumber; + while (readLine(reader, false)) { if (rinexHeader == null) { switch(line.substring(LABEL_START).trim()) { case RINEX_VERSION_TYPE : - formatVersion = parseDouble(line, 0, 9); + formatVersion = parseDouble(0, 9); //File Type must be Observation_Data - if (!(parseString(line, 20, 1)).equals(FILE_TYPE)) { + if (!(parseString(20, 1)).equals(FILE_TYPE)) { throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, name); } - satelliteSystem = SatelliteSystem.parseSatelliteSystem(parseString(line, 40, 1)); + satelliteSystem = SatelliteSystem.parseSatelliteSystem(parseString(40, 1)); inRinexVersion = true; break; case COMMENT : @@ -278,68 +290,68 @@ public class RinexLoader { inRunBy = true; break; case MARKER_NAME : - markerName = parseString(line, 0, 60); + markerName = parseString(0, 60); inMarkerName = true; break; case MARKER_NUMBER : - markerNumber = parseString(line, 0, 20); + markerNumber = parseString(0, 20); break; case MARKER_TYPE : - markerType = parseString(line, 0, 20); + markerType = parseString(0, 20); break; case OBSERVER_AGENCY : - observerName = parseString(line, 0, 20); - agencyName = parseString(line, 20, 40); + observerName = parseString(0, 20); + agencyName = parseString(20, 40); inObserver = true; break; case REC_NB_TYPE_VERS : - receiverNumber = parseString(line, 0, 20); - receiverType = parseString(line, 20, 20); - receiverVersion = parseString(line, 40, 20); + receiverNumber = parseString(0, 20); + receiverType = parseString(20, 20); + receiverVersion = parseString(40, 20); inRecType = true; break; case ANT_NB_TYPE : - antennaNumber = parseString(line, 0, 20); - antennaType = parseString(line, 20, 20); + antennaNumber = parseString(0, 20); + antennaType = parseString(20, 20); inAntType = true; break; case APPROX_POSITION_XYZ : - approxPos = new Vector3D(parseDouble(line, 0, 14), parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + approxPos = new Vector3D(parseDouble(0, 14), parseDouble(14, 14), + parseDouble(28, 14)); inAproxPos = true; break; case ANTENNA_DELTA_H_E_N : - antHeight = parseDouble(line, 0, 14); - eccentricities = new Vector2D(parseDouble(line, 14, 14), parseDouble(line, 28, 14)); + antHeight = parseDouble(0, 14); + eccentricities = new Vector2D(parseDouble(14, 14), parseDouble(28, 14)); inAntDelta = true; break; case ANTENNA_DELTA_X_Y_Z : - antRefPoint = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + antRefPoint = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case ANTENNA_B_SIGHT_XYZ : - antBSight = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + antBSight = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case CENTER_OF_MASS_XYZ : - centerMass = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + centerMass = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case NB_OF_SATELLITES : - nbSat = parseInt(line, 0, 6); + nbSat = parseInt(0, 6); break; case WAVELENGTH_FACT_L1_2 : //Optional line in header //Not stored for now break; case RCV_CLOCK_OFFS_APPL : - clkOffset = parseInt(line, 0, 6); + clkOffset = parseInt(0, 6); break; case INTERVAL : - interval = parseDouble(line, 0, 10); + interval = parseDouble(0, 10); break; case TIME_OF_FIRST_OBS : switch (satelliteSystem) { @@ -354,7 +366,7 @@ public class RinexLoader { break; case MIXED: //in Case of Mixed data, Timescale must be specified in the Time of First line - timeScaleStr = parseString(line, 48, 3); + timeScaleStr = parseString(48, 3); if (timeScaleStr.equals(GPS)) { timeScale = TimeScalesFactory.getGPS(); @@ -371,60 +383,59 @@ public class RinexLoader { lineNumber, name, line); } - tFirstObs = new AbsoluteDate(parseInt(line, 0, 6), - parseInt(line, 6, 6), - parseInt(line, 12, 6), - parseInt(line, 18, 6), - parseInt(line, 24, 6), - parseDouble(line, 30, 13), timeScale); + tFirstObs = new AbsoluteDate(parseInt(0, 6), + parseInt(6, 6), + parseInt(12, 6), + parseInt(18, 6), + parseInt(24, 6), + parseDouble(30, 13), timeScale); inFirstObs = true; break; case TIME_OF_LAST_OBS : - tLastObs = new AbsoluteDate(parseInt(line, 0, 6), - parseInt(line, 6, 6), - parseInt(line, 12, 6), - parseInt(line, 18, 6), - parseInt(line, 24, 6), - parseDouble(line, 30, 13), timeScale); + tLastObs = new AbsoluteDate(parseInt(0, 6), + parseInt(6, 6), + parseInt(12, 6), + parseInt(18, 6), + parseInt(24, 6), + parseDouble(30, 13), timeScale); break; case LEAP_SECONDS : - leapSeconds = parseInt(line, 0, 6); + leapSeconds = parseInt(0, 6); break; case PRN_NB_OF_OBS : //Optional line in header, indicates number of Observations par Satellite //Not stored for now break; case NB_TYPES_OF_OBSERV : - nbTypes = parseInt(line, 0, 6); + nbTypes = parseInt(0, 6); final int nbLinesTypesObs = (nbTypes + MAX_OBS_TYPES_PER_LINE_RNX2 - 1 ) / MAX_OBS_TYPES_PER_LINE_RNX2; for (int j = 0; j < nbLinesTypesObs; j++) { if (j > 0) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } final int iMax = FastMath.min(MAX_OBS_TYPES_PER_LINE_RNX2, nbTypes - typesObs.size()); for (int i = 0; i < iMax; i++) { try { - typesObs.add(ObservationType.valueOf(parseString(line, 10 + (6 * i), 2))); + typesObs.add(ObservationType.valueOf(parseString(10 + (6 * i), 2))); } catch (IllegalArgumentException iae) { throw new OrekitException(OrekitMessages.UNKNOWN_RINEX_FREQUENCY, - parseString(line, 10 + (6 * i), 2), name, lineNumber); + parseString(10 + (6 * i), 2), name, lineNumber); } } } inTypesObs = true; break; case OBS_SCALE_FACTOR : - scaleFactor = FastMath.max(1, parseInt(line, 0, 6)); - nbObsScaleFactor = parseInt(line, 6, 6); + scaleFactor = FastMath.max(1, parseInt(0, 6)); + nbObsScaleFactor = parseInt(6, 6); if (nbObsScaleFactor > MAX_OBS_TYPES_SCALE_FACTOR) { throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, lineNumber, name, line); } final List typesObsScaleFactor = new ArrayList<>(nbObsScaleFactor); for (int i = 0; i < nbObsScaleFactor; i++) { - typesObsScaleFactor.add(ObservationType.valueOf(parseString(line, 16 + (6 * i), 2))); + typesObsScaleFactor.add(ObservationType.valueOf(parseString(16 + (6 * i), 2))); } scaleFactorCorrections.add(new ScaleFactorCorrection(satelliteSystem, scaleFactor, typesObsScaleFactor)); @@ -464,43 +475,40 @@ public class RinexLoader { nbSatObs = -1; satsObsList = null; tObs = null; - strYear = null; - eventFlag = parseInt(line, 28, 1); + eventFlag = parseInt(28, 1); //If eventFlag>1, we skip the corresponding lines to the next observation - if (eventFlag != 0) { + if (eventFlag > 1) { if (eventFlag == 6) { - nbSatObs = parseInt(line, 29, 3); + nbSatObs = parseInt(29, 3); nbLinesSat = (nbSatObs + 12 - 1) / 12; final int nbLinesObs = (nbTypes + 5 - 1) / 5; final int nbLinesSkip = (nbLinesSat - 1) + nbSatObs * nbLinesObs; for (int i = 0; i < nbLinesSkip; i++) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } } else { - final int nbLinesSkip = parseInt(line, 29, 3); + final int nbLinesSkip = parseInt(29, 3); for (int i = 0; i < nbLinesSkip; i++) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } } } else { - final int y = Integer.parseInt(parseString(line, 0, 3)); + int y = parseInt(0, 3); if (79 < y && y <= 99) { - strYear = "19" + y; + y += 1900; } else if (0 <= y && y <= 79) { - strYear = "20" + parseString(line, 0, 3); + y += 2000; } - tObs = new AbsoluteDate(Integer.parseInt(strYear), - parseInt(line, 3, 3), - parseInt(line, 6, 3), - parseInt(line, 9, 3), - parseInt(line, 12, 3), - parseDouble(line, 15, 11), timeScale); - - nbSatObs = parseInt(line, 29, 3); + tObs = new AbsoluteDate(y, + parseInt(3, 3), + parseInt(6, 3), + parseInt(9, 3), + parseInt(12, 3), + parseDouble(15, 11), timeScale); + + nbSatObs = parseInt(29, 3); satsObsList = new String[nbSatObs]; //If the total number of satellites was indicated in the Header if (nbSat != -1 && nbSatObs > nbSat) { @@ -512,16 +520,15 @@ public class RinexLoader { nbLinesSat = (nbSatObs + MAX_N_SAT_OBSERVATION - 1) / MAX_N_SAT_OBSERVATION; for (int j = 0; j < nbLinesSat; j++) { if (j > 0) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } final int iMax = FastMath.min(MAX_N_SAT_OBSERVATION, nbSatObs - j * MAX_N_SAT_OBSERVATION); for (int i = 0; i < iMax; i++) { - satsObsList[i + MAX_N_SAT_OBSERVATION * j] = parseString(line, 32 + 3 * i, 3); + satsObsList[i + MAX_N_SAT_OBSERVATION * j] = parseString(32 + 3 * i, 3); } //Read the Receiver Clock offset, if present - rcvrClkOffset = parseDouble(line, 68, 12); + rcvrClkOffset = parseDouble(68, 12); if (Double.isNaN(rcvrClkOffset)) { rcvrClkOffset = 0.0; } @@ -538,12 +545,11 @@ public class RinexLoader { // - 5 Observations per line final List observationData = new ArrayList<>(nbSatObs); for (int j = 0; j < nbLinesObs; j++) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); final int iMax = FastMath.min(MAX_N_TYPES_OBSERVATION, nbTypes - observationData.size()); for (int i = 0; i < iMax; i++) { final ObservationType type = typesObs.get(observationData.size()); - double value = parseDouble(line, 16 * i, 14); + double value = parseDouble(16 * i, 14); boolean scaleFactorFound = false; //We look for the lines of ScaledFactorCorrections for (int l = 0; l < scaleFactorCorrections.size() && !scaleFactorFound; ++l) { @@ -555,8 +561,8 @@ public class RinexLoader { } observationData.add(new ObservationData(type, value, - parseInt(line, 14 + 16 * i, 1), - parseInt(line, 15 + 16 * i, 1))); + parseInt(14 + 16 * i, 1), + parseInt(15 + 16 * i, 1))); } } @@ -625,21 +631,20 @@ public class RinexLoader { ObservationType phaseShiftTypeObs = null; - for (line = reader.readLine(); line != null; line = reader.readLine()) { - ++lineNumber; + while (readLine(reader, false)) { if (rinexHeader == null) { switch(line.substring(LABEL_START).trim()) { case RINEX_VERSION_TYPE : { - formatVersion = parseDouble(line, 0, 9); + formatVersion = parseDouble(0, 9); format100 = (int) FastMath.rint(100 * formatVersion); - if ((format100 != 300) && (format100 != 301) && (format100 != 302) && (format100 != 303)) { + if ((format100 != 300) && (format100 != 301) && (format100 != 302) && (format100 != 303) && (format100 != 304)) { throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, name); } //File Type must be Observation_Data - if (!(parseString(line, 20, 1)).equals(FILE_TYPE)) { + if (!(parseString(20, 1)).equals(FILE_TYPE)) { throw new OrekitException(OrekitMessages.UNSUPPORTED_FILE_FORMAT, name); } - satelliteSystem = SatelliteSystem.parseSatelliteSystem(parseString(line, 40, 1)); + satelliteSystem = SatelliteSystem.parseSatelliteSystem(parseString(40, 1)); inRinexVersion = true; } break; @@ -650,82 +655,81 @@ public class RinexLoader { inRunBy = true; break; case MARKER_NAME : - markerName = parseString(line, 0, 60); + markerName = parseString(0, 60); inMarkerName = true; break; case MARKER_NUMBER : - markerNumber = parseString(line, 0, 20); + markerNumber = parseString(0, 20); break; case MARKER_TYPE : - markerType = parseString(line, 0, 20); - inMarkerType = true; + markerType = parseString(0, 20); //Could be done with an Enumeration break; case OBSERVER_AGENCY : - observerName = parseString(line, 0, 20); - agencyName = parseString(line, 20, 40); + observerName = parseString(0, 20); + agencyName = parseString(20, 40); inObserver = true; break; case REC_NB_TYPE_VERS : - receiverNumber = parseString(line, 0, 20); - receiverType = parseString(line, 20, 20); - receiverVersion = parseString(line, 40, 20); + receiverNumber = parseString(0, 20); + receiverType = parseString(20, 20); + receiverVersion = parseString(40, 20); inRecType = true; break; case ANT_NB_TYPE : - antennaNumber = parseString(line, 0, 20); - antennaType = parseString(line, 20, 20); + antennaNumber = parseString(0, 20); + antennaType = parseString(20, 20); inAntType = true; break; case APPROX_POSITION_XYZ : - approxPos = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + approxPos = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); inAproxPos = true; break; case ANTENNA_DELTA_H_E_N : - antHeight = parseDouble(line, 0, 14); - eccentricities = new Vector2D(parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + antHeight = parseDouble(0, 14); + eccentricities = new Vector2D(parseDouble(14, 14), + parseDouble(28, 14)); inAntDelta = true; break; case ANTENNA_DELTA_X_Y_Z : - antRefPoint = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + antRefPoint = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case ANTENNA_PHASECENTER : - obsCode = parseString(line, 2, 3); - antPhaseCenter = new Vector3D(parseDouble(line, 5, 9), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + obsCode = parseString(2, 3); + antPhaseCenter = new Vector3D(parseDouble(5, 9), + parseDouble(14, 14), + parseDouble(28, 14)); break; case ANTENNA_B_SIGHT_XYZ : - antBSight = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + antBSight = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case ANTENNA_ZERODIR_AZI : - antAzi = parseDouble(line, 0, 14); + antAzi = parseDouble(0, 14); break; case ANTENNA_ZERODIR_XYZ : - antZeroDir = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + antZeroDir = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case CENTER_OF_MASS_XYZ : - centerMass = new Vector3D(parseDouble(line, 0, 14), - parseDouble(line, 14, 14), - parseDouble(line, 28, 14)); + centerMass = new Vector3D(parseDouble(0, 14), + parseDouble(14, 14), + parseDouble(28, 14)); break; case NB_OF_SATELLITES : - nbSat = parseInt(line, 0, 6); + nbSat = parseInt(0, 6); break; case RCV_CLOCK_OFFS_APPL : - clkOffset = parseInt(line, 0, 6); + clkOffset = parseInt(0, 6); break; case INTERVAL : - interval = parseDouble(line, 0, 10); + interval = parseDouble(0, 10); break; case TIME_OF_FIRST_OBS : switch(satelliteSystem) { @@ -749,7 +753,7 @@ public class RinexLoader { break; case MIXED: //in Case of Mixed data, Timescale must be specified in the Time of First line - timeScaleStr = parseString(line, 48, 3); + timeScaleStr = parseString(48, 3); if (timeScaleStr.equals(GPS)) { timeScale = TimeScalesFactory.getGPS(); @@ -772,27 +776,27 @@ public class RinexLoader { lineNumber, name, line); } - tFirstObs = new AbsoluteDate(parseInt(line, 0, 6), - parseInt(line, 6, 6), - parseInt(line, 12, 6), - parseInt(line, 18, 6), - parseInt(line, 24, 6), - parseDouble(line, 30, 13), timeScale); + tFirstObs = new AbsoluteDate(parseInt(0, 6), + parseInt(6, 6), + parseInt(12, 6), + parseInt(18, 6), + parseInt(24, 6), + parseDouble(30, 13), timeScale); inFirstObs = true; break; case TIME_OF_LAST_OBS : - tLastObs = new AbsoluteDate(parseInt(line, 0, 6), - parseInt(line, 6, 6), - parseInt(line, 12, 6), - parseInt(line, 18, 6), - parseInt(line, 24, 6), - parseDouble(line, 30, 13), timeScale); + tLastObs = new AbsoluteDate(parseInt(0, 6), + parseInt(6, 6), + parseInt(12, 6), + parseInt(18, 6), + parseInt(24, 6), + parseDouble(30, 13), timeScale); break; case LEAP_SECONDS : - leapSeconds = parseInt(line, 0, 6); - leapSecondsFuture = parseInt(line, 6, 6); - leapSecondsWeekNum = parseInt(line, 12, 6); - leapSecondsDayNum = parseInt(line, 18, 6); + leapSeconds = parseInt(0, 6); + leapSecondsFuture = parseInt(6, 6); + leapSecondsWeekNum = parseInt(12, 6); + leapSecondsDayNum = parseInt(18, 6); //Time System Identifier must be added, last A3 String break; case PRN_NB_OF_OBS : @@ -803,22 +807,21 @@ public class RinexLoader { obsTypesSystem = null; typeObs.clear(); - obsTypesSystem = SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)); - nbTypes = parseInt(line, 3, 3); + obsTypesSystem = SatelliteSystem.parseSatelliteSystem(parseString(0, 1)); + nbTypes = parseInt(3, 3); final int nbLinesTypesObs = (nbTypes + MAX_OBS_TYPES_PER_LINE_RNX3 - 1) / MAX_OBS_TYPES_PER_LINE_RNX3; for (int j = 0; j < nbLinesTypesObs; j++) { if (j > 0) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } final int iMax = FastMath.min(MAX_OBS_TYPES_PER_LINE_RNX3, nbTypes - typeObs.size()); for (int i = 0; i < iMax; i++) { try { - typeObs.add(ObservationType.valueOf(parseString(line, 7 + (4 * i), 3))); + typeObs.add(ObservationType.valueOf(parseString(7 + (4 * i), 3))); } catch (IllegalArgumentException iae) { throw new OrekitException(OrekitMessages.UNKNOWN_RINEX_FREQUENCY, - parseString(line, 7 + (4 * i), 3), name, lineNumber); + parseString(7 + (4 * i), 3), name, lineNumber); } } } @@ -826,26 +829,26 @@ public class RinexLoader { inTypesObs = true; break; case SIGNAL_STRENGTH_UNIT : - sigStrengthUnit = parseString(line, 0, 20); + sigStrengthUnit = parseString(0, 20); break; case SYS_DCBS_APPLIED : - listAppliedDCBs.add(new AppliedDCBS(SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)), - parseString(line, 2, 17), parseString(line, 20, 40))); + listAppliedDCBs.add(new AppliedDCBS(SatelliteSystem.parseSatelliteSystem(parseString(0, 1)), + parseString(2, 17), parseString(20, 40))); break; case SYS_PCVS_APPLIED : - listAppliedPCVS.add(new AppliedPCVS(SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)), - parseString(line, 2, 17), parseString(line, 20, 40))); + listAppliedPCVS.add(new AppliedPCVS(SatelliteSystem.parseSatelliteSystem(parseString(0, 1)), + parseString(2, 17), parseString(20, 40))); break; case SYS_SCALE_FACTOR : satSystemScaleFactor = null; scaleFactor = 1; nbObsScaleFactor = 0; - satSystemScaleFactor = SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)); - scaleFactor = parseInt(line, 2, 4); - nbObsScaleFactor = parseInt(line, 8, 2); + satSystemScaleFactor = SatelliteSystem.parseSatelliteSystem(parseString(0, 1)); + scaleFactor = parseInt(2, 4); + nbObsScaleFactor = parseInt(8, 2); final List typesObsScaleFactor = new ArrayList<>(nbObsScaleFactor); if (nbObsScaleFactor == 0) { @@ -855,12 +858,11 @@ public class RinexLoader { MAX_OBS_TYPES_SCALE_FACTOR_PER_LINE; for (int j = 0; j < nbLinesTypesObsScaleFactor; j++) { if ( j > 0) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } final int iMax = FastMath.min(MAX_OBS_TYPES_SCALE_FACTOR_PER_LINE, nbObsScaleFactor - typesObsScaleFactor.size()); for (int i = 0; i < iMax; i++) { - typesObsScaleFactor.add(ObservationType.valueOf(parseString(line, 11 + (4 * i), 3))); + typesObsScaleFactor.add(ObservationType.valueOf(parseString(11 + (4 * i), 3))); } } } @@ -868,7 +870,8 @@ public class RinexLoader { scaleFactorCorrections.add(new ScaleFactorCorrection(satSystemScaleFactor, scaleFactor, typesObsScaleFactor)); break; - case SYS_PHASE_SHIFT : + case SYS_PHASE_SHIFT : + case SYS_PHASE_SHIFTS : { nbSatPhaseShift = 0; satsPhaseShift = null; @@ -876,10 +879,13 @@ public class RinexLoader { phaseShiftTypeObs = null; satSystemPhaseShift = null; - satSystemPhaseShift = SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)); - phaseShiftTypeObs = ObservationType.valueOf(parseString(line, 2, 3)); - nbSatPhaseShift = parseInt(line, 16, 2); - corrPhaseShift = parseDouble(line, 6, 8); + satSystemPhaseShift = SatelliteSystem.parseSatelliteSystem(parseString(0, 1)); + final String to = parseString(2, 3); + phaseShiftTypeObs = to.isEmpty() ? + null : + ObservationType.valueOf(to.length() < 3 ? "L" + to : to); + nbSatPhaseShift = parseInt(16, 2); + corrPhaseShift = parseDouble(6, 8); if (nbSatPhaseShift == 0) { //If nbSat with Phase Shift is not indicated: all the satellites are affected for this Obs Type @@ -888,12 +894,11 @@ public class RinexLoader { final int nbLinesSatPhaseShift = (nbSatPhaseShift + MAX_N_SAT_PHSHIFT_PER_LINE - 1) / MAX_N_SAT_PHSHIFT_PER_LINE; for (int j = 0; j < nbLinesSatPhaseShift; j++) { if (j > 0) { - line = reader.readLine(); //Next line - lineNumber++; + readLine(reader, true); } final int iMax = FastMath.min(MAX_N_SAT_PHSHIFT_PER_LINE, nbSatPhaseShift - j * MAX_N_SAT_PHSHIFT_PER_LINE); for (int i = 0; i < iMax; i++) { - satsPhaseShift[i + 10 * j] = parseString(line, 19 + 4 * i, 3); + satsPhaseShift[i + 10 * j] = parseString(19 + 4 * i, 3); } } } @@ -903,6 +908,7 @@ public class RinexLoader { satsPhaseShift)); inPhaseShift = true; break; + } case GLONASS_SLOT_FRQ_NB : //Not defined yet inGlonassSlot = true; @@ -914,7 +920,7 @@ public class RinexLoader { case END_OF_HEADER : //We make sure that we have read all the mandatory fields inside the header of the Rinex if (!inRinexVersion || !inRunBy || !inMarkerName || - !inMarkerType || !inObserver || !inRecType || !inAntType || + !inObserver || !inRecType || !inAntType || !inAproxPos || !inAntDelta || !inTypesObs || !inFirstObs || (formatVersion >= 3.01 && !inPhaseShift) || (formatVersion >= 3.03 && (!inGlonassSlot || !inGlonassCOD))) { @@ -950,26 +956,25 @@ public class RinexLoader { tObs = null; //A line that starts with ">" correspond to a new observation epoch - if (parseString(line, 0, 1).equals(">")) { + if (parseString(0, 1).equals(">")) { - eventFlag = parseInt(line, 31, 1); + eventFlag = parseInt(31, 1); //If eventFlag>1, we skip the corresponding lines to the next observation if (eventFlag != 0) { - final int nbLinesSkip = parseInt(line, 32, 3); + final int nbLinesSkip = parseInt(32, 3); for (int i = 0; i < nbLinesSkip; i++) { - line = reader.readLine(); - lineNumber++; + readLine(reader, true); } } else { - tObs = new AbsoluteDate(parseInt(line, 2, 4), - parseInt(line, 6, 3), - parseInt(line, 9, 3), - parseInt(line, 12, 3), - parseInt(line, 15, 3), - parseDouble(line, 18, 11), timeScale); + tObs = new AbsoluteDate(parseInt(2, 4), + parseInt(6, 3), + parseInt(9, 3), + parseInt(12, 3), + parseInt(15, 3), + parseDouble(18, 11), timeScale); - nbSatObs = parseInt(line, 32, 3); + nbSatObs = parseInt(32, 3); //If the total number of satellites was indicated in the Header if (nbSat != -1 && nbSatObs > nbSat) { //we check that the number of Sat in the observation is consistent @@ -977,7 +982,7 @@ public class RinexLoader { lineNumber, name, nbSatObs, nbSat); } //Read the Receiver Clock offset, if present - rcvrClkOffset = parseDouble(line, 41, 15); + rcvrClkOffset = parseDouble(41, 15); if (Double.isNaN(rcvrClkOffset)) { rcvrClkOffset = 0.0; } @@ -985,11 +990,10 @@ public class RinexLoader { //For each one of the Satellites in this Observation for (int i = 0; i < nbSatObs; i++) { - line = reader.readLine(); - lineNumber++; + readLine(reader, true); //We check that the Satellite type is consistent with Satellite System in the top of the file - final SatelliteSystem satelliteSystemSat = SatelliteSystem.parseSatelliteSystem(parseString(line, 0, 1)); + final SatelliteSystem satelliteSystemSat = SatelliteSystem.parseSatelliteSystem(parseString(0, 1)); if (!satelliteSystem.equals(SatelliteSystem.MIXED)) { if (!satelliteSystemSat.equals(satelliteSystem)) { throw new OrekitException(OrekitMessages.INCONSISTENT_SATELLITE_SYSTEM, @@ -997,7 +1001,7 @@ public class RinexLoader { } } - final int prn = parseInt(line, 1, 2); + final int prn = parseInt(1, 2); final int prnNumber; switch (satelliteSystemSat) { case GPS: @@ -1024,7 +1028,7 @@ public class RinexLoader { boolean scaleFactorFound = false; //We look for the lines of ScaledFactorCorrections that correspond to this SatSystem int k = 0; - double value = parseDouble(line, 3 + j * 16, 14); + double value = parseDouble(3 + j * 16, 14); while (k < scaleFactorCorrections.size() && !scaleFactorFound) { if (scaleFactorCorrections.get(k).getSatelliteSystem().equals(satelliteSystemSat)) { //We check if the next Observation Type to read needs to be scaled @@ -1037,8 +1041,8 @@ public class RinexLoader { } observationData.add(new ObservationData(rf, value, - parseInt(line, 17 + j * 16, 1), - parseInt(line, 18 + j * 16, 1))); + parseInt(17 + j * 16, 1), + parseInt(18 + j * 16, 1))); } observationDataSets.add(new ObservationDataSet(rinexHeader, satelliteSystemSat, prnNumber, tObs, rcvrClkOffset, observationData)); @@ -1057,14 +1061,28 @@ public class RinexLoader { } } + /** Read a new line. + * @param reader reader from where to read line + * @param complainIfEnd if true an exception should be thrown if end of file is encountered + * @return true if a line has been read + * @exception IOException if a read error occurs + */ + private boolean readLine(final BufferedReader reader, final boolean complainIfEnd) + throws IOException { + line = reader.readLine(); + if (line == null && complainIfEnd) { + throw new OrekitException(OrekitMessages.UNEXPECTED_END_OF_FILE, name); + } + lineNumber++; + return line != null; + } /** Extract a string from a line. - * @param line to parse * @param start start index of the string * @param length length of the string * @return parsed string */ - private String parseString(final String line, final int start, final int length) { + private String parseString(final int start, final int length) { if (line.length() > start) { return line.substring(start, FastMath.min(line.length(), start + length)).trim(); } else { @@ -1073,28 +1091,26 @@ public class RinexLoader { } /** Extract an integer from a line. - * @param line to parse * @param start start index of the integer * @param length length of the integer * @return parsed integer */ - private int parseInt(final String line, final int start, final int length) { - if (line.length() > start && !parseString(line, start, length).isEmpty()) { - return Integer.parseInt(parseString(line, start, length)); + private int parseInt(final int start, final int length) { + if (line.length() > start && !parseString(start, length).isEmpty()) { + return Integer.parseInt(parseString(start, length)); } else { return 0; } } /** Extract a double from a line. - * @param line to parse * @param start start index of the real * @param length length of the real * @return parsed real, or {@code Double.NaN} if field was empty */ - private double parseDouble(final String line, final int start, final int length) { - if (line.length() > start && !parseString(line, start, length).isEmpty()) { - return Double.parseDouble(parseString(line, start, length)); + private double parseDouble(final int start, final int length) { + if (line.length() > start && !parseString(start, length).isEmpty()) { + return Double.parseDouble(parseString(start, length)); } else { return Double.NaN; } @@ -1108,7 +1124,7 @@ public class RinexLoader { /** Satellite System. */ private final SatelliteSystem satSystemPhaseShift; - /** Carrier Phase Observation Code. */ + /** Carrier Phase Observation Code (may be null). */ private final ObservationType typeObsPhaseShift; /** Phase Shift Corrections (cycles). */ private final double phaseShiftCorrection; @@ -1117,7 +1133,7 @@ public class RinexLoader { /** Simple constructor. * @param satSystemPhaseShift Satellite System - * @param typeObsPhaseShift Carrier Phase Observation Code + * @param typeObsPhaseShift Carrier Phase Observation Code (may be null) * @param phaseShiftCorrection Phase Shift Corrections (cycles) * @param satsPhaseShift List of satellites involved */ @@ -1137,6 +1153,10 @@ public class RinexLoader { return satSystemPhaseShift; } /** Get the Carrier Phase Observation Code. + *

+ * The observation code may be null for the uncorrected reference + * signal group + *

* @return Carrier Phase Observation Code. */ public ObservationType getTypeObs() { diff --git a/src/main/java/org/orekit/gnss/SEMParser.java b/src/main/java/org/orekit/gnss/SEMParser.java index 7ec930ba842a9342f28a1deeccd4943bc335e992..11caf260c8ff5a821b14e774093cb41065427dc4 100644 --- a/src/main/java/org/orekit/gnss/SEMParser.java +++ b/src/main/java/org/orekit/gnss/SEMParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -120,7 +121,7 @@ public class SEMParser implements DataLoader { prnList.clear(); // Creates the reader - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); try { // Reads the number of almanacs in the file from the first line diff --git a/src/main/java/org/orekit/gnss/SignalCode.java b/src/main/java/org/orekit/gnss/SignalCode.java new file mode 100644 index 0000000000000000000000000000000000000000..fa8a33f900608139f7fee0bfa151872fb539c353 --- /dev/null +++ b/src/main/java/org/orekit/gnss/SignalCode.java @@ -0,0 +1,75 @@ +/* Copyright 2002-2019 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.gnss; + +/** + * Enumerate for satellite signal code. + * + * @author Bryan Cazabonne + * @since 10.1 + */ +public enum SignalCode { + + /** Galileo A PRS / IRNSS A SPS / GLONASS L1OCd and L2CSI codes. */ + A, + + /** Galileo B I/NAV and B C/NAV / IRNSS B RS / GLONASS L1OCp and LO2Cp codes. */ + B, + + /** GPS C/A / GLONASS C/A / Galileo C / SBAS C/A / QZSS C/A / IRNSS C RS(P) codes. */ + C, + + /** GPS L1(C/A) + (P2-P1) / QZSS L5D codes. */ + D, + + /** QZSS L6E and L6 (D+E) codes. */ + E, + + /** GPS I / GLONASS I / Galileo I F/NAV, I I/NAV and I / SBAS I/ Beidou I codes. */ + I, + + /** GPS L1C (P) and L2C (L) / QZSS L1C (P), L2C (L) and L code. */ + L, + + /** GPS M code. */ + M, + + /** GPS P (AS off) / GLONASS P / QZSS L5P codes. */ + P, + + /** GPS Q / GLONASS Q / Galileo Q / SBAS Q / QZSS Q / Beidou Q codes. */ + Q, + + /** GPS L1C (D), L2C (M) / QZSS L1C (D), L2C (M) and S codes. */ + S, + + /** GPS Z - tracking and similar (AS off) / code. */ + W, + + /** GPS L1C (D+P), L2C (M+L) and I+Q / GLONASS I+Q, L1OCd+L1OCp and L2CSI+LO2Cp / Galileo B+C and I+Q / SBAS I+Q / QZSS L1C (D+P), L2C (M+L), I+Q and S+L / Beidou I+Q / IRNSS B+C codes. */ + X, + + /** GPS Y code. */ + Y, + + /** Galileo A+B+C / QZSS L1-SAIF, L5(D+P) and L6(D+E) codes. */ + Z, + + /** Codeless. */ + CODELESS; + +} diff --git a/src/main/java/org/orekit/gnss/YUMAParser.java b/src/main/java/org/orekit/gnss/YUMAParser.java index 4e954d1d5f384d1ac58210674f4dc4ed6849ecfc..268a21a1b997c75b27a54cdbf8041669cc477850 100644 --- a/src/main/java/org/orekit/gnss/YUMAParser.java +++ b/src/main/java/org/orekit/gnss/YUMAParser.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -132,7 +133,7 @@ public class YUMAParser implements DataLoader { prnList.clear(); // Creates the reader - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); try { // Gathers data to create one GPSAlmanac from 13 consecutive lines diff --git a/src/main/java/org/orekit/gnss/antenna/AntexLoader.java b/src/main/java/org/orekit/gnss/antenna/AntexLoader.java index c73c9aec21942fc28099de518cb53abf23cef26e..2b020456657534c7fb60ee77f14491dc103f4cc0 100644 --- a/src/main/java/org/orekit/gnss/antenna/AntexLoader.java +++ b/src/main/java/org/orekit/gnss/antenna/AntexLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -155,7 +156,7 @@ public class AntexLoader { public void loadData(final InputStream input, final String name) throws IOException, OrekitException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { // placeholders for parsed data int lineNumber = 0; @@ -326,6 +327,13 @@ public class AntexLoader { } + // Check if the number of frequencies has been parsed + if (patterns == null) { + // null object, an OrekitException is thrown + throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, + lineNumber, name, line); + } + final PhaseCenterVariationFunction phaseCenterVariation; if (grid2D == null) { double max = 0; diff --git a/src/main/java/org/orekit/gnss/attitude/GNSSAttitudeContext.java b/src/main/java/org/orekit/gnss/attitude/GNSSAttitudeContext.java index f5046d90351c06484697c36d2f4031a913b6d60b..7e5255d66b0289732ff6e780dcc38919c25044fa 100644 --- a/src/main/java/org/orekit/gnss/attitude/GNSSAttitudeContext.java +++ b/src/main/java/org/orekit/gnss/attitude/GNSSAttitudeContext.java @@ -270,11 +270,11 @@ class GNSSAttitudeContext implements TimeStamped { final double dtMin = FastMath.min(turnSpan.getTurnStartDate().durationFrom(date), dt0 - 60.0); final double dtMax = FastMath.max(dtMin + fullTurn, dt0 + 60.0); double[] bracket = UnivariateSolverUtils.bracket(yawReached, dt0, - dtMin, dtMax, 1.0, 2.0, 15); + dtMin, dtMax, fullTurn / 100, 1.0, 100); if (yawReached.value(bracket[0]) <= 0.0) { // we have bracketed the wrong crossing bracket = UnivariateSolverUtils.bracket(yawReached, 0.5 * (bracket[0] + bracket[1] + fullTurn), - bracket[1], bracket[1] + fullTurn, 1.0, 2.0, 15); + bracket[1], bracket[1] + fullTurn, fullTurn / 100, 1.0, 100); } final double dt = new BracketingNthOrderBrentSolver(1.0e-3, 5). solve(100, yawReached, bracket[0], bracket[1]); diff --git a/src/main/java/org/orekit/gnss/attitude/GNSSFieldAttitudeContext.java b/src/main/java/org/orekit/gnss/attitude/GNSSFieldAttitudeContext.java index dac0472a3d69c7f7e8f7595d09a87c07f10b0f1a..580260d87fdb7b8eb69305ebd470ea130d4e6c02 100644 --- a/src/main/java/org/orekit/gnss/attitude/GNSSFieldAttitudeContext.java +++ b/src/main/java/org/orekit/gnss/attitude/GNSSFieldAttitudeContext.java @@ -297,11 +297,11 @@ class GNSSFieldAttitudeContext> implements FieldTi final double dtMin = FastMath.min(turnSpan.getTurnStartDate().durationFrom(date).getReal(), dt0 - 60.0); final double dtMax = FastMath.max(dtMin + fullTurn, dt0 + 60.0); double[] bracket = UnivariateSolverUtils.bracket(yawReached, dt0, - dtMin, dtMax, 1.0, 2.0, 15); + dtMin, dtMax, fullTurn / 100, 1.0, 100); if (yawReached.value(bracket[0]) <= 0.0) { // we have bracketed the wrong crossing bracket = UnivariateSolverUtils.bracket(yawReached, 0.5 * (bracket[0] + bracket[1] + fullTurn), - bracket[1], bracket[1] + fullTurn, 1.0, 2.0, 15); + bracket[1], bracket[1] + fullTurn, fullTurn / 100, 1.0, 100); } final double dt = new BracketingNthOrderBrentSolver(1.0e-3, 5). solve(100, yawReached, bracket[0], bracket[1]); diff --git a/src/main/java/org/orekit/models/earth/GeoMagneticModelLoader.java b/src/main/java/org/orekit/models/earth/GeoMagneticModelLoader.java index d79e2aa5e3be029821ff47d0d846c13f746b5f22..ca4cbb96f2a3698050d8c8c1e79f02abc38fc4a6 100644 --- a/src/main/java/org/orekit/models/earth/GeoMagneticModelLoader.java +++ b/src/main/java/org/orekit/models/earth/GeoMagneticModelLoader.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StreamTokenizer; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Collection; import java.util.LinkedList; @@ -93,7 +94,7 @@ public class GeoMagneticModelLoader implements DataLoader { throws IOException, ParseException { // open data file and parse values - final StreamTokenizer str = new StreamTokenizer(new InputStreamReader(input, "UTF-8")); + final StreamTokenizer str = new StreamTokenizer(new InputStreamReader(input, StandardCharsets.UTF_8)); while (true) { final GeoMagneticField model = readModel(str); diff --git a/src/main/java/org/orekit/models/earth/ReferenceEllipsoid.java b/src/main/java/org/orekit/models/earth/ReferenceEllipsoid.java index a1e6120605128b9b98e81778d2e17e42cba30d2f..c9b193eeb2db3b947af7ec4ada5655dcf84c52de 100644 --- a/src/main/java/org/orekit/models/earth/ReferenceEllipsoid.java +++ b/src/main/java/org/orekit/models/earth/ReferenceEllipsoid.java @@ -51,6 +51,7 @@ import org.orekit.utils.Constants; * Third Edition, Amendment 1. * * @author Evan Ward + * @author Guylaine Prat */ public class ReferenceEllipsoid extends OneAxisEllipsoid implements EarthShape { @@ -242,4 +243,42 @@ public class ReferenceEllipsoid extends OneAxisEllipsoid implements EarthShape { ); } + /** + * Get the IERS96 ellipsoid, attached to the given body frame. + * + * @param bodyFrame the earth centered fixed frame + * @return an IERS96 reference ellipsoid + */ + public static ReferenceEllipsoid getIers96(final Frame bodyFrame) { + return new ReferenceEllipsoid(Constants.IERS96_EARTH_EQUATORIAL_RADIUS, + Constants.IERS96_EARTH_FLATTENING, bodyFrame, + Constants.IERS96_EARTH_MU, + Constants.IERS96_EARTH_ANGULAR_VELOCITY); + } + + /** + * Get the IERS2003 ellipsoid, attached to the given body frame. + * + * @param bodyFrame the earth centered fixed frame + * @return an IERS2003 reference ellipsoid + */ + public static ReferenceEllipsoid getIers2003(final Frame bodyFrame) { + return new ReferenceEllipsoid(Constants.IERS2003_EARTH_EQUATORIAL_RADIUS, + Constants.IERS2003_EARTH_FLATTENING, bodyFrame, + Constants.IERS2003_EARTH_MU, + Constants.IERS2003_EARTH_ANGULAR_VELOCITY); + } + + /** + * Get the IERS2010 ellipsoid, attached to the given body frame. + * + * @param bodyFrame the earth centered fixed frame + * @return an IERS2010 reference ellipsoid + */ + public static ReferenceEllipsoid getIers2010(final Frame bodyFrame) { + return new ReferenceEllipsoid(Constants.IERS2010_EARTH_EQUATORIAL_RADIUS, + Constants.IERS2010_EARTH_FLATTENING, bodyFrame, + Constants.IERS2010_EARTH_MU, + Constants.IERS2010_EARTH_ANGULAR_VELOCITY); + } } diff --git a/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java b/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java index 7895a50d0d3c35f67d7baf02b5d5851e79b8fe56..59b064ef656bbb5f36c8767d8573f3a03bf3c084 100644 --- a/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java +++ b/src/main/java/org/orekit/models/earth/atmosphere/data/MarshallSolarActivityFutureEstimation.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Serializable; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.Iterator; import java.util.SortedSet; @@ -483,7 +484,7 @@ public class MarshallSolarActivityFutureEstimation implements DataLoader, DTM200 } // read the data - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); boolean inData = false; final TimeScale utc = TimeScalesFactory.getUTC(); DateComponents fileDate = null; diff --git a/src/main/java/org/orekit/models/earth/displacement/OceanLoadingCoefficientsBLQFactory.java b/src/main/java/org/orekit/models/earth/displacement/OceanLoadingCoefficientsBLQFactory.java index 7464c16651c0d61244ba51ba954f1ecac378f036..1f2764e493a2294573f6332b54de5d1fe1dbcea6 100644 --- a/src/main/java/org/orekit/models/earth/displacement/OceanLoadingCoefficientsBLQFactory.java +++ b/src/main/java/org/orekit/models/earth/displacement/OceanLoadingCoefficientsBLQFactory.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -285,7 +286,7 @@ public class OceanLoadingCoefficientsBLQFactory { data[i][2] = new double[4]; } - try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) { int lineNumber = 0; int dataLine = -1; diff --git a/src/main/java/org/orekit/models/earth/ionosphere/FieldNeQuickParameters.java b/src/main/java/org/orekit/models/earth/ionosphere/FieldNeQuickParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..4c296e7921f493cb8e85ed2cde014c56b0380bee --- /dev/null +++ b/src/main/java/org/orekit/models/earth/ionosphere/FieldNeQuickParameters.java @@ -0,0 +1,810 @@ +/* Copyright 2002-2019 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.models.earth.ionosphere; + +import org.hipparchus.Field; +import org.hipparchus.RealFieldElement; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.FieldSinCos; +import org.hipparchus.util.MathArrays; +import org.orekit.time.DateComponents; +import org.orekit.time.DateTimeComponents; +import org.orekit.time.TimeComponents; + +/** + * This class perfoms the computation of the parameters used by the NeQuick model. + * + * @author Bryan Cazabonne + * + * @see "European Union (2016). European GNSS (Galileo) Open Service-Ionospheric Correction + * Algorithm for Galileo Single Frequency Users. 1.2." + * + * @since 10.1 + */ +class FieldNeQuickParameters > { + + /** Solar zenith angle at day night transition, degrees. */ + private static final double X0 = 86.23292796211615; + + /** F2 layer maximum density. */ + private final T nmF2; + + /** F2 layer maximum density height [km]. */ + private final T hmF2; + + /** F1 layer maximum density height [km]. */ + private final T hmF1; + + /** E layer maximum density height [km]. */ + private final T hmE; + + /** F2 layer bottom thickness parameter [km]. */ + private final T b2Bot; + + /** F1 layer top thickness parameter [km]. */ + private final T b1Top; + + /** F1 layer bottom thickness parameter [km]. */ + private final T b1Bot; + + /** E layer top thickness parameter [km]. */ + private final T beTop; + + /** E layer bottom thickness parameter [km]. */ + private final T beBot; + + /** topside thickness parameter [km]. */ + private final T h0; + + /** Layer amplitudes. */ + private final T[] amplitudes; + + /** + * Build a new instance. + * @param field field of the elements + * @param dateTime current date time components + * @param f2 F2 coefficients used by the F2 layer + * @param fm3 Fm3 coefficients used by the F2 layer + * @param latitude latitude of a point along the integration path, in radians + * @param longitude longitude of a point along the integration path, in radians + * @param alpha effective ionisation level coefficients + * @param modipGrip modip grid + */ + FieldNeQuickParameters(final Field field, final DateTimeComponents dateTime, final double[][][] f2, + final double[][][] fm3, final T latitude, final T longitude, + final double[] alpha, final double[][] modipGrip) { + + // Zero + final T zero = field.getZero(); + + // MODIP in degrees + final T modip = computeMODIP(latitude, longitude, modipGrip); + // Effective ionisation level Az + final T az = computeAz(modip, alpha); + // Effective sunspot number (Eq. 19) + final T azr = FastMath.sqrt(az.subtract(63.7).multiply(1123.6).add(167273.0)).subtract(408.99); + // Date and Time components + final DateComponents date = dateTime.getDate(); + final TimeComponents time = dateTime.getTime(); + // Hours + final double hours = time.getSecondsInUTCDay() / 3600.0; + // Effective solar zenith angle in radians + final T xeff = computeEffectiveSolarAngle(date.getMonth(), hours, latitude, longitude); + + // Coefficients for F2 layer parameters + // Compute the array of interpolated coefficients for foF2 (Eq. 44) + final T[][] af2 = MathArrays.buildArray(field, 76, 13); + for (int j = 0; j < 76; j++) { + for (int k = 0; k < 13; k++ ) { + af2[j][k] = azr.multiply(0.01).negate().add(1.0).multiply(f2[0][j][k]).add(azr.multiply(0.01).multiply(f2[1][j][k])); + } + } + + // Compute the array of interpolated coefficients for M(3000)F2 (Eq. 46) + final T[][] am3 = MathArrays.buildArray(field, 49, 9); + for (int j = 0; j < 49; j++) { + for (int k = 0; k < 9; k++ ) { + am3[j][k] = azr.multiply(0.01).negate().add(1.0).multiply(fm3[0][j][k]).add(azr.multiply(0.01).multiply(fm3[1][j][k])); + } + } + + // E layer maximum density height in km (Eq. 78) + this.hmE = field.getZero().add(120.0); + // E layer critical frequency in MHz + final T foE = computefoE(date.getMonth(), az, xeff, latitude); + // E layer maximum density in 10^11 m-3 (Eq. 36) + final T nmE = foE.multiply(foE).multiply(0.124); + + // Time argument (Eq. 49) + final double t = FastMath.toRadians(15 * hours) - FastMath.PI; + // Compute Fourier time series for foF2 and M(3000)F2 + final T[] cf2 = computeCF2(field, af2, t); + final T[] cm3 = computeCm3(field, am3, t); + // F2 layer critical frequency in MHz + final T foF2 = computefoF2(field, modip, cf2, latitude, longitude); + // Maximum Usable Frequency factor + final T mF2 = computeMF2(field, modip, cm3, latitude, longitude); + // F2 layer maximum density in 10^11 m-3 + this.nmF2 = foF2.multiply(foF2).multiply(0.124); + // F2 layer maximum density height in km + this.hmF2 = computehmF2(field, foE, foF2, mF2); + + // F1 layer critical frequency in MHz + final T foF1 = computefoF1(field, foE, foF2); + // F1 layer maximum density in 10^11 m-3 + final T nmF1; + if (foF1.getReal() <= 0.0 && foE.getReal() > 2.0) { + final T foEpopf = foE.add(0.5); + nmF1 = foEpopf.multiply(foEpopf).multiply(0.124); + } else { + nmF1 = foF1.multiply(foF1).multiply(0.124); + } + // F1 layer maximum density height in km + this.hmF1 = hmF2.add(hmE).multiply(0.5); + + // Thickness parameters (Eq. 85 to 89) + final T a = clipExp(FastMath.log(foF2.multiply(foF2)).multiply(0.857).add(FastMath.log(mF2).multiply(2.02)).add(-3.467)).multiply(0.01); + this.b2Bot = nmF2.divide(a).multiply(0.385); + this.b1Top = hmF2.subtract(hmF1).multiply(0.3); + this.b1Bot = hmF1.subtract(hmE).multiply(0.5); + this.beTop = FastMath.max(b1Bot, zero.add(7.0)); + this.beBot = zero.add(5.0); + + // Layer amplitude coefficients + this.amplitudes = computeLayerAmplitudes(field, nmE, nmF1, foF1); + + // Topside thickness parameter + this.h0 = computeH0(field, date.getMonth(), azr); + } + + /** + * Get the F2 layer maximum density. + * @return nmF2 + */ + public T getNmF2() { + return nmF2; + } + + /** + * Get the F2 layer maximum density height. + * @return hmF2 in km + */ + public T getHmF2() { + return hmF2; + } + + /** + * Get the F1 layer maximum density height. + * @return hmF1 in km + */ + public T getHmF1() { + return hmF1; + } + + /** + * Get the E layer maximum density height. + * @return hmE in km + */ + public T getHmE() { + return hmE; + } + + /** + * Get the F2 layer thickness parameter (bottom). + * @return B2Bot in km + */ + public T getB2Bot() { + return b2Bot; + } + + /** + * Get the F1 layer thickness parameter (top). + * @return B1Top in km + */ + public T getB1Top() { + return b1Top; + } + + /** + * Get the F1 layer thickness parameter (bottom). + * @return B1Bot in km + */ + public T getB1Bot() { + return b1Bot; + } + + /** + * Get the E layer thickness parameter (bottom). + * @return BeBot in km + */ + public T getBEBot() { + return beBot; + } + + /** + * Get the E layer thickness parameter (top). + * @return BeTop in km + */ + public T getBETop() { + return beTop; + } + + /** + * Get the F2, F1 and E layer amplitudes. + *

+ * The resulting element is an array having the following form: + *

    + *
  • double[0] = A1 → F2 layer amplitude + *
  • double[1] = A2 → F1 layer amplitude + *
  • double[2] = A3 → E layer amplitude + *
+ * @return layer amplitudes + */ + public T[] getLayerAmplitudes() { + return amplitudes.clone(); + } + + /** + * Get the topside thickness parameter H0. + * @return H0 in km + */ + public T getH0() { + return h0; + } + + /** + * Computes the value of the modified dip latitude (MODIP) for the + * given latitude and longitude. + * + * @param lat receiver latitude, radians + * @param lon receiver longitude, radians + * @param stModip modip grid + * @return the MODIP in degrees + */ + private T computeMODIP(final T lat, final T lon, final double[][] stModip) { + + // Zero + final T zero = lat.getField().getZero(); + + // For the MODIP computation, the latitude and longitude have to be converted in degrees + final T latitude = FastMath.toDegrees(lat); + final T longitude = FastMath.toDegrees(lon); + + // Extreme cases + if (latitude.getReal() == 90.0 || latitude.getReal() == -90.0) { + return latitude; + } + + // Auxiliary parameter l (Eq. 6 to 8) + final int lF = (int) ((longitude.getReal() + 180) * 0.1); + int l = lF - 2; + if (l < 0) { + l += 36; + } else if (l > 33) { + l -= 36; + } + + // Auxiliary parameter a (Eq. 9 to 11) + final T a = latitude.add(90).multiply(0.2).add(1.0); + final T aF = FastMath.floor(a); + // Eq. 10 + final T x = a.subtract(aF); + // Eq. 11 + final int i = (int) aF.getReal() - 2; + + // zi coefficients (Eq. 12 and 13) + final T z1 = interpolate(zero.add(stModip[i + 1][l + 2]), zero.add(stModip[i + 2][l + 2]), + zero.add(stModip[i + 3][l + 2]), zero.add(stModip[i + 4][l + 2]), x); + final T z2 = interpolate(zero.add(stModip[i + 1][l + 3]), zero.add(stModip[i + 2][l + 3]), + zero.add(stModip[i + 3][l + 3]), zero.add(stModip[i + 4][l + 3]), x); + final T z3 = interpolate(zero.add(stModip[i + 1][l + 4]), zero.add(stModip[i + 2][l + 4]), + zero.add(stModip[i + 3][l + 4]), zero.add(stModip[i + 4][l + 4]), x); + final T z4 = interpolate(zero.add(stModip[i + 1][l + 5]), zero.add(stModip[i + 2][l + 5]), + zero.add(stModip[i + 3][l + 5]), zero.add(stModip[i + 4][l + 5]), x); + + // Auxiliary parameter b (Eq. 14 and 15) + final T b = longitude.add(180).multiply(0.1); + final T bF = FastMath.floor(b); + final T y = b.subtract(bF); + + // MODIP (Ref Eq. 16) + final T modip = interpolate(z1, z2, z3, z4, y); + + return modip; + } + + /** + * This method computes the effective ionisation level Az. + *

+ * This parameter is used for the computation of the Total Electron Content (TEC). + *

+ * @param modip modified dip latitude (MODIP) in degrees + * @param alpha effective ionisation level coefficients + * @return the ionisation level Az + */ + private T computeAz(final T modip, final double[] alpha) { + // Field + final Field field = modip.getField(); + // Zero + final T zero = field.getZero(); + // Particular condition (Eq. 17) + if (alpha[0] == 0.0 && alpha[1] == 0.0 && alpha[2] == 0.0) { + return zero.add(63.7); + } + // Az = a0 + modip * a1 + modip^2 * a2 (Eq. 18) + T az = modip.multiply(alpha[2]).add(alpha[1]).multiply(modip).add(alpha[0]); + // If Az < 0 -> Az = 0 + az = FastMath.max(zero, az); + // If Az > 400 -> Az = 400 + az = FastMath.min(zero.add(400.0), az); + return az; + } + + /** + * This method computes the effective solar zenith angle. + *

+ * The effective solar zenith angle is compute as a function of the + * solar zenith angle and the solar zenith angle at day night transition. + *

+ * @param month current month of the year + * @param hours universal time (hours) + * @param latitude in radians + * @param longitude in radians + * @return the effective solar zenith angle, radians + */ + private T computeEffectiveSolarAngle(final int month, + final double hours, + final T latitude, + final T longitude) { + // Zero + final T zero = latitude.getField().getZero(); + // Local time (Eq.4) + final T lt = longitude.divide(FastMath.toRadians(15.0)).add(hours); + // Day of year at the middle of the month (Eq. 20) + final double dy = 30.5 * month - 15.0; + // Time (Eq. 21) + final double t = dy + (18 - hours) / 24; + // Arguments am and al (Eq. 22 and 23) + final double am = FastMath.toRadians(0.9856 * t - 3.289); + final double al = am + FastMath.toRadians(1.916 * FastMath.sin(am) + 0.020 * FastMath.sin(2.0 * am) + 282.634); + // Sine and cosine of solar declination (Eq. 24 and 25) + final double sDec = 0.39782 * FastMath.sin(al); + final double cDec = FastMath.sqrt(1. - sDec * sDec); + // Solar zenith angle, deg (Eq. 26 and 27) + final FieldSinCos scLat = FastMath.sinCos(latitude); + final T coef = lt.negate().add(12.0).multiply(FastMath.PI / 12); + final T cZenith = scLat.sin().multiply(sDec).add(scLat.cos().multiply(cDec).multiply(FastMath.cos(coef))); + final T angle = FastMath.atan2(FastMath.sqrt(cZenith.multiply(cZenith).negate().add(1.0)), cZenith); + final T x = FastMath.toDegrees(angle); + // Effective solar zenith angle (Eq. 28) + final T xeff = join(clipExp(x.multiply(0.2).negate().add(20.0)).multiply(0.24).negate().add(90.0), x, zero.add(12.0), x.subtract(X0)); + return FastMath.toRadians(xeff); + } + + /** + * This method computes the E layer critical frequency at a given location. + * @param month current month + * @param az ffective ionisation level + * @param xeff effective solar zenith angle in radians + * @param latitude latitude in radians + * @return the E layer critical frequency at a given location in MHz + */ + private T computefoE(final int month, final T az, + final T xeff, final T latitude) { + // The latitude has to be converted in degrees + final T lat = FastMath.toDegrees(latitude); + // Square root of the effective ionisation level + final T sqAz = FastMath.sqrt(az); + // seas parameter (Eq. 30 to 32) + final int seas; + if (month == 1 || month == 2 || month == 11 || month == 12) { + seas = -1; + } else if (month == 3 || month == 4 || month == 9 || month == 10) { + seas = 0; + } else { + seas = 1; + } + // Latitudinal dependence (Eq. 33 and 34) + final T ee = clipExp(lat.multiply(0.3)); + final T seasp = ee.subtract(1.0).divide(ee.add(1.0)).multiply(seas); + // Critical frequency (Eq. 35) + final T coef = seasp.multiply(0.019).negate().add(1.112); + final T foE = FastMath.sqrt(coef .multiply(coef).multiply(sqAz).multiply(FastMath.cos(xeff).pow(0.6)).add(0.49)); + return foE; + } + + /** + * Computes the F2 layer height of maximum electron density. + * @param field field of the elements + * @param foE E layer layer critical frequency in MHz + * @param foF2 F2 layer layer critical frequency in MHz + * @param mF2 maximum usable frequency factor + * @return hmF2 in km + */ + private T computehmF2(final Field field, final T foE, final T foF2, final T mF2) { + // Zero + final T zero = field.getZero(); + // Ratio + final T fo = foF2.divide(foE); + final T ratio = join(fo, zero.add(1.75), zero.add(20.0), fo.subtract(1.75)); + + // deltaM parameter + T deltaM = zero.subtract(0.012); + if (foE.getReal() >= 1e-30) { + deltaM = deltaM.add(ratio.subtract(1.215).divide(0.253).reciprocal()); + } + + // hmF2 Eq. 80 + final T mF2Sq = mF2.multiply(mF2); + final T temp = FastMath.sqrt(mF2Sq.multiply(0.0196).add(1.0).divide(mF2Sq.multiply(1.2967).subtract(1.0))); + final T height = mF2.multiply(1490.0).multiply(temp).divide(mF2.add(deltaM)).subtract(176.0); + return height; + } + + /** + * Computes cf2 coefficients. + * @param field field of the elements + * @param af2 interpolated coefficients for foF2 + * @param t time argument + * @return the cf2 coefficients array + */ + private T[] computeCF2(final Field field, final T[][] af2, final double t) { + // Eq. 50 + final T[] cf2 = MathArrays.buildArray(field, 76); + for (int i = 0; i < cf2.length; i++) { + T sum = field.getZero(); + for (int k = 0; k < 6; k++) { + sum = sum.add(af2[i][2 * k + 1].multiply(FastMath.sin((k + 1) * t)).add(af2[i][2 * (k + 1)].multiply(FastMath.cos((k + 1) * t)))); + } + cf2[i] = af2[i][0].add(sum); + } + return cf2; + } + + /** + * Computes Cm3 coefficients. + * @param field field of the elements + * @param am3 interpolated coefficients for foF2 + * @param t time argument + * @return the Cm3 coefficients array + */ + private T[] computeCm3(final Field field, final T[][] am3, final double t) { + // Eq. 51 + final T[] cm3 = MathArrays.buildArray(field, 49); + for (int i = 0; i < cm3.length; i++) { + T sum = field.getZero(); + for (int k = 0; k < 4; k++) { + sum = sum.add(am3[i][2 * k + 1].multiply(FastMath.sin((k + 1) * t)).add(am3[i][2 * (k + 1)].multiply(FastMath.cos((k + 1) * t)))); + } + cm3[i] = am3[i][0].add(sum); + } + return cm3; + } + + /** + * This method computes the F2 layer critical frequency. + * @param field field of the elements + * @param modip modified DIP latitude, in degrees + * @param cf2 Fourier time series for foF2 + * @param latitude latitude in radians + * @param longitude longitude in radians + * @return the F2 layer critical frequency, MHz + */ + private T computefoF2(final Field field, final T modip, final T[] cf2, + final T latitude, final T longitude) { + + // One + final T one = field.getOne(); + + // Legendre grades (Eq. 63) + final int[] q = new int[] { + 12, 12, 9, 5, 2, 1, 1, 1, 1 + }; + + // Array for geographic terms + final T[] g = MathArrays.buildArray(field, cf2.length); + g[0] = one; + + // MODIP coefficients Eq. 57 + final T sinMODIP = FastMath.sin(FastMath.toRadians(modip)); + final T[] m = MathArrays.buildArray(field, 12); + m[0] = one; + for (int i = 1; i < q[0]; i++) { + m[i] = sinMODIP.multiply(m[i - 1]); + g[i] = m[i]; + } + + // Latitude coefficients (Eq. 58) + final T cosLat = FastMath.cos(latitude); + final T[] p = MathArrays.buildArray(field, 8); + p[0] = cosLat; + for (int n = 2; n < 9; n++) { + p[n - 1] = cosLat.multiply(p[n - 2]); + } + + // latitude and longitude terms + int index = 12; + for (int i = 1; i < q.length; i++) { + for (int j = 0; j < q[i]; j++) { + g[index++] = m[j].multiply(p[i - 1]).multiply(FastMath.cos(longitude.multiply(i))); + g[index++] = m[j].multiply(p[i - 1]).multiply(FastMath.sin(longitude.multiply(i))); + } + } + + // Compute foF2 by linear combination + final T frequency = one.linearCombination(g, cf2); + return frequency; + } + + /** + * This method computes the Maximum Usable Frequency factor. + * @param field field of the elements + * @param modip modified DIP latitude, in degrees + * @param cm3 Fourier time series for M(3000)F2 + * @param latitude latitude in radians + * @param longitude longitude in radians + * @return the Maximum Usable Frequency factor + */ + private T computeMF2(final Field field, final T modip, final T[] cm3, + final T latitude, final T longitude) { + + // One + final T one = field.getOne(); + // Legendre grades (Eq. 71) + final int[] r = new int[] { + 7, 8, 6, 3, 2, 1, 1 + }; + + // Array for geographic terms + final T[] g = MathArrays.buildArray(field, cm3.length); + g[0] = one; + + // MODIP coefficients Eq. 57 + final T sinMODIP = FastMath.sin(FastMath.toRadians(modip)); + final T[] m = MathArrays.buildArray(field, 12); + m[0] = one; + for (int i = 1; i < 12; i++) { + m[i] = sinMODIP.multiply(m[i - 1]); + if (i < 7) { + g[i] = m[i]; + } + } + + // Latitude coefficients (Eq. 58) + final T cosLat = FastMath.cos(latitude); + final T[] p = MathArrays.buildArray(field, 8); + p[0] = cosLat; + for (int n = 2; n < 9; n++) { + p[n - 1] = cosLat.multiply(p[n - 2]); + } + + // latitude and longitude terms + int index = 7; + for (int i = 1; i < r.length; i++) { + for (int j = 0; j < r[i]; j++) { + g[index++] = m[j].multiply(p[i - 1]).multiply(FastMath.cos(longitude.multiply(i))); + g[index++] = m[j].multiply(p[i - 1]).multiply(FastMath.sin(longitude.multiply(i))); + } + } + + // Compute m3000 by linear combination + final T m3000 = one.linearCombination(g, cm3); + return m3000; + } + + /** + * This method computes the F1 layer critical frequency. + *

+ * This computation performs the algorithm exposed in Annex F + * of the reference document. + *

+ * @param field field of the elements + * @param foE the E layer critical frequency, MHz + * @return the F1 layer critical frequency, MHz + * @param foF2 the F2 layer critical frequency, MHz + */ + private T computefoF1(final Field field, final T foE, final T foF2) { + final T zero = field.getZero(); + final T temp = join(foE.multiply(1.4), zero, zero.add(1000.0), foE.subtract(2.0)); + final T temp2 = join(zero, temp, zero.add(1000.0), foE.subtract(temp)); + final T value = join(temp2, temp2.multiply(0.85), zero.add(60.0), foF2.multiply(0.85).subtract(temp2)); + if (value.getReal() < 1.0E-6) { + return zero; + } else { + return value; + } + } + + /** + * This method allows the computation of the F2, F1 and E layer amplitudes. + *

+ * The resulting element is an array having the following form: + *

    + *
  • double[0] = A1 → F2 layer amplitude + *
  • double[1] = A2 → F1 layer amplitude + *
  • double[2] = A3 → E layer amplitude + *
+ *

+ * @param field field of the elements + * @param nmE E layer maximum density in 10^11 m-3 + * @param nmF1 F1 layer maximum density in 10^11 m-3 + * @param foF1 F1 layer critical frequency in MHz + * @return a three components array containing the layer amplitudes + */ + private T[] computeLayerAmplitudes(final Field field, final T nmE, final T nmF1, final T foF1) { + // Zero + final T zero = field.getZero(); + + // Initialize array + final T[] amplitude = MathArrays.buildArray(field, 3); + + // F2 layer amplitude (Eq. 90) + final T a1 = nmF2.multiply(4.0); + amplitude[0] = a1; + + // F1 and E layer amplitudes (Eq. 91 to 98) + if (foF1.getReal() < 0.5) { + amplitude[1] = zero; + amplitude[2] = nmE.subtract(epst(a1, hmF2, b2Bot, hmE)).multiply(4.0); + } else { + T a2a = zero; + T a3a = nmE.multiply(4.0); + for (int i = 0; i < 5; i++) { + a2a = nmF1.subtract(epst(a1, hmF2, b2Bot, hmF1)).subtract(epst(a3a, hmE, beTop, hmF1)).multiply(4.0); + a2a = join(a2a, nmF1.multiply(0.8), field.getOne(), a2a.subtract(nmF1.multiply(0.8))); + a3a = nmE.subtract(epst(a2a, hmF1, b1Bot, hmE)).subtract(epst(a1, hmF2, b2Bot, hmE)).multiply(4.0); + } + amplitude[1] = a2a; + amplitude[2] = join(a3a, zero.add(0.05), zero.add(60.0), a3a.subtract(0.005)); + } + + return amplitude; + } + + /** + * This method computes the topside thickness parameter H0. + * + * @param field field of the elements + * @param month current month + * @param azr effective sunspot number + * @return H0 in km + */ + private T computeH0(final Field field, final int month, final T azr) { + + // One + final T one = field.getOne(); + + // Auxiliary parameter ka (Eq. 99 and 100) + final T ka; + if (month > 3 && month < 10) { + // month = 4,5,6,7,8,9 + ka = azr.multiply(0.014).add(hmF2.multiply(0.008)).negate().add(6.705); + } else { + // month = 1,2,3,10,11,12 + final T ratio = hmF2.divide(b2Bot); + ka = ratio.multiply(ratio).multiply(0.097).add(nmF2.multiply(0.153)).add(-7.77); + } + + // Auxiliary parameter kb (Eq. 101 and 102) + T kb = join(ka, one.multiply(2.0), one, ka.subtract(2.0)); + kb = join(one.multiply(8.0), kb, one, kb.subtract(8.0)); + + // Auxiliary parameter Ha (Eq. 103) + final T hA = kb.multiply(b2Bot); + + // Auxiliary parameters x and v (Eq. 104 and 105) + final T x = hA.subtract(150.0).multiply(0.01); + final T v = x.multiply(0.041163).subtract(0.183981).multiply(x).add(1.424472); + + // Topside thickness parameter (Eq. 106) + final T h = hA.divide(v); + return h; + } + + /** + * A clipped exponential function. + *

+ * This function, describe in section F.2.12.2 of the reference document, is + * recommanded for the computation of exponential values. + *

+ * @param power power for exponential function + * @return clipped exponential value + */ + private T clipExp(final T power) { + final T zero = power.getField().getZero(); + if (power.getReal() > 80.0) { + return zero.add(5.5406E34); + } else if (power.getReal() < -80) { + return zero.add(1.8049E-35); + } else { + return FastMath.exp(power); + } + } + + /** + * This method provides a third order interpolation function + * as recommended in the reference document (Ref Eq. 128 to Eq. 138) + * + * @param z1 z1 coefficient + * @param z2 z2 coefficient + * @param z3 z3 coefficient + * @param z4 z4 coefficient + * @param x position + * @return a third order interpolation + */ + private T interpolate(final T z1, final T z2, + final T z3, final T z4, + final T x) { + + if (FastMath.abs(2.0 * x.getReal()) < 1e-10) { + return z2; + } + + final T delta = x.multiply(2.0).subtract(1.0); + final T g1 = z3.add(z2); + final T g2 = z3.subtract(z2); + final T g3 = z4.add(z1); + final T g4 = z4.subtract(z1).divide(3.0); + final T a0 = g1.multiply(9.0).subtract(g3); + final T a1 = g2.multiply(9.0).subtract(g4); + final T a2 = g3.subtract(g1); + final T a3 = g4.subtract(g2); + final T zx = delta.multiply(a3).add(a2).multiply(delta).add(a1).multiply(delta).add(a0).multiply(0.0625); + + return zx; + } + + /** + * Allows smooth joining of functions f1 and f2 + * (i.e. continuous first derivatives) at origin. + *

+ * This function, describe in section F.2.12.1 of the reference document, is + * recommanded for computational efficiency. + *

+ * @param dF1 first function + * @param dF2 second function + * @param dA width of transition region + * @param dX x value + * @return the computed value + */ + private T join(final T dF1, final T dF2, + final T dA, final T dX) { + final T ee = clipExp(dA.multiply(dX)); + return dF1.multiply(ee).add(dF2).divide(ee.add(1.0)); + } + + /** + * The Epstein function. + *

+ * This function, describe in section 2.5.1 of the reference document, is used + * as a basis analytical function in NeQuick for the construction of the ionospheric layers. + *

+ * @param x x parameter + * @param y y parameter + * @param z z parameter + * @param w w parameter + * @return value of the epstein function + */ + private T epst(final T x, final T y, + final T z, final T w) { + final T ex = clipExp(w.subtract(y).divide(z)); + final T opex = ex.add(1.0); + final T epst = x.multiply(ex).divide(opex.multiply(opex)); + return epst; + } + +} diff --git a/src/main/java/org/orekit/models/earth/ionosphere/GlobalIonosphereMapModel.java b/src/main/java/org/orekit/models/earth/ionosphere/GlobalIonosphereMapModel.java index b04eaca231f82ae3b17d63893d8af9faa7bd0698..cd0c467543e21531273d46821c98961b2e1dea17 100644 --- a/src/main/java/org/orekit/models/earth/ionosphere/GlobalIonosphereMapModel.java +++ b/src/main/java/org/orekit/models/earth/ionosphere/GlobalIonosphereMapModel.java @@ -499,7 +499,7 @@ public class GlobalIonosphereMapModel implements IonosphericModel { double[] longitudes = null; AbsoluteDate firstEpoch = null; AbsoluteDate lastEpoch = null; - AbsoluteDate epoch = null; + AbsoluteDate epoch = firstEpoch; ArrayList values = new ArrayList<>(); for (line = br.readLine(); line != null; line = br.readLine()) { @@ -545,6 +545,14 @@ public class GlobalIonosphereMapModel implements IonosphericModel { longitudes = parseCoordinate(line); break; case "END OF HEADER" : + // Check that latitude and longitude bondaries were found + if (latitudes == null || longitudes == null) { + throw new OrekitException(OrekitMessages.NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER, supportedNames); + } + // Check that first and last epochs were found + if (firstEpoch == null || lastEpoch == null) { + throw new OrekitException(OrekitMessages.NO_EPOCH_IN_IONEX_HEADER, supportedNames); + } // At the end of the header, we build the IONEXHeader object header = new IONEXHeader(firstEpoch, lastEpoch, interval, nbOfMaps, baseRadius, hIon, mappingF); diff --git a/src/main/java/org/orekit/models/earth/ionosphere/KlobucharIonoCoefficientsLoader.java b/src/main/java/org/orekit/models/earth/ionosphere/KlobucharIonoCoefficientsLoader.java index 90e58259118fbcb42f5077101b4ecd7d424e587d..5a5f1275e5bdba6108cb024aaec0fd94823b58d0 100644 --- a/src/main/java/org/orekit/models/earth/ionosphere/KlobucharIonoCoefficientsLoader.java +++ b/src/main/java/org/orekit/models/earth/ionosphere/KlobucharIonoCoefficientsLoader.java @@ -21,6 +21,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import org.orekit.data.DataLoader; @@ -153,7 +154,7 @@ public class KlobucharIonoCoefficientsLoader implements DataLoader { throws IOException, ParseException { // Open stream and parse data - final BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader br = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; final String splitter = "\\s+"; for (String line = br.readLine(); line != null; line = br.readLine()) { diff --git a/src/main/java/org/orekit/models/earth/ionosphere/NeQuickModel.java b/src/main/java/org/orekit/models/earth/ionosphere/NeQuickModel.java new file mode 100644 index 0000000000000000000000000000000000000000..8db8374b67d3d6dce45156b30c3234eea86ebcf5 --- /dev/null +++ b/src/main/java/org/orekit/models/earth/ionosphere/NeQuickModel.java @@ -0,0 +1,1552 @@ +/* Copyright 2002-2019 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.models.earth.ionosphere; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.List; + +import org.hipparchus.Field; +import org.hipparchus.RealFieldElement; +import org.hipparchus.util.FastMath; +import org.hipparchus.util.FieldSinCos; +import org.hipparchus.util.MathArrays; +import org.hipparchus.util.SinCos; +import org.orekit.bodies.BodyShape; +import org.orekit.bodies.FieldGeodeticPoint; +import org.orekit.bodies.GeodeticPoint; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.frames.TopocentricFrame; +import org.orekit.propagation.FieldSpacecraftState; +import org.orekit.propagation.SpacecraftState; +import org.orekit.time.AbsoluteDate; +import org.orekit.time.DateComponents; +import org.orekit.time.DateTimeComponents; +import org.orekit.time.FieldAbsoluteDate; +import org.orekit.time.TimeScalesFactory; +import org.orekit.utils.ParameterDriver; +import org.orekit.utils.TimeStampedFieldPVCoordinates; +import org.orekit.utils.TimeStampedPVCoordinates; + +/** + * NeQuick ionospheric delay model. + * + * @author Bryan Cazabonne + * + * @see "European Union (2016). European GNSS (Galileo) Open Service-Ionospheric Correction + * Algorithm for Galileo Single Frequency Users. 1.2." + * + * @since 10.1 + */ +public class NeQuickModel implements IonosphericModel { + + /** NeQuick resources base directory. */ + private static final String NEQUICK_BASE = "/assets/org/orekit/nequick/"; + + /** Serializable UID. */ + private static final long serialVersionUID = 201928051L; + + /** Splitter for MODIP and CCIR files. */ + private static final String SPLITER = "\\s+"; + + /** Mean Earth radius in m (Ref Table 2.5.2). */ + private static final double RE = 6371200.0; + + /** Meters to kilometers converter. */ + private static final double M_TO_KM = 0.001; + + /** Factor for the electron density computation. */ + private static final double DENSITY_FACTOR = 1.0e11; + + /** Factor for the path delay computation. */ + private static final double DELAY_FACTOR = 40.3e16; + + /** The three ionospheric coefficients broadcast in the Galileo navigation message. */ + private final double[] alpha; + + /** MODIP grid. */ + private final double[][] stModip; + + /** Month used for loading CCIR coefficients. */ + private int month; + + /** F2 coefficients used by the F2 layer. */ + private double[][][] f2; + + /** Fm3 coefficients used by the F2 layer. */ + private double[][][] fm3; + + /** + * Build a new instance. + * @param alpha effective ionisation level coefficients + */ + public NeQuickModel(final double[] alpha) { + // F2 layer values + this.month = 0; + this.f2 = null; + this.fm3 = null; + // Read modip grid + final MODIPLoader parser = new MODIPLoader(); + parser.loadMODIPGrid(); + this.stModip = parser.getMODIPGrid(); + // Ionisation level coefficients + this.alpha = alpha.clone(); + } + + @Override + public double pathDelay(final SpacecraftState state, final TopocentricFrame baseFrame, + final double frequency, final double[] parameters) { + // Point + final GeodeticPoint recPoint = baseFrame.getPoint(); + // Date + final AbsoluteDate date = state.getDate(); + + // Reference body shape + final BodyShape ellipsoid = baseFrame.getParentShape(); + // Satellite geodetic coordinates + final TimeStampedPVCoordinates pv = state.getPVCoordinates(ellipsoid.getBodyFrame()); + final GeodeticPoint satPoint = ellipsoid.transform(pv.getPosition(), ellipsoid.getBodyFrame(), state.getDate()); + + // Total Electron Content + final double tec = stec(date, recPoint, satPoint); + + // Ionospheric delay + final double factor = DELAY_FACTOR / (frequency * frequency); + return factor * tec; + } + + @Override + public > T pathDelay(final FieldSpacecraftState state, final TopocentricFrame baseFrame, + final double frequency, final T[] parameters) { + // Date + final FieldAbsoluteDate date = state.getDate(); + // Point + final FieldGeodeticPoint recPoint = baseFrame.getPoint(date.getField()); + + + // Reference body shape + final BodyShape ellipsoid = baseFrame.getParentShape(); + // Satellite geodetic coordinates + final TimeStampedFieldPVCoordinates pv = state.getPVCoordinates(ellipsoid.getBodyFrame()); + final FieldGeodeticPoint satPoint = ellipsoid.transform(pv.getPosition(), ellipsoid.getBodyFrame(), state.getDate()); + + // Total Electron Content + final T tec = stec(date, recPoint, satPoint); + + // Ionospheric delay + final double factor = DELAY_FACTOR / (frequency * frequency); + return tec.multiply(factor); + } + + @Override + public List getParametersDrivers() { + return Collections.emptyList(); + } + + /** + * This method allows the computation of the Stant Total Electron Content (STEC). + *

+ * This method follows the Gauss algorithm exposed in section 2.5.8.2.8 of + * the reference document. + *

+ * @param date current date + * @param recP receiver position + * @param satP satellite position + * @return the STEC in TECUnits + */ + public double stec(final AbsoluteDate date, final GeodeticPoint recP, final GeodeticPoint satP) { + + // Ray-perigee parameters + final Ray ray = new Ray(recP, satP); + + // Load the correct CCIR file + final DateTimeComponents dateTime = date.getComponents(TimeScalesFactory.getUTC()); + loadsIfNeeded(dateTime.getDate()); + + // Tolerance for the integration accuracy. Defined inside the reference document, section 2.5.8.1. + final double h1 = recP.getAltitude(); + final double tolerance; + if (h1 < 1000000.0) { + tolerance = 0.001; + } else { + tolerance = 0.01; + } + + // Integration + int n = 8; + final Segment seg1 = new Segment(n, ray); + double gn1 = stecIntegration(seg1, dateTime); + n *= 2; + final Segment seg2 = new Segment(n, ray); + double gn2 = stecIntegration(seg2, dateTime); + + int count = 1; + while (FastMath.abs(gn2 - gn1) > tolerance * FastMath.abs(gn1) && count < 20) { + gn1 = gn2; + n *= 2; + final Segment seg = new Segment(n, ray); + gn2 = stecIntegration(seg, dateTime); + count += 1; + } + + // If count > 20 the integration did not converge + if (count == 20) { + throw new OrekitException(OrekitMessages.STEC_INTEGRATION_DID_NOT_CONVERGE); + } + + // Eq. 202 + return (gn2 + ((gn2 - gn1) / 15.0)) * 1.0e-16; + } + + /** + * This method allows the computation of the Stant Total Electron Content (STEC). + *

+ * This method follows the Gauss algorithm exposed in section 2.5.8.2.8 of + * the reference document. + *

+ * @param type of the elements + * @param date current date + * @param recP receiver position + * @param satP satellite position + * @return the STEC in TECUnits + */ + public > T stec(final FieldAbsoluteDate date, + final FieldGeodeticPoint recP, + final FieldGeodeticPoint satP) { + + // Field + final Field field = date.getField(); + + // Ray-perigee parameters + final FieldRay ray = new FieldRay<>(field, recP, satP); + + // Load the correct CCIR file + final DateTimeComponents dateTime = date.getComponents(TimeScalesFactory.getUTC()); + loadsIfNeeded(dateTime.getDate()); + + // Tolerance for the integration accuracy. Defined inside the reference document, section 2.5.8.1. + final T h1 = recP.getAltitude(); + final double tolerance; + if (h1.getReal() < 1000000.0) { + tolerance = 0.001; + } else { + tolerance = 0.01; + } + + // Integration + int n = 8; + final FieldSegment seg1 = new FieldSegment<>(field, n, ray); + T gn1 = stecIntegration(field, seg1, dateTime); + n *= 2; + final FieldSegment seg2 = new FieldSegment<>(field, n, ray); + T gn2 = stecIntegration(field, seg2, dateTime); + + int count = 1; + while (FastMath.abs(gn2.subtract(gn1)).getReal() > FastMath.abs(gn1).multiply(tolerance).getReal() && count < 20) { + gn1 = gn2; + n *= 2; + final FieldSegment seg = new FieldSegment<>(field, n, ray); + gn2 = stecIntegration(field, seg, dateTime); + count += 1; + } + + // If count > 20 the integration did not converge + if (count == 20) { + throw new OrekitException(OrekitMessages.STEC_INTEGRATION_DID_NOT_CONVERGE); + } + + // Eq. 202 + return gn2.add(gn2.subtract(gn1).divide(15.0)).multiply(1.0e-16); + } + + /** + * This method perfoms the STEC integration. + * @param seg coordinates along the integration path + * @param dateTime current date and time componentns + * @return result of the integration + */ + private double stecIntegration(final Segment seg, final DateTimeComponents dateTime) { + // Integration points + final double[] heightS = seg.getHeights(); + final double[] latitudeS = seg.getLatitudes(); + final double[] longitudeS = seg.getLongitudes(); + + // Compute electron density + double density = 0.0; + for (int i = 0; i < heightS.length; i++) { + final NeQuickParameters parameters = new NeQuickParameters(dateTime, f2, fm3, + latitudeS[i], longitudeS[i], + alpha, stModip); + density += electronDensity(heightS[i], parameters); + } + + return 0.5 * seg.getInterval() * density; + } + + /** + * This method perfoms the STEC integration. + * @param type of the elements + * @param field field of the elements + * @param seg coordinates along the integration path + * @param dateTime current date and time componentns + * @return result of the integration + */ + private > T stecIntegration(final Field field, + final FieldSegment seg, + final DateTimeComponents dateTime) { + // Integration points + final T[] heightS = seg.getHeights(); + final T[] latitudeS = seg.getLatitudes(); + final T[] longitudeS = seg.getLongitudes(); + + // Compute electron density + T density = field.getZero(); + for (int i = 0; i < heightS.length; i++) { + final FieldNeQuickParameters parameters = new FieldNeQuickParameters<>(field, dateTime, f2, fm3, + latitudeS[i], longitudeS[i], + alpha, stModip); + density = density.add(electronDensity(field, heightS[i], parameters)); + } + + return seg.getInterval().multiply(density).multiply(0.5); + } + + /** + * Computes the electron density at a given height. + * @param h height in m + * @param parameters NeQuick model parameters + * @return electron density [m^-3] + */ + private double electronDensity(final double h, final NeQuickParameters parameters) { + // Convert height in kilometers + final double hInKm = h * M_TO_KM; + // Electron density + final double n; + if (hInKm <= parameters.getHmF2()) { + n = bottomElectronDensity(hInKm, parameters); + } else { + n = topElectronDensity(hInKm, parameters); + } + return n; + } + + /** + * Computes the electron density at a given height. + * @param type of the elements + * @param field field of the elements + * @param h height in m + * @param parameters NeQuick model parameters + * @return electron density [m^-3] + */ + private > T electronDensity(final Field field, + final T h, + final FieldNeQuickParameters parameters) { + // Convert height in kilometers + final T hInKm = h.multiply(M_TO_KM); + // Electron density + final T n; + if (hInKm.getReal() <= parameters.getHmF2().getReal()) { + n = bottomElectronDensity(field, hInKm, parameters); + } else { + n = topElectronDensity(field, hInKm, parameters); + } + return n; + } + + /** + * Computes the electron density of the bottomside. + * @param h height in km + * @param parameters NeQuick model parameters + * @return the electron density N in m-3 + */ + private double bottomElectronDensity(final double h, final NeQuickParameters parameters) { + + // Select the relevant B parameter for the current height (Eq. 109 and 110) + final double be; + if (h > parameters.getHmE()) { + be = parameters.getBETop(); + } else { + be = parameters.getBEBot(); + } + final double bf1; + if (h > parameters.getHmF1()) { + bf1 = parameters.getB1Top(); + } else { + bf1 = parameters.getB1Bot(); + } + final double bf2 = parameters.getB2Bot(); + + // Useful array of constants + final double[] ct = new double[] { + 1.0 / bf2, 1.0 / bf1, 1.0 / be + }; + + // Compute the exponential argument for each layer (Eq. 111 to 113) + // If h < 100km we use h = 100km as recommended in the reference document + final double hTemp = FastMath.max(100.0, h); + final double exp = clipExp(10.0 / (1.0 + FastMath.abs(hTemp - parameters.getHmF2()))); + final double[] arguments = new double[3]; + arguments[0] = (hTemp - parameters.getHmF2()) / bf2; + arguments[1] = ((hTemp - parameters.getHmF1()) / bf1) * exp; + arguments[2] = ((hTemp - parameters.getHmE()) / be) * exp; + + // S coefficients + final double[] s = new double[3]; + // Array of corrective terms + final double[] ds = new double[3]; + + // Layer amplitudes + final double[] amplitudes = parameters.getLayerAmplitudes(); + + // Fill arrays (Eq. 114 to 118) + for (int i = 0; i < 3; i++) { + if (FastMath.abs(arguments[i]) > 25.0) { + s[i] = 0.0; + ds[i] = 0.0; + } else { + final double expA = clipExp(arguments[i]); + final double opExpA = 1.0 + expA; + s[i] = amplitudes[i] * (expA / (opExpA * opExpA)); + ds[i] = ct[i] * ((1.0 - expA) / (1.0 + expA)); + } + } + + // Electron density + final double aNo = MathArrays.linearCombination(s[0], 1.0, s[1], 1.0, s[2], 1.0); + if (h >= 100) { + return aNo * DENSITY_FACTOR; + } else { + // Chapman parameters (Eq. 119 and 120) + final double bc = 1.0 - 10.0 * (MathArrays.linearCombination(s[0], ds[0], s[1], ds[1], s[2], ds[2]) / aNo); + final double z = 0.1 * (h - 100.0); + // Electron density (Eq. 121) + return aNo * clipExp(1.0 - bc * z - clipExp(-z)) * DENSITY_FACTOR; + } + } + + /** + * Computes the electron density of the bottomside. + * @param type of the elements + * @param field field of the elements + * @param h height in km + * @param parameters NeQuick model parameters + * @return the electron density N in m-3 + */ + private > T bottomElectronDensity(final Field field, + final T h, + final FieldNeQuickParameters parameters) { + + // Zero and One + final T zero = field.getZero(); + final T one = field.getOne(); + + // Select the relevant B parameter for the current height (Eq. 109 and 110) + final T be; + if (h.getReal() > parameters.getHmE().getReal()) { + be = parameters.getBETop(); + } else { + be = parameters.getBEBot(); + } + final T bf1; + if (h.getReal() > parameters.getHmF1().getReal()) { + bf1 = parameters.getB1Top(); + } else { + bf1 = parameters.getB1Bot(); + } + final T bf2 = parameters.getB2Bot(); + + // Useful array of constants + final T[] ct = MathArrays.buildArray(field, 3); + ct[0] = bf2.reciprocal(); + ct[1] = bf1.reciprocal(); + ct[2] = be.reciprocal(); + + // Compute the exponential argument for each layer (Eq. 111 to 113) + // If h < 100km we use h = 100km as recommended in the reference document + final T hTemp = FastMath.max(zero.add(100.0), h); + final T exp = clipExp(field, FastMath.abs(hTemp.subtract(parameters.getHmF2())).add(1.0).divide(10.0).reciprocal()); + final T[] arguments = MathArrays.buildArray(field, 3); + arguments[0] = hTemp.subtract(parameters.getHmF2()).divide(bf2); + arguments[1] = hTemp.subtract(parameters.getHmF1()).divide(bf1).multiply(exp); + arguments[2] = hTemp.subtract(parameters.getHmE()).divide(be).multiply(exp); + + // S coefficients + final T[] s = MathArrays.buildArray(field, 3); + // Array of corrective terms + final T[] ds = MathArrays.buildArray(field, 3); + + // Layer amplitudes + final T[] amplitudes = parameters.getLayerAmplitudes(); + + // Fill arrays (Eq. 114 to 118) + for (int i = 0; i < 3; i++) { + if (FastMath.abs(arguments[i]).getReal() > 25.0) { + s[i] = zero; + ds[i] = zero; + } else { + final T expA = clipExp(field, arguments[i]); + final T opExpA = expA.add(1.0); + s[i] = amplitudes[i].multiply(expA.divide(opExpA.multiply(opExpA))); + ds[i] = ct[i].multiply(expA.negate().add(1.0).divide(expA.add(1.0))); + } + } + + // Electron density + final T aNo = one.linearCombination(s[0], one, s[1], one, s[2], one); + if (h.getReal() >= 100) { + return aNo.multiply(DENSITY_FACTOR); + } else { + // Chapman parameters (Eq. 119 and 120) + final T bc = s[0].multiply(ds[0]).add(one.linearCombination(s[0], ds[0], s[1], ds[1], s[2], ds[2])).divide(aNo).multiply(10.0).negate().add(1.0); + final T z = h.subtract(100.0).multiply(0.1); + // Electron density (Eq. 121) + return aNo.multiply(clipExp(field, bc.multiply(z).add(clipExp(field, z.negate())).negate().add(1.0))).multiply(DENSITY_FACTOR); + } + } + + /** + * Computes the electron density of the topside. + * @param h height in km + * @param parameters NeQuick model parameters + * @return the electron density N in m-3 + */ + private double topElectronDensity(final double h, final NeQuickParameters parameters) { + + // Constant parameters (Eq. 122 and 123) + final double g = 0.125; + final double r = 100.0; + + // Arguments deltaH and z (Eq. 124 and 125) + final double deltaH = h - parameters.getHmF2(); + final double z = deltaH / (parameters.getH0() * (1.0 + (r * g * deltaH) / (r * parameters.getH0() + g * deltaH))); + + // Exponential (Eq. 126) + final double ee = clipExp(z); + + // Electron density (Eq. 127) + if (ee > 1.0e11) { + return (4.0 * parameters.getNmF2() / ee) * DENSITY_FACTOR; + } else { + final double opExpZ = 1.0 + ee; + return ((4.0 * parameters.getNmF2() * ee) / (opExpZ * opExpZ)) * DENSITY_FACTOR; + } + } + + /** + * Computes the electron density of the topside. + * @param type of the elements + * @param field field of the elements + * @param h height in km + * @param parameters NeQuick model parameters + * @return the electron density N in m-3 + */ + private > T topElectronDensity(final Field field, + final T h, + final FieldNeQuickParameters parameters) { + + // Constant parameters (Eq. 122 and 123) + final double g = 0.125; + final double r = 100.0; + + // Arguments deltaH and z (Eq. 124 and 125) + final T deltaH = h.subtract(parameters.getHmF2()); + final T z = deltaH.divide(parameters.getH0().multiply(deltaH.multiply(r).multiply(g).divide(parameters.getH0().multiply(r).add(deltaH.multiply(g))).add(1.0))); + + // Exponential (Eq. 126) + final T ee = clipExp(field, z); + + // Electron density (Eq. 127) + if (ee.getReal() > 1.0e11) { + return parameters.getNmF2().multiply(4.0).divide(ee).multiply(DENSITY_FACTOR); + } else { + final T opExpZ = ee.add(field.getOne()); + return parameters.getNmF2().multiply(4.0).multiply(ee).divide(opExpZ.multiply(opExpZ)).multiply(DENSITY_FACTOR); + } + } + + /** + * Lazy loading of CCIR data. + * @param date current date components + */ + private void loadsIfNeeded(final DateComponents date) { + + // Current month + final int currentMonth = date.getMonth(); + + // Check if date have changed or if f2 and fm3 arrays are null + if (currentMonth != month || f2 == null || fm3 == null) { + this.month = currentMonth; + + // Read file + final CCIRLoader loader = new CCIRLoader(); + loader.loadCCIRCoefficients(date); + + // Update arrays + this.f2 = loader.getF2(); + this.fm3 = loader.getFm3(); + } + } + + /** + * A clipped exponential function. + *

+ * This function, describe in section F.2.12.2 of the reference document, is + * recommanded for the computation of exponential values. + *

+ * @param power power for exponential function + * @return clipped exponential value + */ + private double clipExp(final double power) { + if (power > 80.0) { + return 5.5406E34; + } else if (power < -80) { + return 1.8049E-35; + } else { + return FastMath.exp(power); + } + } + + /** + * A clipped exponential function. + *

+ * This function, describe in section F.2.12.2 of the reference document, is + * recommanded for the computation of exponential values. + *

+ * @param type of the elements + * @param field field of the elements + * @param power power for exponential function + * @return clipped exponential value + */ + private > T clipExp(final Field field, final T power) { + final T zero = field.getZero(); + if (power.getReal() > 80.0) { + return zero.add(5.5406E34); + } else if (power.getReal() < -80) { + return zero.add(1.8049E-35); + } else { + return FastMath.exp(power); + } + } + + /** Get a data stream. + * @param name file name of the resource stream + * @return stream + */ + private static InputStream getStream(final String name) { + return NeQuickModel.class.getResourceAsStream(name); + } + + /** + * Parser for Modified Dip Latitude (MODIP) grid file. + *

+ * The MODIP grid allows to estimate MODIP μ [deg] at a given point (φ,λ) + * by interpolation of the relevant values contained in the support file. + *

+ * The file contains the values of MODIP (expressed in degrees) on a geocentric grid + * from 90°S to 90°N with a 5-degree step in latitude and from 180°W to 180°E with a + * 10-degree in longitude. + *

+ */ + private static class MODIPLoader { + + /** Supported name for MODIP grid. */ + private static final String SUPPORTED_NAME = NEQUICK_BASE + "modip.txt"; + + /** MODIP grid. */ + private double[][] grid; + + /** + * Build a new instance. + */ + MODIPLoader() { + this.grid = null; + } + + /** Returns the MODIP grid array. + * @return the MODIP grid array + */ + public double[][] getMODIPGrid() { + return grid.clone(); + } + + /** + * Load the data using supported names. + */ + public void loadMODIPGrid() { + try (InputStream in = getStream(SUPPORTED_NAME)) { + loadData(in, SUPPORTED_NAME); + } catch (IOException e) { + throw new OrekitException(OrekitMessages.INTERNAL_ERROR, e); + } + + // Throw an exception if MODIP grid was not loaded properly + if (grid == null) { + throw new OrekitException(OrekitMessages.MODIP_GRID_NOT_LOADED, SUPPORTED_NAME); + } + } + + /** + * Load data from a stream. + * @param input input stream + * @param name name of the file + * @throws IOException if data can't be read + */ + public void loadData(final InputStream input, final String name) + throws IOException { + + // Grid size + final int size = 39; + + // Initialize array + final double[][] array = new double[size][size]; + + // Open stream and parse data + int lineNumber = 0; + String line = null; + try (InputStreamReader isr = new InputStreamReader(input, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr)) { + + for (line = br.readLine(); line != null; line = br.readLine()) { + ++lineNumber; + line = line.trim(); + + // Read grid data + if (line.length() > 0) { + final String[] modip_line = line.split(SPLITER); + for (int column = 0; column < modip_line.length; column++) { + array[lineNumber - 1][column] = Double.valueOf(modip_line[column]); + } + } + + } + + } catch (NumberFormatException nfe) { + throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, + lineNumber, name, line); + } + + // Close the stream after reading + input.close(); + + // Clone parsed grid + grid = array.clone(); + + } + } + + /** + * Parser for CCIR files. + *

+ * Numerical grid maps which describe the regular variation of the ionosphere. + * They are used to derive other variables such as critical frequencies and transmission factors. + *

+ * The coefficients correspond to low and high solar activity conditions. + *

+ * The CCIR file naming convention is ccirXX.asc where each XX means month + 10. + *

+ * Coefficients are store into tow arrays, F2 and Fm3. F2 coefficients are used for the computation + * of the F2 layer critical frequency. Fm3 for the computation of the F2 layer maximum usable frequency factor. + * The size of these two arrays is fixed and discussed into the section 2.5.3.2 + * of the reference document. + *

+ */ + private static class CCIRLoader { + + /** Default supported files name pattern. */ + public static final String DEFAULT_SUPPORTED_NAME = "ccir**.asc"; + + /** Total number of F2 coefficients contained in the file. */ + private static final int NUMBER_F2_COEFFICIENTS = 1976; + + /** Rows number for F2 and Fm3 arrays. */ + private static final int ROWS = 2; + + /** Columns number for F2 array. */ + private static final int TOTAL_COLUMNS_F2 = 76; + + /** Columns number for Fm3 array. */ + private static final int TOTAL_COLUMNS_FM3 = 49; + + /** Depth of F2 array. */ + private static final int DEPTH_F2 = 13; + + /** Depth of Fm3 array. */ + private static final int DEPTH_FM3 = 9; + + /** Regular expression for supported file name. */ + private String supportedName; + + /** F2 coefficients used for the computation of the F2 layer critical frequency. */ + private double[][][] f2Loader; + + /** Fm3 coefficients used for the computation of the F2 layer maximum usable frequency factor. */ + private double[][][] fm3Loader; + + /** + * Build a new instance. + */ + CCIRLoader() { + this.supportedName = DEFAULT_SUPPORTED_NAME; + this.f2Loader = null; + this.fm3Loader = null; + } + + /** + * Get the F2 coefficients used for the computation of the F2 layer critical frequency. + * @return the F2 coefficients + */ + public double[][][] getF2() { + return f2Loader.clone(); + } + + /** + * Get the Fm3 coefficients used for the computation of the F2 layer maximum usable frequency factor. + * @return the F2 coefficients + */ + public double[][][] getFm3() { + return fm3Loader.clone(); + } + + /** Load the data for a given month. + * @param dateComponents month given but its DateComponents + */ + public void loadCCIRCoefficients(final DateComponents dateComponents) { + + // The files are named ccirXX.asc where XX substitute the month of the year + 10 + final int currentMonth = dateComponents.getMonth(); + this.supportedName = NEQUICK_BASE + String.format("ccir%02d.asc", currentMonth + 10); + try (InputStream in = getStream(supportedName)) { + loadData(in, supportedName); + } catch (IOException e) { + throw new OrekitException(OrekitMessages.INTERNAL_ERROR, e); + } + // Throw an exception if F2 or Fm3 were not loaded properly + if (f2Loader == null || fm3Loader == null) { + throw new OrekitException(OrekitMessages.NEQUICK_F2_FM3_NOT_LOADED, supportedName); + } + + } + + /** + * Load data from a stream. + * @param input input stream + * @param name name of the file + * @throws IOException if data can't be read + */ + public void loadData(final InputStream input, final String name) + throws IOException { + + // Initialize arrays + final double[][][] f2Temp = new double[ROWS][TOTAL_COLUMNS_F2][DEPTH_F2]; + final double[][][] fm3Temp = new double[ROWS][TOTAL_COLUMNS_FM3][DEPTH_FM3]; + + // Placeholders for parsed data + int lineNumber = 0; + int index = 0; + int currentRowF2 = 0; + int currentColumnF2 = 0; + int currentDepthF2 = 0; + int currentRowFm3 = 0; + int currentColumnFm3 = 0; + int currentDepthFm3 = 0; + String line = null; + + try (InputStreamReader isr = new InputStreamReader(input, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr)) { + + for (line = br.readLine(); line != null; line = br.readLine()) { + ++lineNumber; + line = line.trim(); + + // Read grid data + if (line.length() > 0) { + final String[] ccir_line = line.split(SPLITER); + for (int i = 0; i < ccir_line.length; i++) { + + if (index < NUMBER_F2_COEFFICIENTS) { + // Parse F2 coefficients + if (currentDepthF2 >= DEPTH_F2 && currentColumnF2 < (TOTAL_COLUMNS_F2 - 1)) { + currentDepthF2 = 0; + currentColumnF2++; + } else if (currentDepthF2 >= DEPTH_F2 && currentColumnF2 >= (TOTAL_COLUMNS_F2 - 1)) { + currentDepthF2 = 0; + currentColumnF2 = 0; + currentRowF2++; + } + f2Temp[currentRowF2][currentColumnF2][currentDepthF2++] = Double.valueOf(ccir_line[i]); + index++; + } else { + // Parse Fm3 coefficients + if (currentDepthFm3 >= DEPTH_FM3 && currentColumnFm3 < (TOTAL_COLUMNS_FM3 - 1)) { + currentDepthFm3 = 0; + currentColumnFm3++; + } else if (currentDepthFm3 >= DEPTH_FM3 && currentColumnFm3 >= (TOTAL_COLUMNS_FM3 - 1)) { + currentDepthFm3 = 0; + currentColumnFm3 = 0; + currentRowFm3++; + } + fm3Temp[currentRowFm3][currentColumnFm3][currentDepthFm3++] = Double.valueOf(ccir_line[i]); + index++; + } + + } + } + + } + + } catch (NumberFormatException nfe) { + throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE, + lineNumber, name, line); + } + + // Close the stream after reading + input.close(); + + f2Loader = f2Temp.clone(); + fm3Loader = fm3Temp.clone(); + + } + + } + + /** + * Container for ray-perigee parameters. + * By convention, point 1 is at lower height. + */ + private static class Ray { + + /** Threshold for ray-perigee parameters computation. */ + private static final double THRESHOLD = 1.0e-10; + + /** Distance of the first point from the ray perigee [m]. */ + private final double s1; + + /** Distance of the second point from the ray perigee [m]. */ + private final double s2; + + /** Ray-perigee radius [m]. */ + private final double rp; + + /** Ray-perigee latitude [rad]. */ + private final double latP; + + /** Ray-perigee longitude [rad]. */ + private final double lonP; + + /** Sine of azimuth of satellite as seen from ray-perigee. */ + private final double sinAzP; + + /** Cosine of azimuth of satellite as seen from ray-perigee. */ + private final double cosAzP; + + /** + * Constructor. + * @param recP receiver position + * @param satP satellite position + */ + Ray(final GeodeticPoint recP, final GeodeticPoint satP) { + + // Integration limits in meters (Eq. 140 and 141) + final double r1 = RE + recP.getAltitude(); + final double r2 = RE + satP.getAltitude(); + + // Useful parameters + final double lat1 = recP.getLatitude(); + final double lat2 = satP.getLatitude(); + final double lon1 = recP.getLongitude(); + final double lon2 = satP.getLongitude(); + final SinCos scLatSat = FastMath.sinCos(lat2); + final SinCos scLatRec = FastMath.sinCos(lat1); + + // Zenith angle computation (Eq. 153 to 155) + final double cosD = scLatRec.sin() * scLatSat.sin() + + scLatRec.cos() * scLatSat.cos() * FastMath.cos(lon2 - lon1); + final double sinD = FastMath.sqrt(1.0 - cosD * cosD); + final double z = FastMath.atan2(sinD, cosD - (r1 / r2)); + + // Ray-perigee computation in meters (Eq. 156) + this.rp = r1 * FastMath.sin(z); + + // Ray-perigee latitude and longitude + if (FastMath.abs(FastMath.abs(lat1) - 0.5 * FastMath.PI) < THRESHOLD) { + + // Ray-perigee latitude (Eq. 157) + if (lat1 < 0) { + this.latP = -z; + } else { + this.latP = z; + } + + // Ray-perigee longitude (Eq. 164) + if (z < 0) { + this.lonP = lon2; + } else { + this.lonP = lon2 + FastMath.PI; + } + + } else { + + // Ray-perigee latitude (Eq. 158 to 163) + final double deltaP = 0.5 * FastMath.PI - z; + final SinCos scDeltaP = FastMath.sinCos(deltaP); + final double sinAz = FastMath.sin(lon2 - lon1) * scLatSat.cos() / sinD; + final double cosAz = (scLatSat.sin() - cosD * scLatRec.sin()) / (sinD * scLatRec.cos()); + final double sinLatP = scLatRec.sin() * scDeltaP.cos() - scLatRec.cos() * scDeltaP.sin() * cosAz; + final double cosLatP = FastMath.sqrt(1.0 - sinLatP * sinLatP); + this.latP = FastMath.atan2(sinLatP, cosLatP); + + // Ray-perigee longitude (Eq. 165 to 167) + final double sinLonP = -sinAz * scDeltaP.sin() / cosLatP; + final double cosLonP = (scDeltaP.cos() - scLatRec.sin() * sinLatP) / (scLatRec.cos() * cosLatP); + this.lonP = FastMath.atan2(sinLonP, cosLonP) + lon1; + + } + + // Sine and cosie of azimuth of satellite as seen from ray-perigee + final double psi = greatCircleAngle(lat2, lon2); + if (FastMath.abs(FastMath.abs(latP) - 0.5 * FastMath.PI) < THRESHOLD) { + // Eq. 172 and 173 + this.sinAzP = 0.0; + if (latP < 0.0) { + this.cosAzP = 1; + } else { + this.cosAzP = -1; + } + } else { + // Eq. 174 and 175 + this.sinAzP = scLatSat.cos() * FastMath.sin(lon2 - lonP) / FastMath.sin(psi); + this.cosAzP = (scLatSat.sin() - FastMath.sin(latP) * FastMath.cos(psi)) / (FastMath.cos(latP) * FastMath.sin(psi)); + } + + // Integration en points s1 and s2 in meters (Eq. 176 and 177) + this.s1 = FastMath.sqrt(r1 * r1 - rp * rp); + this.s2 = FastMath.sqrt(r2 * r2 - rp * rp); + } + + /** + * Get the distance of the first point from the ray perigee. + * @return s1 in meters + */ + public double getS1() { + return s1; + } + + /** + * Get the distance of the second point from the ray perigee. + * @return s2 in meters + */ + public double getS2() { + return s2; + } + + /** + * Get the ray-perigee radius. + * @return the ray-perigee radius in meters + */ + public double getRadius() { + return rp; + } + + /** + * Get the ray-perigee latitude. + * @return the ray-perigee latitude in radians + */ + public double getLatitude() { + return latP; + } + + /** + * Get the ray-perigee longitude. + * @return the ray-perigee longitude in radians + */ + public double getLongitude() { + return lonP; + } + + /** + * Get the sine of azimuth of satellite as seen from ray-perigee. + * @return the sine of azimuth + */ + public double getSineAz() { + return sinAzP; + } + + /** + * Get the cosine of azimuth of satellite as seen from ray-perigee. + * @return the cosine of azimuth + */ + public double getCosineAz() { + return cosAzP; + } + + /** + * Compute the great circle angle from ray-perigee to satellite. + *

+ * This method used the equations 168 to 171 pf the reference document. + *

+ * @param latitude satellite latitude in radians + * @param longitude satellite longitude in radians + * @return the great circle angle in radians + */ + private double greatCircleAngle(final double latitude, final double longitude) { + if (FastMath.abs(FastMath.abs(latP) - 0.5 * FastMath.PI) < THRESHOLD) { + return FastMath.abs(latitude - latP); + } else { + final double cosPhi = FastMath.sin(latP) * FastMath.sin(latitude) + + FastMath.cos(latP) * FastMath.cos(latitude) * FastMath.cos(longitude - lonP); + final double sinPhi = FastMath.sqrt(1.0 - cosPhi * cosPhi); + return FastMath.atan2(sinPhi, cosPhi); + } + } + } + + /** + * Container for ray-perigee parameters. + * By convention, point 1 is at lower height. + */ + private static class FieldRay > { + + /** Threshold for ray-perigee parameters computation. */ + private static final double THRESHOLD = 1.0e-10; + + /** Distance of the first point from the ray perigee [m]. */ + private final T s1; + + /** Distance of the second point from the ray perigee [m]. */ + private final T s2; + + /** Ray-perigee radius [m]. */ + private final T rp; + + /** Ray-perigee latitude [rad]. */ + private final T latP; + + /** Ray-perigee longitude [rad]. */ + private final T lonP; + + /** Sine of azimuth of satellite as seen from ray-perigee. */ + private final T sinAzP; + + /** Cosine of azimuth of satellite as seen from ray-perigee. */ + private final T cosAzP; + + /** + * Constructor. + * @param field field of the elements + * @param recP receiver position + * @param satP satellite position + */ + FieldRay(final Field field, final FieldGeodeticPoint recP, final FieldGeodeticPoint satP) { + + // Integration limits in meters (Eq. 140 and 141) + final T r1 = recP.getAltitude().add(RE); + final T r2 = satP.getAltitude().add(RE); + + // Useful parameters + final T lat1 = recP.getLatitude(); + final T lat2 = satP.getLatitude(); + final T lon1 = recP.getLongitude(); + final T lon2 = satP.getLongitude(); + final FieldSinCos scLatSat = FastMath.sinCos(lat2); + final FieldSinCos scLatRec = FastMath.sinCos(lat1); + + // Zenith angle computation (Eq. 153 to 155) + final T cosD = scLatRec.sin().multiply(scLatSat.sin()). + add(scLatRec.cos().multiply(scLatSat.cos()).multiply(FastMath.cos(lon2.subtract(lon1)))); + final T sinD = FastMath.sqrt(cosD.multiply(cosD).negate().add(1.0)); + final T z = FastMath.atan2(sinD, cosD.subtract(r1.divide(r2))); + + // Ray-perigee computation in meters (Eq. 156) + this.rp = r1.multiply(FastMath.sin(z)); + + // Ray-perigee latitude and longitude + if (FastMath.abs(FastMath.abs(lat1).getReal() - 0.5 * FastMath.PI) < THRESHOLD) { + + // Ray-perigee latitude (Eq. 157) + if (lat1.getReal() < 0) { + this.latP = z.negate(); + } else { + this.latP = z; + } + + // Ray-perigee longitude (Eq. 164) + if (z.getReal() < 0) { + this.lonP = lon2; + } else { + this.lonP = lon2.add(FastMath.PI); + } + + } else { + + // Ray-perigee latitude (Eq. 158 to 163) + final T deltaP = z.negate().add(0.5 * FastMath.PI); + final FieldSinCos scDeltaP = FastMath.sinCos(deltaP); + final T sinAz = FastMath.sin(lon2.subtract(lon1)).multiply(scLatSat.cos()).divide(sinD); + final T cosAz = scLatSat.sin().subtract(cosD.multiply(scLatRec.sin())).divide(sinD.multiply(scLatRec.cos())); + final T sinLatP = scLatRec.sin().multiply(scDeltaP.cos()).subtract(scLatRec.cos().multiply(scDeltaP.sin()).multiply(cosAz)); + final T cosLatP = FastMath.sqrt(sinLatP.multiply(sinLatP).negate().add(1.0)); + this.latP = FastMath.atan2(sinLatP, cosLatP); + + // Ray-perigee longitude (Eq. 165 to 167) + final T sinLonP = sinAz.negate().multiply(scDeltaP.sin()).divide(cosLatP); + final T cosLonP = scDeltaP.cos().subtract(scLatRec.sin().multiply(sinLatP)).divide(scLatRec.cos().multiply(cosLatP)); + this.lonP = FastMath.atan2(sinLonP, cosLonP).add(lon1); + + } + + // Sine and cosie of azimuth of satellite as seen from ray-perigee + final T psi = greatCircleAngle(lat2, lon2); + if (FastMath.abs(FastMath.abs(latP).getReal() - 0.5 * FastMath.PI) < THRESHOLD) { + // Eq. 172 and 173 + this.sinAzP = field.getZero(); + if (latP.getReal() < 0.0) { + this.cosAzP = field.getOne(); + } else { + this.cosAzP = field.getOne().negate(); + } + } else { + // Eq. 174 and 175 + this.sinAzP = scLatSat.cos().multiply(FastMath.sin(lon2.subtract(lonP))).divide(FastMath.sin(psi)); + this.cosAzP = scLatSat.sin().subtract(FastMath.sin(latP).multiply(FastMath.cos(psi))).divide(FastMath.cos(latP).multiply(FastMath.sin(psi))); + } + + // Integration en points s1 and s2 in meters (Eq. 176 and 177) + this.s1 = FastMath.sqrt(r1.multiply(r1).subtract(rp.multiply(rp))); + this.s2 = FastMath.sqrt(r2.multiply(r2).subtract(rp.multiply(rp))); + } + + /** + * Get the distance of the first point from the ray perigee. + * @return s1 in meters + */ + public T getS1() { + return s1; + } + + /** + * Get the distance of the second point from the ray perigee. + * @return s2 in meters + */ + public T getS2() { + return s2; + } + + /** + * Get the ray-perigee radius. + * @return the ray-perigee radius in meters + */ + public T getRadius() { + return rp; + } + + /** + * Get the ray-perigee latitude. + * @return the ray-perigee latitude in radians + */ + public T getLatitude() { + return latP; + } + + /** + * Get the ray-perigee longitude. + * @return the ray-perigee longitude in radians + */ + public T getLongitude() { + return lonP; + } + + /** + * Get the sine of azimuth of satellite as seen from ray-perigee. + * @return the sine of azimuth + */ + public T getSineAz() { + return sinAzP; + } + + /** + * Get the cosine of azimuth of satellite as seen from ray-perigee. + * @return the cosine of azimuth + */ + public T getCosineAz() { + return cosAzP; + } + + /** + * Compute the great circle angle from ray-perigee to satellite. + *

+ * This method used the equations 168 to 171 pf the reference document. + *

+ * @param latitude satellite latitude in radians + * @param longitude satellite longitude in radians + * @return the great circle angle in radians + */ + private T greatCircleAngle(final T latitude, final T longitude) { + if (FastMath.abs(FastMath.abs(latP).getReal() - 0.5 * FastMath.PI) < THRESHOLD) { + return FastMath.abs(latitude.subtract(latP)); + } else { + final T cosPhi = FastMath.sin(latP).multiply(FastMath.sin(latitude)). + add(FastMath.cos(latP).multiply(FastMath.cos(latitude)).multiply(FastMath.cos(longitude.subtract(lonP)))); + final T sinPhi = FastMath.sqrt(cosPhi.multiply(cosPhi).negate().add(1.0)); + return FastMath.atan2(sinPhi, cosPhi); + } + } + } + + /** Performs the computation of the coordinates along the integration path. */ + private static class Segment { + + /** Latitudes [rad]. */ + private final double[] latitudes; + + /** Longitudes [rad]. */ + private final double[] longitudes; + + /** Heights [m]. */ + private final double[] heights; + + /** Integration step [m]. */ + private final double deltaN; + + /** + * Constructor. + * @param n number of points used for the integration + * @param ray ray-perigee parameters + */ + Segment(final int n, final Ray ray) { + // Integration en points + final double s1 = ray.getS1(); + final double s2 = ray.getS2(); + + // Integration step (Eq. 195) + this.deltaN = (s2 - s1) / n; + + // Segments + final double[] s = getSegments(n, s1, s2); + + // Useful parameters + final double rp = ray.getRadius(); + final SinCos scLatP = FastMath.sinCos(ray.getLatitude()); + + // Geodetic coordinates + final int size = s.length; + heights = new double[size]; + latitudes = new double[size]; + longitudes = new double[size]; + for (int i = 0; i < size; i++) { + // Heights (Eq. 178) + heights[i] = FastMath.sqrt(s[i] * s[i] + rp * rp) - RE; + + // Great circle parameters (Eq. 179 to 181) + final double tanDs = s[i] / rp; + final double cosDs = 1.0 / FastMath.sqrt(1.0 + tanDs * tanDs); + final double sinDs = tanDs * cosDs; + + // Latitude (Eq. 182 to 183) + final double sinLatS = scLatP.sin() * cosDs + scLatP.cos() * sinDs * ray.getCosineAz(); + final double cosLatS = FastMath.sqrt(1.0 - sinLatS * sinLatS); + latitudes[i] = FastMath.atan2(sinLatS, cosLatS); + + // Longitude (Eq. 184 to 187) + final double sinLonS = sinDs * ray.getSineAz() * scLatP.cos(); + final double cosLonS = cosDs - scLatP.sin() * sinLatS; + longitudes[i] = FastMath.atan2(sinLonS, cosLonS) + ray.getLongitude(); + } + } + + /** + * Computes the distance of a point from the ray-perigee. + * @param n number of points used for the integration + * @param s1 lower boundary + * @param s2 upper boundary + * @return the distance of a point from the ray-perigee in km + */ + private double[] getSegments(final int n, final double s1, final double s2) { + // Eq. 196 + final double g = 0.5773502691896 * deltaN; + // Eq. 197 + final double y = s1 + (deltaN - g) * 0.5; + final double[] segments = new double[2 * n]; + int index = 0; + for (int i = 0; i < n; i++) { + // Eq. 198 + segments[index] = y + i * deltaN; + index++; + segments[index] = y + i * deltaN + g; + index++; + } + return segments; + } + + /** + * Get the latitudes of the coordinates along the integration path. + * @return the latitudes in radians + */ + public double[] getLatitudes() { + return latitudes; + } + + /** + * Get the longitudes of the coordinates along the integration path. + * @return the longitudes in radians + */ + public double[] getLongitudes() { + return longitudes; + } + + /** + * Get the heights of the coordinates along the integration path. + * @return the heights in m + */ + public double[] getHeights() { + return heights; + } + + /** + * Get the integration step. + * @return the integration step in meters + */ + public double getInterval() { + return deltaN; + } + } + + /** Performs the computation of the coordinates along the integration path. */ + private static class FieldSegment > { + + /** Latitudes [rad]. */ + private final T[] latitudes; + + /** Longitudes [rad]. */ + private final T[] longitudes; + + /** Heights [m]. */ + private final T[] heights; + + /** Integration step [m]. */ + private final T deltaN; + + /** + * Constructor. + * @param field field of the elements + * @param n number of points used for the integration + * @param ray ray-perigee parameters + */ + FieldSegment(final Field field, final int n, final FieldRay ray) { + // Integration en points + final T s1 = ray.getS1(); + final T s2 = ray.getS2(); + + // Integration step (Eq. 195) + this.deltaN = s2.subtract(s1).divide(n); + + // Segments + final T[] s = getSegments(field, n, s1, s2); + + // Useful parameters + final T rp = ray.getRadius(); + final FieldSinCos scLatP = FastMath.sinCos(ray.getLatitude()); + + // Geodetic coordinates + final int size = s.length; + heights = MathArrays.buildArray(field, size); + latitudes = MathArrays.buildArray(field, size); + longitudes = MathArrays.buildArray(field, size); + for (int i = 0; i < size; i++) { + // Heights (Eq. 178) + heights[i] = FastMath.sqrt(s[i].multiply(s[i]).add(rp.multiply(rp))).subtract(RE); + + // Great circle parameters (Eq. 179 to 181) + final T tanDs = s[i].divide(rp); + final T cosDs = FastMath.sqrt(tanDs.multiply(tanDs).add(1.0)).reciprocal(); + final T sinDs = tanDs.multiply(cosDs); + + // Latitude (Eq. 182 to 183) + final T sinLatS = scLatP.sin().multiply(cosDs).add(scLatP.cos().multiply(sinDs).multiply(ray.getCosineAz())); + final T cosLatS = FastMath.sqrt(sinLatS.multiply(sinLatS).negate().add(1.0)); + latitudes[i] = FastMath.atan2(sinLatS, cosLatS); + + // Longitude (Eq. 184 to 187) + final T sinLonS = sinDs.multiply(ray.getSineAz()).multiply(scLatP.cos()); + final T cosLonS = cosDs.subtract(scLatP.sin().multiply(sinLatS)); + longitudes[i] = FastMath.atan2(sinLonS, cosLonS).add(ray.getLongitude()); + } + } + + /** + * Computes the distance of a point from the ray-perigee. + * @param field field of the elements + * @param n number of points used for the integration + * @param s1 lower boundary + * @param s2 upper boundary + * @return the distance of a point from the ray-perigee in km + */ + private T[] getSegments(final Field field, final int n, final T s1, final T s2) { + // Eq. 196 + final T g = deltaN.multiply(0.5773502691896); + // Eq. 197 + final T y = s1.add(deltaN.subtract(g).multiply(0.5)); + final T[] segments = MathArrays.buildArray(field, 2 * n); + int index = 0; + for (int i = 0; i < n; i++) { + // Eq. 198 + segments[index] = y.add(deltaN.multiply(i)); + index++; + segments[index] = y.add(deltaN.multiply(i)).add(g); + index++; + } + return segments; + } + + /** + * Get the latitudes of the coordinates along the integration path. + * @return the latitudes in radians + */ + public T[] getLatitudes() { + return latitudes; + } + + /** + * Get the longitudes of the coordinates along the integration path. + * @return the longitudes in radians + */ + public T[] getLongitudes() { + return longitudes; + } + + /** + * Get the heights of the coordinates along the integration path. + * @return the heights in m + */ + public T[] getHeights() { + return heights; + } + + /** + * Get the integration step. + * @return the integration step in meters + */ + public T getInterval() { + return deltaN; + } + } + +} diff --git a/src/main/java/org/orekit/models/earth/ionosphere/NeQuickParameters.java b/src/main/java/org/orekit/models/earth/ionosphere/NeQuickParameters.java new file mode 100644 index 0000000000000000000000000000000000000000..679751c3a6881906c02b4cfefc8dbe09d1d57123 --- /dev/null +++ b/src/main/java/org/orekit/models/earth/ionosphere/NeQuickParameters.java @@ -0,0 +1,768 @@ +/* Copyright 2002-2019 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.models.earth.ionosphere; + +import org.hipparchus.util.FastMath; +import org.hipparchus.util.MathArrays; +import org.hipparchus.util.SinCos; +import org.orekit.time.DateComponents; +import org.orekit.time.DateTimeComponents; +import org.orekit.time.TimeComponents; + +/** + * This class perfoms the computation of the parameters used by the NeQuick model. + * + * @author Bryan Cazabonne + * + * @see "European Union (2016). European GNSS (Galileo) Open Service-Ionospheric Correction + * Algorithm for Galileo Single Frequency Users. 1.2." + * + * @since 10.1 + */ +class NeQuickParameters { + + /** Solar zenith angle at day night transition, degrees. */ + private static final double X0 = 86.23292796211615; + + /** F2 layer maximum density. */ + private final double nmF2; + + /** F2 layer maximum density height [km]. */ + private final double hmF2; + + /** F1 layer maximum density height [km]. */ + private final double hmF1; + + /** E layer maximum density height [km]. */ + private final double hmE; + + /** F2 layer bottom thickness parameter [km]. */ + private final double b2Bot; + + /** F1 layer top thickness parameter [km]. */ + private final double b1Top; + + /** F1 layer bottom thickness parameter [km]. */ + private final double b1Bot; + + /** E layer top thickness parameter [km]. */ + private final double beTop; + + /** E layer bottom thickness parameter [km]. */ + private final double beBot; + + /** topside thickness parameter [km]. */ + private final double h0; + + /** Layer amplitudes. */ + private final double[] amplitudes; + + /** + * Build a new instance. + * @param dateTime current date time components + * @param f2 F2 coefficients used by the F2 layer + * @param fm3 Fm3 coefficients used by the F2 layer + * @param latitude latitude of a point along the integration path, in radians + * @param longitude longitude of a point along the integration path, in radians + * @param alpha effective ionisation level coefficients + * @param modipGrip modip grid + */ + NeQuickParameters(final DateTimeComponents dateTime, final double[][][] f2, + final double[][][] fm3, final double latitude, final double longitude, + final double[] alpha, final double[][] modipGrip) { + + // MODIP in degrees + final double modip = computeMODIP(latitude, longitude, modipGrip); + // Effective ionisation level Az + final double az = computeAz(modip, alpha); + // Effective sunspot number (Eq. 19) + final double azr = FastMath.sqrt(167273.0 + (az - 63.7) * 1123.6) - 408.99; + // Date and Time components + final DateComponents date = dateTime.getDate(); + final TimeComponents time = dateTime.getTime(); + // Hours + final double hours = time.getSecondsInUTCDay() / 3600.0; + // Effective solar zenith angle in radians + final double xeff = computeEffectiveSolarAngle(date.getMonth(), hours, latitude, longitude); + + // Coefficients for F2 layer parameters + // Compute the array of interpolated coefficients for foF2 (Eq. 44) + final double[][] af2 = new double[76][13]; + for (int j = 0; j < 76; j++) { + for (int k = 0; k < 13; k++ ) { + af2[j][k] = f2[0][j][k] * (1.0 - (azr * 0.01)) + f2[1][j][k] * (azr * 0.01); + } + } + + // Compute the array of interpolated coefficients for M(3000)F2 (Eq. 46) + final double[][] am3 = new double[49][9]; + for (int j = 0; j < 49; j++) { + for (int k = 0; k < 9; k++ ) { + am3[j][k] = fm3[0][j][k] * (1.0 - (azr * 0.01)) + fm3[1][j][k] * (azr * 0.01); + } + } + + // E layer maximum density height in km (Eq. 78) + this.hmE = 120.0; + // E layer critical frequency in MHz + final double foE = computefoE(date.getMonth(), az, xeff, latitude); + // E layer maximum density in 10^11 m-3 (Eq. 36) + final double nmE = 0.124 * foE * foE; + + // Time argument (Eq. 49) + final double t = FastMath.toRadians(15 * hours) - FastMath.PI; + // Compute Fourier time series for foF2 and M(3000)F2 + final double[] cf2 = computeCF2(af2, t); + final double[] cm3 = computeCm3(am3, t); + // F2 layer critical frequency in MHz + final double foF2 = computefoF2(modip, cf2, latitude, longitude); + // Maximum Usable Frequency factor + final double mF2 = computeMF2(modip, cm3, latitude, longitude); + // F2 layer maximum density in 10^11 m-3 + this.nmF2 = 0.124 * foF2 * foF2; + // F2 layer maximum density height in km + this.hmF2 = computehmF2(foE, foF2, mF2); + + // F1 layer critical frequency in MHz + final double foF1 = computefoF1(foE, foF2); + // F1 layer maximum density in 10^11 m-3 + final double nmF1; + if (foF1 <= 0.0 && foE > 2.0) { + final double foEpopf = foE + 0.5; + nmF1 = 0.124 * foEpopf * foEpopf; + } else { + nmF1 = 0.124 * foF1 * foF1; + } + // F1 layer maximum density height in km + this.hmF1 = 0.5 * (hmF2 + hmE); + + // Thickness parameters (Eq. 85 to 89) + final double a = 0.01 * clipExp(-3.467 + 0.857 * FastMath.log(foF2 * foF2) + 2.02 * FastMath.log(mF2)); + this.b2Bot = 0.385 * nmF2 / a; + this.b1Top = 0.3 * (hmF2 - hmF1); + this.b1Bot = 0.5 * (hmF1 - hmE); + this.beTop = FastMath.max(b1Bot, 7.0); + this.beBot = 5.0; + + // Layer amplitude coefficients + this.amplitudes = computeLayerAmplitudes(nmE, nmF1, foF1); + + // Topside thickness parameter + this.h0 = computeH0(date.getMonth(), azr); + } + + /** + * Get the F2 layer maximum density. + * @return nmF2 + */ + public double getNmF2() { + return nmF2; + } + + /** + * Get the F2 layer maximum density height. + * @return hmF2 in km + */ + public double getHmF2() { + return hmF2; + } + + /** + * Get the F1 layer maximum density height. + * @return hmF1 in km + */ + public double getHmF1() { + return hmF1; + } + + /** + * Get the E layer maximum density height. + * @return hmE in km + */ + public double getHmE() { + return hmE; + } + + /** + * Get the F2 layer thickness parameter (bottom). + * @return B2Bot in km + */ + public double getB2Bot() { + return b2Bot; + } + + /** + * Get the F1 layer thickness parameter (top). + * @return B1Top in km + */ + public double getB1Top() { + return b1Top; + } + + /** + * Get the F1 layer thickness parameter (bottom). + * @return B1Bot in km + */ + public double getB1Bot() { + return b1Bot; + } + + /** + * Get the E layer thickness parameter (bottom). + * @return BeBot in km + */ + public double getBEBot() { + return beBot; + } + + /** + * Get the E layer thickness parameter (top). + * @return BeTop in km + */ + public double getBETop() { + return beTop; + } + + /** + * Get the F2, F1 and E layer amplitudes. + *

+ * The resulting element is an array having the following form: + *

    + *
  • double[0] = A1 → F2 layer amplitude + *
  • double[1] = A2 → F1 layer amplitude + *
  • double[2] = A3 → E layer amplitude + *
+ * @return layer amplitudes + */ + public double[] getLayerAmplitudes() { + return amplitudes.clone(); + } + + /** + * Get the topside thickness parameter H0. + * @return H0 in km + */ + public double getH0() { + return h0; + } + + /** + * Computes the value of the modified dip latitude (MODIP) for the + * given latitude and longitude. + * + * @param lat receiver latitude, radians + * @param lon receiver longitude, radians + * @param stModip modip grid + * @return the MODIP in degrees + */ + private double computeMODIP(final double lat, final double lon, final double[][] stModip) { + + // For the MODIP computation, latitude and longitude have to be converted in degrees + final double latitude = FastMath.toDegrees(lat); + final double longitude = FastMath.toDegrees(lon); + + // Extreme cases + if (latitude == 90.0 || latitude == -90.0) { + return latitude; + } + + // Auxiliary parameter l (Eq. 6 to 8) + final int lF = (int) ((longitude + 180) * 0.1); + int l = lF - 2; + if (l < 0) { + l += 36; + } else if (l > 33) { + l -= 36; + } + + // Auxiliary parameter a (Eq. 9 to 11) + final double a = 0.2 * (latitude + 90) + 1.0; + final double aF = FastMath.floor(a); + // Eq. 10 + final double x = a - aF; + // Eq. 11 + final int i = (int) aF - 2; + + // zi coefficients (Eq. 12 and 13) + final double z1 = interpolate(stModip[i + 1][l + 2], stModip[i + 2][l + 2], stModip[i + 3][l + 2], stModip[i + 4][l + 2], x); + final double z2 = interpolate(stModip[i + 1][l + 3], stModip[i + 2][l + 3], stModip[i + 3][l + 3], stModip[i + 4][l + 3], x); + final double z3 = interpolate(stModip[i + 1][l + 4], stModip[i + 2][l + 4], stModip[i + 3][l + 4], stModip[i + 4][l + 4], x); + final double z4 = interpolate(stModip[i + 1][l + 5], stModip[i + 2][l + 5], stModip[i + 3][l + 5], stModip[i + 4][l + 5], x); + + // Auxiliary parameter b (Eq. 14 and 15) + final double b = (longitude + 180) * 0.1; + final double bF = FastMath.floor(b); + final double y = b - bF; + + // MODIP (Ref Eq. 16) + final double modip = interpolate(z1, z2, z3, z4, y); + + return modip; + } + + /** + * This method computes the effective ionisation level Az. + *

+ * This parameter is used for the computation of the Total Electron Content (TEC). + *

+ * @param modip modified dip latitude (MODIP) in degrees + * @param alpha effective ionisation level coefficients + * @return the ionisation level Az + */ + private double computeAz(final double modip, final double[] alpha) { + // Particular condition (Eq. 17) + if (alpha[0] == 0.0 && alpha[1] == 0.0 && alpha[2] == 0.0) { + return 63.7; + } + // Az = a0 + modip * a1 + modip^2 * a2 (Eq. 18) + double az = alpha[0] + modip * (alpha[1] + modip * alpha[2]); + // If Az < 0 -> Az = 0 + az = FastMath.max(0.0, az); + // If Az > 400 -> Az = 400 + az = FastMath.min(400.0, az); + return az; + } + + /** + * This method computes the effective solar zenith angle. + *

+ * The effective solar zenith angle is compute as a function of the + * solar zenith angle and the solar zenith angle at day night transition. + *

+ * @param month current month of the year + * @param hours universal time (hours) + * @param latitude in radians + * @param longitude in radians + * @return the effective solar zenith angle, radians + */ + private double computeEffectiveSolarAngle(final int month, + final double hours, + final double latitude, + final double longitude) { + // Local time (Eq.4) + final double lt = hours + longitude / FastMath.toRadians(15.0); + // Day of year at the middle of the month (Eq. 20) + final double dy = 30.5 * month - 15.0; + // Time (Eq. 21) + final double t = dy + (18 - hours) / 24; + // Arguments am and al (Eq. 22 and 23) + final double am = FastMath.toRadians(0.9856 * t - 3.289); + final double al = am + FastMath.toRadians(1.916 * FastMath.sin(am) + 0.020 * FastMath.sin(2.0 * am) + 282.634); + // Sine and cosine of solar declination (Eq. 24 and 25) + final double sDec = 0.39782 * FastMath.sin(al); + final double cDec = FastMath.sqrt(1. - sDec * sDec); + // Solar zenith angle, deg (Eq. 26 and 27) + final SinCos scLat = FastMath.sinCos(latitude); + final double coef = (FastMath.PI / 12) * (12 - lt); + final double cZenith = scLat.sin() * sDec + scLat.cos() * cDec * FastMath.cos(coef); + final double angle = FastMath.atan2(FastMath.sqrt(1.0 - cZenith * cZenith), cZenith); + final double x = FastMath.toDegrees(angle); + // Effective solar zenith angle (Eq. 28) + final double xeff = join(90.0 - 0.24 * clipExp(20.0 - 0.2 * x), x, 12.0, x - X0); + return FastMath.toRadians(xeff); + } + + /** + * This method computes the E layer critical frequency at a given location. + * @param month current month + * @param az ffective ionisation level + * @param xeff effective solar zenith angle in radians + * @param latitude latitude in radians + * @return the E layer critical frequency at a given location in MHz + */ + private double computefoE(final int month, final double az, + final double xeff, final double latitude) { + // The latitude has to be converted in degrees + final double lat = FastMath.toDegrees(latitude); + // Square root of the effective ionisation level + final double sqAz = FastMath.sqrt(az); + // seas parameter (Eq. 30 to 32) + final int seas; + if (month == 1 || month == 2 || month == 11 || month == 12) { + seas = -1; + } else if (month == 3 || month == 4 || month == 9 || month == 10) { + seas = 0; + } else { + seas = 1; + } + // Latitudinal dependence (Eq. 33 and 34) + final double ee = clipExp(0.3 * lat); + final double seasp = seas * ((ee - 1.0) / (ee + 1.0)); + // Critical frequency (Eq. 35) + final double coef = 1.112 - 0.019 * seasp; + final double foE = FastMath.sqrt(coef * coef * sqAz * FastMath.pow(FastMath.cos(xeff), 0.6) + 0.49); + return foE; + } + + /** + * Computes the F2 layer height of maximum electron density. + * @param foE E layer layer critical frequency in MHz + * @param foF2 F2 layer layer critical frequency in MHz + * @param mF2 maximum usable frequency factor + * @return hmF2 in km + */ + private double computehmF2(final double foE, final double foF2, final double mF2) { + // Ratio + final double fo = foF2 / foE; + final double ratio = join(fo, 1.75, 20.0, fo - 1.75); + + // deltaM parameter + double deltaM = -0.012; + if (foE >= 1e-30) { + deltaM += 0.253 / (ratio - 1.215); + } + + // hmF2 Eq. 80 + final double mF2Sq = mF2 * mF2; + final double temp = FastMath.sqrt((0.0196 * mF2Sq + 1) / (1.2967 * mF2Sq - 1.0)); + final double height = ((1490.0 * mF2 * temp) / (mF2 + deltaM)) - 176.0; + return height; + } + + /** + * Computes cf2 coefficients. + * @param af2 interpolated coefficients for foF2 + * @param t time argument + * @return the cf2 coefficients array + */ + private double[] computeCF2(final double[][] af2, final double t) { + // Eq. 50 + final double[] cf2 = new double[76]; + for (int i = 0; i < cf2.length; i++) { + double sum = 0.0; + for (int k = 0; k < 6; k++) { + sum += af2[i][2 * k + 1] * FastMath.sin((k + 1) * t) + af2[i][2 * (k + 1)] * FastMath.cos((k + 1) * t); + } + cf2[i] = af2[i][0] + sum; + } + return cf2; + } + + /** + * Computes Cm3 coefficients. + * @param am3 interpolated coefficients for foF2 + * @param t time argument + * @return the Cm3 coefficients array + */ + private double[] computeCm3(final double[][] am3, final double t) { + // Eq. 51 + final double[] cm3 = new double[49]; + for (int i = 0; i < cm3.length; i++) { + double sum = 0.0; + for (int k = 0; k < 4; k++) { + sum += am3[i][2 * k + 1] * FastMath.sin((k + 1) * t) + am3[i][2 * (k + 1)] * FastMath.cos((k + 1) * t); + } + cm3[i] = am3[i][0] + sum; + } + return cm3; + } + + /** + * This method computes the F2 layer critical frequency. + * @param modip modified DIP latitude, in degrees + * @param cf2 Fourier time series for foF2 + * @param latitude latitude in radians + * @param longitude longitude in radians + * @return the F2 layer critical frequency, MHz + */ + private double computefoF2(final double modip, final double[] cf2, + final double latitude, final double longitude) { + + // Legendre grades (Eq. 63) + final int[] q = new int[] { + 12, 12, 9, 5, 2, 1, 1, 1, 1 + }; + + // Array for geographic terms + final double[] g = new double[cf2.length]; + g[0] = 1.0; + + // MODIP coefficients Eq. 57 + final double sinMODIP = FastMath.sin(FastMath.toRadians(modip)); + final double[] m = new double[12]; + m[0] = 1.0; + for (int i = 1; i < q[0]; i++) { + m[i] = sinMODIP * m[i - 1]; + g[i] = m[i]; + } + + // Latitude coefficients (Eq. 58) + final double cosLat = FastMath.cos(latitude); + final double[] p = new double[8]; + p[0] = cosLat; + for (int n = 2; n < 9; n++) { + p[n - 1] = cosLat * p[n - 2]; + } + + // latitude and longitude terms + int index = 12; + for (int i = 1; i < q.length; i++) { + for (int j = 0; j < q[i]; j++) { + g[index++] = m[j] * p[i - 1] * FastMath.cos(i * longitude); + g[index++] = m[j] * p[i - 1] * FastMath.sin(i * longitude); + } + } + + // Compute foF2 by linear combination + final double frequency = MathArrays.linearCombination(cf2, g); + return frequency; + } + + /** + * This method computes the Maximum Usable Frequency factor. + * @param modip modified DIP latitude, in degrees + * @param cm3 Fourier time series for M(3000)F2 + * @param latitude latitude in radians + * @param longitude longitude in radians + * @return the Maximum Usable Frequency factor + */ + private double computeMF2(final double modip, final double[] cm3, + final double latitude, final double longitude) { + + // Legendre grades (Eq. 71) + final int[] r = new int[] { + 7, 8, 6, 3, 2, 1, 1 + }; + + // Array for geographic terms + final double[] g = new double[cm3.length]; + g[0] = 1.0; + + // MODIP coefficients Eq. 57 + final double sinMODIP = FastMath.sin(FastMath.toRadians(modip)); + final double[] m = new double[12]; + m[0] = 1.0; + for (int i = 1; i < 12; i++) { + m[i] = sinMODIP * m[i - 1]; + if (i < 7) { + g[i] = m[i]; + } + } + + // Latitude coefficients (Eq. 58) + final double cosLat = FastMath.cos(latitude); + final double[] p = new double[8]; + p[0] = cosLat; + for (int n = 2; n < 9; n++) { + p[n - 1] = cosLat * p[n - 2]; + } + + // latitude and longitude terms + int index = 7; + for (int i = 1; i < r.length; i++) { + for (int j = 0; j < r[i]; j++) { + g[index++] = m[j] * p[i - 1] * FastMath.cos(i * longitude); + g[index++] = m[j] * p[i - 1] * FastMath.sin(i * longitude); + } + } + + // Compute m3000 by linear combination + final double m3000 = MathArrays.linearCombination(g, cm3); + return m3000; + } + + /** + * This method computes the F1 layer critical frequency. + *

+ * This computation performs the algorithm exposed in Annex F + * of the reference document. + *

+ * @param foE the E layer critical frequency, MHz + * @return the F1 layer critical frequency, MHz + * @param foF2 the F2 layer critical frequency, MHz + */ + private double computefoF1(final double foE, final double foF2) { + final double temp = join(1.4 * foE, 0.0, 1000.0, foE - 2.0); + final double temp2 = join(0.0, temp, 1000.0, foE - temp); + final double value = join(temp2, 0.85 * temp2, 60.0, 0.85 * foF2 - temp2); + if (value < 1.0E-6) { + return 0.0; + } else { + return value; + } + } + + /** + * This method allows the computation of the F2, F1 and E layer amplitudes. + *

+ * The resulting element is an array having the following form: + *

    + *
  • double[0] = A1 → F2 layer amplitude + *
  • double[1] = A2 → F1 layer amplitude + *
  • double[2] = A3 → E layer amplitude + *
+ *

+ * @param nmE E layer maximum density in 10^11 m-3 + * @param nmF1 F1 layer maximum density in 10^11 m-3 + * @param foF1 F1 layer critical frequency in MHz + * @return a three components array containing the layer amplitudes + */ + private double[] computeLayerAmplitudes(final double nmE, final double nmF1, final double foF1) { + // Initialize array + final double[] amplitude = new double[3]; + + // F2 layer amplitude (Eq. 90) + final double a1 = 4.0 * nmF2; + amplitude[0] = a1; + + // F1 and E layer amplitudes (Eq. 91 to 98) + if (foF1 < 0.5) { + amplitude[1] = 0.0; + amplitude[2] = 4.0 * (nmE - epst(a1, hmF2, b2Bot, hmE)); + } else { + double a2a = 0.0; + double a3a = 4.0 * nmE; + for (int i = 0; i < 5; i++) { + a2a = 4.0 * (nmF1 - epst(a1, hmF2, b2Bot, hmF1) - epst(a3a, hmE, beTop, hmF1)); + a2a = join(a2a, 0.8 * nmF1, 1.0, a2a - 0.8 * nmF1); + a3a = 4.0 * (nmE - epst(a2a, hmF1, b1Bot, hmE) - epst(a1, hmF2, b2Bot, hmE)); + } + amplitude[1] = a2a; + amplitude[2] = join(a3a, 0.05, 60.0, a3a - 0.005); + } + + return amplitude; + } + + /** + * This method computes the topside thickness parameter H0. + * + * @param month current month + * @param azr effective sunspot number + * @return H0 in km + */ + private double computeH0(final int month, final double azr) { + + // Auxiliary parameter ka (Eq. 99 and 100) + final double ka; + if (month > 3 && month < 10) { + // month = 4,5,6,7,8,9 + ka = 6.705 - 0.014 * azr - 0.008 * hmF2; + } else { + // month = 1,2,3,10,11,12 + final double ratio = hmF2 / b2Bot; + ka = -7.77 + 0.097 * ratio * ratio + 0.153 * nmF2; + } + + // Auxiliary parameter kb (Eq. 101 and 102) + double kb = join(ka, 2.0, 1.0, ka - 2.0); + kb = join(8.0, kb, 1.0, kb - 8.0); + + // Auxiliary parameter Ha (Eq. 103) + final double hA = kb * b2Bot; + + // Auxiliary parameters x and v (Eq. 104 and 105) + final double x = 0.01 * (hA - 150.0); + final double v = (0.041163 * x - 0.183981) * x + 1.424472; + + // Topside thickness parameter (Eq. 106) + final double h = hA / v; + return h; + } + + /** + * A clipped exponential function. + *

+ * This function, describe in section F.2.12.2 of the reference document, is + * recommanded for the computation of exponential values. + *

+ * @param power power for exponential function + * @return clipped exponential value + */ + private double clipExp(final double power) { + if (power > 80.0) { + return 5.5406E34; + } else if (power < -80) { + return 1.8049E-35; + } else { + return FastMath.exp(power); + } + } + + /** + * This method provides a third order interpolation function + * as recommended in the reference document (Ref Eq. 128 to Eq. 138) + * + * @param z1 z1 coefficient + * @param z2 z2 coefficient + * @param z3 z3 coefficient + * @param z4 z4 coefficient + * @param x position + * @return a third order interpolation + */ + private double interpolate(final double z1, final double z2, + final double z3, final double z4, + final double x) { + + if (FastMath.abs(2.0 * x) < 1e-10) { + return z2; + } + + final double delta = 2.0 * x - 1.0; + final double g1 = z3 + z2; + final double g2 = z3 - z2; + final double g3 = z4 + z1; + final double g4 = (z4 - z1) / 3.0; + final double a0 = 9.0 * g1 - g3; + final double a1 = 9.0 * g2 - g4; + final double a2 = g3 - g1; + final double a3 = g4 - g2; + final double zx = 0.0625 * (a0 + delta * (a1 + delta * (a2 + delta * a3))); + + return zx; + } + + /** + * Allows smooth joining of functions f1 and f2 + * (i.e. continuous first derivatives) at origin. + *

+ * This function, describe in section F.2.12.1 of the reference document, is + * recommanded for computational efficiency. + *

+ * @param dF1 first function + * @param dF2 second function + * @param dA width of transition region + * @param dX x value + * @return the computed value + */ + private double join(final double dF1, final double dF2, + final double dA, final double dX) { + final double ee = clipExp(dA * dX); + return (dF1 * ee + dF2) / (ee + 1.0); + } + + /** + * The Epstein function. + *

+ * This function, describe in section 2.5.1 of the reference document, is used + * as a basis analytical function in NeQuick for the construction of the ionospheric layers. + *

+ * @param x x parameter + * @param y y parameter + * @param z z parameter + * @param w w parameter + * @return value of the epstein function + */ + private double epst(final double x, final double y, + final double z, final double w) { + final double ex = clipExp((w - y) / z); + final double opex = 1.0 + ex; + final double epst = x * ex / (opex * opex); + return epst; + } + +} diff --git a/src/main/java/org/orekit/models/earth/troposphere/SaastamoinenModel.java b/src/main/java/org/orekit/models/earth/troposphere/SaastamoinenModel.java index eb16e1cace675b09ed625fe87d9436c9972aedfd..f4fec4efaa4020e3a20c15ea272d45d471a36971 100644 --- a/src/main/java/org/orekit/models/earth/troposphere/SaastamoinenModel.java +++ b/src/main/java/org/orekit/models/earth/troposphere/SaastamoinenModel.java @@ -151,9 +151,9 @@ public class SaastamoinenModel implements DiscreteTroposphericModel { public double pathDelay(final double elevation, final double height, final double[] parameters, final AbsoluteDate date) { - // there are no data in the model for negative altitudes - // we use the data for the lowest available altitude: 0.0 - final double fixedHeight = FastMath.max(0.0, height); + // there are no data in the model for negative altitudes and altitude bigger than 5000 m + // limit the height to a range of [0, 5000] m + final double fixedHeight = FastMath.min(FastMath.max(0, height), 5000); // the corrected temperature using a temperature gradient of -6.5 K/km final double T = t0 - 6.5e-3 * fixedHeight; @@ -192,9 +192,9 @@ public class SaastamoinenModel implements DiscreteTroposphericModel { final Field field = height.getField(); final T zero = field.getZero(); - // there are no data in the model for negative altitudes - // we use the data for the lowest available altitude: 0.0 - final T fixedHeight = FastMath.max(zero, height); + // there are no data in the model for negative altitudes and altitude bigger than 5000 m + // limit the height to a range of [0, 5000] m + final T fixedHeight = FastMath.min(FastMath.max(zero, height), zero.add(5000)); // the corrected temperature using a temperature gradient of -6.5 K/km final T T = fixedHeight.multiply(6.5e-3).negate().add(t0); diff --git a/src/main/java/org/orekit/models/earth/troposphere/ViennaModelCoefficientsLoader.java b/src/main/java/org/orekit/models/earth/troposphere/ViennaModelCoefficientsLoader.java index daa3cf6aa85d243f164085f79777b43b632d5eee..5074cdfd530da799acef11f47649ad02688ce3a8 100644 --- a/src/main/java/org/orekit/models/earth/troposphere/ViennaModelCoefficientsLoader.java +++ b/src/main/java/org/orekit/models/earth/troposphere/ViennaModelCoefficientsLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; @@ -238,7 +239,7 @@ public class ViennaModelCoefficientsLoader implements DataLoader { throws IOException, ParseException { // Open stream and parse data - final BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader br = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); int lineNumber = 0; final String splitter = "\\s+"; diff --git a/src/main/java/org/orekit/orbits/FieldCircularOrbit.java b/src/main/java/org/orekit/orbits/FieldCircularOrbit.java index 5e3118ec3f41197c191d2e329c3e3f43ce944e21..d09a6838d29f4b901c481d04a868d3a11bfd00df 100644 --- a/src/main/java/org/orekit/orbits/FieldCircularOrbit.java +++ b/src/main/java/org/orekit/orbits/FieldCircularOrbit.java @@ -30,6 +30,7 @@ import org.hipparchus.analysis.interpolation.FieldHermiteInterpolator; import org.hipparchus.geometry.euclidean.threed.FieldVector3D; import org.hipparchus.util.FastMath; import org.hipparchus.util.MathArrays; +import org.hipparchus.util.MathUtils; import org.orekit.errors.OrekitIllegalArgumentException; import org.orekit.errors.OrekitInternalError; import org.orekit.errors.OrekitMessages; @@ -1027,8 +1028,8 @@ public class FieldCircularOrbit> } else { final T dt = circ.getDate().durationFrom(previousDate); final T keplerAM = previousAlphaM .add(circ.getKeplerianMeanMotion().multiply(dt)); - continuousRAAN = normalizeAngle(circ.getRightAscensionOfAscendingNode(), previousRAAN); - continuousAlphaM = normalizeAngle(circ.getAlphaM(), keplerAM); + continuousRAAN = MathUtils.normalizeAngle(circ.getRightAscensionOfAscendingNode(), previousRAAN); + continuousAlphaM = MathUtils.normalizeAngle(circ.getAlphaM(), keplerAM); } previousDate = circ.getDate(); previousRAAN = continuousRAAN; @@ -1355,7 +1356,9 @@ public class FieldCircularOrbit> * @param center center of the desired 2π interval for the result * @param the type of the field elements * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π + * @deprecated replaced by {@link MathUtils#normalizeAngle(RealFieldElement, RealFieldElement)} */ + @Deprecated public static > T normalizeAngle(final T a, final T center) { return a.subtract(2 * FastMath.PI * FastMath.floor((a.getReal() + FastMath.PI - center.getReal()) / (2 * FastMath.PI))); } diff --git a/src/main/java/org/orekit/orbits/FieldEquinoctialOrbit.java b/src/main/java/org/orekit/orbits/FieldEquinoctialOrbit.java index 3cb8df806ea1b0a323fa1fa8728d0bf1a9701517..e21fe402564b6591b7266008637b15c0a2b3d468 100644 --- a/src/main/java/org/orekit/orbits/FieldEquinoctialOrbit.java +++ b/src/main/java/org/orekit/orbits/FieldEquinoctialOrbit.java @@ -30,6 +30,7 @@ import org.hipparchus.analysis.interpolation.FieldHermiteInterpolator; import org.hipparchus.geometry.euclidean.threed.FieldVector3D; import org.hipparchus.util.FastMath; import org.hipparchus.util.MathArrays; +import org.hipparchus.util.MathUtils; import org.orekit.errors.OrekitIllegalArgumentException; import org.orekit.errors.OrekitInternalError; import org.orekit.errors.OrekitMessages; @@ -856,7 +857,7 @@ public class FieldEquinoctialOrbit> extends FieldO } else { final T dt = (T) equi.getDate().durationFrom(previousDate); final T keplerLm = previousLm.add((T) equi.getKeplerianMeanMotion().multiply(dt)); - continuousLm = normalizeAngle((T) equi.getLM(), keplerLm); + continuousLm = MathUtils.normalizeAngle((T) equi.getLM(), keplerLm); } previousDate = equi.getDate(); previousLm = continuousLm; @@ -1113,7 +1114,9 @@ public class FieldEquinoctialOrbit> extends FieldO * @param center center of the desired 2π interval for the result * @param the type of the field elements * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π + * @deprecated replaced by {@link MathUtils#normalizeAngle(RealFieldElement, RealFieldElement)} */ + @Deprecated public static > T normalizeAngle(final T a, final T center) { return a.subtract(2 * FastMath.PI * FastMath.floor((a.getReal() + FastMath.PI - center.getReal()) / (2 * FastMath.PI))); } diff --git a/src/main/java/org/orekit/orbits/FieldKeplerianOrbit.java b/src/main/java/org/orekit/orbits/FieldKeplerianOrbit.java index 6b26066fe5fff9890b09195eaf166b22538f43d3..1a441cf93ef68c5c8f347ab05120fe9d1143046c 100644 --- a/src/main/java/org/orekit/orbits/FieldKeplerianOrbit.java +++ b/src/main/java/org/orekit/orbits/FieldKeplerianOrbit.java @@ -32,6 +32,7 @@ import org.hipparchus.exception.MathIllegalArgumentException; import org.hipparchus.geometry.euclidean.threed.FieldVector3D; import org.hipparchus.util.FastMath; import org.hipparchus.util.MathArrays; +import org.hipparchus.util.MathUtils; import org.hipparchus.util.Precision; import org.orekit.errors.OrekitIllegalArgumentException; import org.orekit.errors.OrekitInternalError; @@ -710,7 +711,7 @@ public class FieldKeplerianOrbit> extends FieldOrb */ public static > T meanToEllipticEccentric(final T M, final T e) { // reduce M to [-PI PI) interval - final T reducedM = normalizeAngle(M, M.getField().getZero()); + final T reducedM = MathUtils.normalizeAngle(M, M.getField().getZero()); // compute start value according to A. W. Odell and R. H. Gooding S12 starter T E; @@ -1208,9 +1209,9 @@ public class FieldKeplerianOrbit> extends FieldOrb } else { final T dt = kep.getDate().durationFrom(previousDate); final T keplerM = previousM.add(kep.getKeplerianMeanMotion().multiply(dt)); - continuousPA = normalizeAngle(kep.getPerigeeArgument(), previousPA); - continuousRAAN = normalizeAngle(kep.getRightAscensionOfAscendingNode(), previousRAAN); - continuousM = normalizeAngle(kep.getMeanAnomaly(), keplerM); + continuousPA = MathUtils.normalizeAngle(kep.getPerigeeArgument(), previousPA); + continuousRAAN = MathUtils.normalizeAngle(kep.getRightAscensionOfAscendingNode(), previousRAAN); + continuousM = MathUtils.normalizeAngle(kep.getMeanAnomaly(), keplerM); } previousDate = kep.getDate(); previousPA = continuousPA; @@ -1743,7 +1744,9 @@ public class FieldKeplerianOrbit> extends FieldOrb * @param center center of the desired 2π interval for the result * @param the type of the field elements * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π + * @deprecated replaced by {@link MathUtils#normalizeAngle(RealFieldElement, RealFieldElement)} */ + @Deprecated public static > T normalizeAngle(final T a, final T center) { return a.subtract(2 * FastMath.PI * FastMath.floor((a.getReal() + FastMath.PI - center.getReal()) / (2 * FastMath.PI))); } diff --git a/src/main/java/org/orekit/orbits/FieldOrbit.java b/src/main/java/org/orekit/orbits/FieldOrbit.java index 775880b158fcb38ac37ab1ab461ccb64224f02ef..1c70348f492c1fe4947b5bcc730a134695ec4853 100644 --- a/src/main/java/org/orekit/orbits/FieldOrbit.java +++ b/src/main/java/org/orekit/orbits/FieldOrbit.java @@ -363,6 +363,9 @@ public abstract class FieldOrbit> */ public abstract boolean hasDerivatives(); + /** Get the central attraction coefficient used for position and velocity conversions (m³/s²). + * @return central attraction coefficient used for position and velocity conversions (m³/s²) + */ public T getMu() { return mu; } diff --git a/src/main/java/org/orekit/overview.html b/src/main/java/org/orekit/overview.html index a71f5973020ed497eec3abe087d37930472104ba..8aef98cc4e501aa89671992c30ffa94fcd19bb69 100644 --- a/src/main/java/org/orekit/overview.html +++ b/src/main/java/org/orekit/overview.html @@ -54,7 +54,8 @@ discrete events. Here is a short list of the features offered by the library:

composite transforms reduction and caching for efficiency
  • extensible central body shapes models (with predefined spherical and ellipsoidic shapes)
  • Cartesian and geodesic coordinates, kinematics
  • -
  • Computation of Dilution Of Precision (DOP) with respect to GNSS constellations
  • +
  • computation of Dilution Of Precision (DOP) with respect to GNSS constellations
  • +
  • projection of sensor Field Of View footprint on ground for any FoV shape
  • Spacecraft state @@ -288,12 +289,14 @@ discrete events. Here is a short list of the features offered by the library:

  • Customizable data loading
      -
    • loading from local disk
    • +
    • loading by exploring folders hierarchy on local disk
    • +
    • loading from explicit lists of files on local disk
    • loading from classpath
    • loading from network (even through internet proxies)
    • support for zip archives
    • automatic decompression of gzip compressed (.gz) files upon loading
    • automatic decompression of Unix compressed (.Z) files upon loading
    • +
    • automatic decompression of Hatanaka compressed files upon loading
    • plugin mechanism to add filtering like custom decompression algorithms, deciphering or monitoring
    • plugin mechanism to delegate loading to user defined database or data access library
    diff --git a/src/main/java/org/orekit/propagation/AbstractPropagator.java b/src/main/java/org/orekit/propagation/AbstractPropagator.java index 3cd4d834e24a664c62414bfb343bf424a5d57e05..294292ae87746973ad8c26416e9c52849b3db7bf 100644 --- a/src/main/java/org/orekit/propagation/AbstractPropagator.java +++ b/src/main/java/org/orekit/propagation/AbstractPropagator.java @@ -19,6 +19,7 @@ package org.orekit.propagation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import org.orekit.propagation.sampling.OrekitFixedStepHandler; import org.orekit.propagation.sampling.OrekitStepHandler; import org.orekit.propagation.sampling.OrekitStepNormalizer; import org.orekit.time.AbsoluteDate; +import org.orekit.utils.TimeSpanMap; import org.orekit.utils.TimeStampedPVCoordinates; /** Common handling of {@link Propagator} methods for analytical propagators. @@ -61,6 +63,9 @@ public abstract class AbstractPropagator implements Propagator { /** Additional state providers. */ private final List additionalStateProviders; + /** States managed by neither additional equations nor state providers. */ + private final Map> unmanagedStates; + /** Initial state. */ private SpacecraftState initialState; @@ -71,6 +76,7 @@ public abstract class AbstractPropagator implements Propagator { stepHandler = null; fixedStepSize = Double.NaN; additionalStateProviders = new ArrayList(); + unmanagedStates = new HashMap<>(); } /** Set a start date. @@ -177,7 +183,7 @@ public abstract class AbstractPropagator implements Propagator { /** Update state by adding all additional states. * @param original original state * @return updated state, with all additional states included - * @see #addAdditionalStateProvider(AdditionalStateProvider) + * @see #addAdditionalStateProvider(AdditionalStateProvider) */ protected SpacecraftState updateAdditionalStates(final SpacecraftState original) { @@ -185,17 +191,10 @@ public abstract class AbstractPropagator implements Propagator { // which may already contain additional states, for example in interpolated ephemerides SpacecraftState updated = original; - if (initialState != null) { - // there is an initial state - // (null initial states occur for example in interpolated ephemerides) - // copy the additional states present in initialState but otherwise not managed - for (final Map.Entry initial : initialState.getAdditionalStates().entrySet()) { - if (!isAdditionalStateManaged(initial.getKey())) { - // this additional state was in the initial state, but is unknown to the propagator - // we simply copy its initial value as is - updated = updated.addAdditionalState(initial.getKey(), initial.getValue()); - } - } + // update the states not managed by providers + for (final Map.Entry> entry : unmanagedStates.entrySet()) { + updated = updated.addAdditionalState(entry.getKey(), + entry.getValue().get(original.getDate())); } // update the additional states managed by providers @@ -266,4 +265,44 @@ public abstract class AbstractPropagator implements Propagator { return propagate(date).getPVCoordinates(frame); } + /** Initialize propagation. + * @since 10.1 + */ + protected void initializePropagation() { + + unmanagedStates.clear(); + + if (initialState != null) { + // there is an initial state + // (null initial states occur for example in interpolated ephemerides) + // copy the additional states present in initialState but otherwise not managed + for (final Map.Entry initial : initialState.getAdditionalStates().entrySet()) { + if (!isAdditionalStateManaged(initial.getKey())) { + // this additional state is in the initial state, but is unknown to the propagator + // we store it in a way event handlers may change it + unmanagedStates.put(initial.getKey(), new TimeSpanMap<>(initial.getValue())); + } + } + } + } + + /** Notify about a state change. + * @param state new state + */ + protected void stateChanged(final SpacecraftState state) { + final AbsoluteDate date = state.getDate(); + final boolean forward = date.durationFrom(getStartDate()) >= 0.0; + for (final Map.Entry changed : state.getAdditionalStates().entrySet()) { + final TimeSpanMap tsm = unmanagedStates.get(changed.getKey()); + if (tsm != null) { + // this is an unmanaged state + if (forward) { + tsm.addValidAfter(changed.getValue(), date); + } else { + tsm.addValidBefore(changed.getValue(), date); + } + } + } + } + } diff --git a/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java b/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java index 754273a666a0a3718eb62ba4f9136f5f1dc7ded5..6b7cc8ed8dca9a30f6056b474a50aa7a741376f5 100644 --- a/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java +++ b/src/main/java/org/orekit/propagation/FieldAbstractPropagator.java @@ -19,6 +19,7 @@ package org.orekit.propagation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -32,7 +33,9 @@ import org.orekit.propagation.events.FieldEventDetector; import org.orekit.propagation.sampling.FieldOrekitFixedStepHandler; import org.orekit.propagation.sampling.FieldOrekitStepHandler; import org.orekit.propagation.sampling.FieldOrekitStepNormalizer; +import org.orekit.time.AbsoluteDate; import org.orekit.time.FieldAbsoluteDate; +import org.orekit.utils.TimeSpanMap; import org.orekit.utils.TimeStampedFieldPVCoordinates; /** Common handling of {@link Propagator} methods for analytical propagators. @@ -63,6 +66,9 @@ public abstract class FieldAbstractPropagator> imp /** Additional state providers. */ private final List> additionalStateProviders; + /** States managed by neither additional equations nor state providers. */ + private final Map> unmanagedStates; + /** Field used.*/ private final Field field; @@ -77,7 +83,8 @@ public abstract class FieldAbstractPropagator> imp stepHandler = null; this.field = field; fixedStepSize = field.getZero().add(Double.NaN); - additionalStateProviders = new ArrayList>(); + additionalStateProviders = new ArrayList<>(); + unmanagedStates = new HashMap<>(); } /** Set a start date. @@ -182,7 +189,7 @@ public abstract class FieldAbstractPropagator> imp /** Update state by adding all additional states. * @param original original state * @return updated state, with all additional states included - * @see #addAdditionalStateProvider(FieldAdditionalStateProvider) + * @see #addAdditionalStateProvider(FieldAdditionalStateProvider) */ protected FieldSpacecraftState updateAdditionalStates(final FieldSpacecraftState original) { @@ -190,18 +197,10 @@ public abstract class FieldAbstractPropagator> imp // which may already contain additional states, for example in interpolated ephemerides FieldSpacecraftState updated = original; - if (initialState != null) { - // there is an initial state - // (null initial states occur for example in interpolated ephemerides) - // copy the additional states present in initialState but otherwise not managed - for (final Map.Entry initial : initialState.getAdditionalStates().entrySet()) { - - if (!isAdditionalStateManaged(initial.getKey())) { - // this additional state was in the initial state, but is unknown to the propagator - // we simply copy its initial value as is - updated = updated.addAdditionalState(initial.getKey(), initial.getValue()); - } - } + // update the states not managed by providers + for (final Map.Entry> entry : unmanagedStates.entrySet()) { + updated = updated.addAdditionalState(entry.getKey(), + entry.getValue().get(original.getDate().toAbsoluteDate())); } // update the additional states managed by providers @@ -273,4 +272,44 @@ public abstract class FieldAbstractPropagator> imp return propagate(date).getPVCoordinates(frame); } + /** Initialize propagation. + * @since 10.1 + */ + protected void initializePropagation() { + + unmanagedStates.clear(); + + if (initialState != null) { + // there is an initial state + // (null initial states occur for example in interpolated ephemerides) + // copy the additional states present in initialState but otherwise not managed + for (final Map.Entry initial : initialState.getAdditionalStates().entrySet()) { + if (!isAdditionalStateManaged(initial.getKey())) { + // this additional state is in the initial state, but is unknown to the propagator + // we store it in a way event handlers may change it + unmanagedStates.put(initial.getKey(), new TimeSpanMap<>(initial.getValue())); + } + } + } + } + + /** Notify about a state change. + * @param state new state + */ + protected void stateChanged(final FieldSpacecraftState state) { + final AbsoluteDate date = state.getDate().toAbsoluteDate(); + final boolean forward = date.durationFrom(getStartDate().toAbsoluteDate()) >= 0.0; + for (final Map.Entry changed : state.getAdditionalStates().entrySet()) { + final TimeSpanMap tsm = unmanagedStates.get(changed.getKey()); + if (tsm != null) { + // this is an unmanaged state + if (forward) { + tsm.addValidAfter(changed.getValue(), date); + } else { + tsm.addValidBefore(changed.getValue(), date); + } + } + } + } + } diff --git a/src/main/java/org/orekit/propagation/FieldPropagator.java b/src/main/java/org/orekit/propagation/FieldPropagator.java index 0b568479b1381c2177a8fe7e8c2d00d1bb74e3ee..8a539aa5ff10e1e477bb78db110c0341ca552475 100644 --- a/src/main/java/org/orekit/propagation/FieldPropagator.java +++ b/src/main/java/org/orekit/propagation/FieldPropagator.java @@ -175,7 +175,11 @@ public interface FieldPropagator> extends FieldPVC * Additional states that are present in the {@link #getInitialState() initial state} * but have no evolution method registered are not considered as managed states. * These unmanaged additional states are not lost during propagation, though. Their - * value will simply be copied unchanged throughout propagation. + * value are piecewise constant between state resets that may change them if some + * event handler {@link + * org.orekit.propagation.events.handlers.FieldEventHandler#resetState(FieldEventDetector, + * FieldSpacecraftState) resetState} method is called at an event occurrence and happens + * to change the unmanaged additional state. *

    * @param name name of the additional state * @return true if the additional state is managed diff --git a/src/main/java/org/orekit/propagation/FieldSpacecraftState.java b/src/main/java/org/orekit/propagation/FieldSpacecraftState.java index 5d6e94515574215c9360333e6db7dfe3559709f6..7a4d0b37b16a06a26723789bf9bc7c037a0c94ae 100644 --- a/src/main/java/org/orekit/propagation/FieldSpacecraftState.java +++ b/src/main/java/org/orekit/propagation/FieldSpacecraftState.java @@ -424,10 +424,11 @@ public class FieldSpacecraftState > final Map newMap = new HashMap(additional.size() + 1); newMap.putAll(additional); newMap.put(name, value.clone()); - if (absPva == null) + if (absPva == null) { return new FieldSpacecraftState<>(orbit, attitude, mass, newMap); - else + } else { return new FieldSpacecraftState<>(absPva, attitude, mass, newMap); + } } /** Check orbit and attitude dates are equal. diff --git a/src/main/java/org/orekit/propagation/Propagator.java b/src/main/java/org/orekit/propagation/Propagator.java index 1b83b05c37f6c03476c984455bb72d3b7751553b..6769d83d763c3b5d4807f2e708edbfa33673e4ba 100644 --- a/src/main/java/org/orekit/propagation/Propagator.java +++ b/src/main/java/org/orekit/propagation/Propagator.java @@ -209,7 +209,11 @@ public interface Propagator extends PVCoordinatesProvider { * Additional states that are present in the {@link #getInitialState() initial state} * but have no evolution method registered are not considered as managed states. * These unmanaged additional states are not lost during propagation, though. Their - * value will simply be copied unchanged throughout propagation. + * value are piecewise constant between state resets that may change them if some + * event handler {@link + * org.orekit.propagation.events.handlers.EventHandler#resetState(EventDetector, + * SpacecraftState) resetState} method is called at an event occurrence and happens + * to change the unmanaged additional state. *

    * @param name name of the additional state * @return true if the additional state is managed diff --git a/src/main/java/org/orekit/propagation/SpacecraftState.java b/src/main/java/org/orekit/propagation/SpacecraftState.java index a9191e9fdba43844bda557e36a1047348face248..f80bf8fe435bf5f445dfa487c3026e3bd664fa4b 100644 --- a/src/main/java/org/orekit/propagation/SpacecraftState.java +++ b/src/main/java/org/orekit/propagation/SpacecraftState.java @@ -341,10 +341,11 @@ public class SpacecraftState final Map newMap = new HashMap(additional.size() + 1); newMap.putAll(additional); newMap.put(name, value.clone()); - if (absPva == null) + if (absPva == null) { return new SpacecraftState(orbit, attitude, mass, newMap); - else + } else { return new SpacecraftState(absPva, attitude, mass, newMap); + } } /** Check orbit and attitude dates are equal. @@ -435,12 +436,13 @@ public class SpacecraftState * except for the mass and additional states which stay unchanged */ public SpacecraftState shiftedBy(final double dt) { - if (absPva == null) + if (absPva == null) { return new SpacecraftState(orbit.shiftedBy(dt), attitude.shiftedBy(dt), mass, additional); - else + } else { return new SpacecraftState(absPva.shiftedBy(dt), attitude.shiftedBy(dt), mass, additional); + } } /** {@inheritDoc} diff --git a/src/main/java/org/orekit/propagation/analytical/AbstractAnalyticalPropagator.java b/src/main/java/org/orekit/propagation/analytical/AbstractAnalyticalPropagator.java index 2329d0e2f8ab85cbb3398e22cca319e865a3fcce..87bcd2a3183f6a918a223aac26b03a1338a9dc2c 100644 --- a/src/main/java/org/orekit/propagation/analytical/AbstractAnalyticalPropagator.java +++ b/src/main/java/org/orekit/propagation/analytical/AbstractAnalyticalPropagator.java @@ -116,6 +116,8 @@ public abstract class AbstractAnalyticalPropagator extends AbstractPropagator { public SpacecraftState propagate(final AbsoluteDate start, final AbsoluteDate target) { try { + initializePropagation(); + lastPropagationStart = start; final double dt = target.durationFrom(start); diff --git a/src/main/java/org/orekit/propagation/analytical/AggregateBoundedPropagator.java b/src/main/java/org/orekit/propagation/analytical/AggregateBoundedPropagator.java index 72b820580dd2531bcfd29521671f2c83cc521220..a199369f2fdc1c30a51758177b352c99ac0a126a 100644 --- a/src/main/java/org/orekit/propagation/analytical/AggregateBoundedPropagator.java +++ b/src/main/java/org/orekit/propagation/analytical/AggregateBoundedPropagator.java @@ -21,6 +21,7 @@ import java.util.Map.Entry; import java.util.NavigableMap; import java.util.TreeMap; +import org.orekit.attitudes.Attitude; import org.orekit.errors.OrekitException; import org.orekit.errors.OrekitMessages; import org.orekit.frames.Frame; @@ -71,6 +72,27 @@ public class AggregateBoundedPropagator extends AbstractAnalyticalPropagator this.propagators.firstEntry().getValue().getInitialState()); } + @Override + protected SpacecraftState basicPropagate(final AbsoluteDate date) { + // #589 override this method for a performance benefit, + // getPropagator(date).propagate(date) is only called once + + // do propagation + final SpacecraftState state = getPropagator(date).propagate(date); + + // evaluate attitude + final Attitude attitude = + getAttitudeProvider().getAttitude(this, date, state.getFrame()); + + // build raw state + if (state.isOrbitDefined()) { + return new SpacecraftState( + state.getOrbit(), attitude, state.getMass(), state.getAdditionalStates()); + } else { + return new SpacecraftState( + state.getAbsPVA(), attitude, state.getMass(), state.getAdditionalStates()); + } + } @Override public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, diff --git a/src/main/java/org/orekit/propagation/analytical/EcksteinHechlerPropagator.java b/src/main/java/org/orekit/propagation/analytical/EcksteinHechlerPropagator.java index 54f4182b1b5f3217964e35e316bdd4ecc11adc02..1225a8bc70a637ef9e5c95b8a00c72047a648cf3 100644 --- a/src/main/java/org/orekit/propagation/analytical/EcksteinHechlerPropagator.java +++ b/src/main/java/org/orekit/propagation/analytical/EcksteinHechlerPropagator.java @@ -313,6 +313,7 @@ public class EcksteinHechlerPropagator extends AbstractAnalyticalPropagator { } else { models.addValidBefore(newModel, state.getDate()); } + stateChanged(state); } /** Compute mean parameters according to the Eckstein-Hechler analytical model. diff --git a/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java b/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java index da303dde6adc94b7426dd9914cbbe6dec4b35fe7..2564fa85ca78fd3030eb5660dceec3a36a722cfe 100644 --- a/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java +++ b/src/main/java/org/orekit/propagation/analytical/FieldAbstractAnalyticalPropagator.java @@ -115,6 +115,9 @@ public abstract class FieldAbstractAnalyticalPropagator propagate(final FieldAbsoluteDate start, final FieldAbsoluteDate target) { try { + + initializePropagation(); + lastPropagationStart = start; final T dt = target.durationFrom(start); @@ -170,8 +173,6 @@ public abstract class FieldAbstractAnalyticalPropagator> exten } else { models.addValidBefore(newModel, state.getDate()); } + stateChanged(state); } /** Compute mean parameters according to the Eckstein-Hechler analytical model. @@ -330,10 +332,10 @@ public class FieldEcksteinHechlerPropagator> exten final T deltaEx = osculating.getCircularEx().subtract(parameters[1].getValue()); final T deltaEy = osculating.getCircularEy().subtract(parameters[2].getValue()); final T deltaI = osculating.getI() .subtract(parameters[3].getValue()); - final T deltaRAAN = normalizeAngle(osculating.getRightAscensionOfAscendingNode().subtract( + final T deltaRAAN = MathUtils.normalizeAngle(osculating.getRightAscensionOfAscendingNode().subtract( parameters[4].getValue()), zero); - final T deltaAlphaM = normalizeAngle(osculating.getAlphaM().subtract(parameters[5].getValue()), zero); + final T deltaAlphaM = MathUtils.normalizeAngle(osculating.getAlphaM().subtract(parameters[5].getValue()), zero); // update mean parameters current = new FieldEHModel<>(factory, new FieldCircularOrbit<>(current.mean.getA().add(deltaA), @@ -607,13 +609,13 @@ public class FieldEcksteinHechlerPropagator> exten // right ascension of ascending node final FieldDerivativeStructure omm = - factory.build(normalizeAngle(mean.getRightAscensionOfAscendingNode().add(ommD.multiply(xnot.getValue())), + factory.build(MathUtils.normalizeAngle(mean.getRightAscensionOfAscendingNode().add(ommD.multiply(xnot.getValue())), zero.add(FastMath.PI)), ommD.multiply(xnotDot), zero); // latitude argument final FieldDerivativeStructure xlm = - factory.build(normalizeAngle(mean.getAlphaM().add(aMD.multiply(xnot.getValue())), zero.add(FastMath.PI)), + factory.build(MathUtils.normalizeAngle(mean.getAlphaM().add(aMD.multiply(xnot.getValue())), zero.add(FastMath.PI)), aMD.multiply(xnotDot), zero); @@ -816,7 +818,9 @@ public class FieldEcksteinHechlerPropagator> exten * @param the type of the field elements * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π * @since 1.2 + * @deprecated replaced by {@link MathUtils#normalizeAngle(RealFieldElement, RealFieldElement)} */ + @Deprecated public static > T normalizeAngle(final T a, final T center) { return a.subtract(2 * FastMath.PI * FastMath.floor((a.getReal() + FastMath.PI - center.getReal()) / (2 * FastMath.PI))); } diff --git a/src/main/java/org/orekit/propagation/analytical/FieldKeplerianPropagator.java b/src/main/java/org/orekit/propagation/analytical/FieldKeplerianPropagator.java index 8e36f62eb49b7ca8520ef1dd812832073ee239eb..8cdd2ab75cfc93b52601839ebc4ca397cfbc14bb 100644 --- a/src/main/java/org/orekit/propagation/analytical/FieldKeplerianPropagator.java +++ b/src/main/java/org/orekit/propagation/analytical/FieldKeplerianPropagator.java @@ -17,6 +17,9 @@ package org.orekit.propagation.analytical; +import java.util.Collections; +import java.util.Map; + import org.hipparchus.RealFieldElement; import org.hipparchus.util.MathArrays; import org.orekit.attitudes.AttitudeProvider; @@ -103,7 +106,7 @@ public class FieldKeplerianPropagator> extends Fie getAttitudeProvider().getAttitude(initialOrbit, initialOrbit.getDate(), initialOrbit.getFrame()), - mass, mu); + mass, mu, Collections.emptyMap()); states = new FieldTimeSpanMap<>(initialState, initialOrbit.getA().getField()); super.resetInitialState(initialState); } @@ -117,16 +120,21 @@ public class FieldKeplerianPropagator> extends Fie * @param attitude current attitude * @param mass current mass * @param mu gravity coefficient to use + * @param additionalStates additional states * @return fixed orbit */ private FieldSpacecraftState fixState(final FieldOrbit orbit, final FieldAttitude attitude, final T mass, - final T mu) { + final T mu, final Map additionalStates) { final OrbitType type = orbit.getType(); final T[] stateVector = MathArrays.buildArray(mass.getField(), 6); type.mapOrbitToArray(orbit, PositionAngle.TRUE, stateVector, null); final FieldOrbit fixedOrbit = type.mapArrayToOrbit(stateVector, null, PositionAngle.TRUE, orbit.getDate(), mu, orbit.getFrame()); - return new FieldSpacecraftState<>(fixedOrbit, attitude, mass); + FieldSpacecraftState fixedState = new FieldSpacecraftState<>(fixedOrbit, attitude, mass); + for (final Map.Entry entry : additionalStates.entrySet()) { + fixedState = fixedState.addAdditionalState(entry.getKey(), entry.getValue()); + } + return fixedState; } /** {@inheritDoc} */ @@ -137,7 +145,8 @@ public class FieldKeplerianPropagator> extends Fie final FieldSpacecraftState fixedState = fixState(state.getOrbit(), state.getAttitude(), state.getMass(), - mu); + mu, + state.getAdditionalStates()); initialState = fixedState; states = new FieldTimeSpanMap<>(initialState, state.getDate().getField()); @@ -152,6 +161,7 @@ public class FieldKeplerianPropagator> extends Fie } else { states.addValidBefore(state, state.getDate()); } + stateChanged(state); } /** {@inheritDoc} */ diff --git a/src/main/java/org/orekit/propagation/analytical/KeplerianPropagator.java b/src/main/java/org/orekit/propagation/analytical/KeplerianPropagator.java index e73c526cfb5b1c773cdad614caef4e35eb7d9214..68f7d6b70d31f8aaddf7a9d9ad29e5e48540fe47 100644 --- a/src/main/java/org/orekit/propagation/analytical/KeplerianPropagator.java +++ b/src/main/java/org/orekit/propagation/analytical/KeplerianPropagator.java @@ -157,6 +157,7 @@ public class KeplerianPropagator extends AbstractAnalyticalPropagator { } else { states.addValidBefore(state, state.getDate()); } + stateChanged(state); } /** {@inheritDoc} */ diff --git a/src/main/java/org/orekit/propagation/analytical/gnss/IRNSSOrbitalElements.java b/src/main/java/org/orekit/propagation/analytical/gnss/IRNSSOrbitalElements.java new file mode 100644 index 0000000000000000000000000000000000000000..a79d8c5af4ebdc9039623c797f8dda6b5931f378 --- /dev/null +++ b/src/main/java/org/orekit/propagation/analytical/gnss/IRNSSOrbitalElements.java @@ -0,0 +1,60 @@ +/* Copyright 2002-2019 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.propagation.analytical.gnss; + +/** This interface provides the minimal set of orbital elements needed by the {@link IRNSSPropagator}. +* +* @see "Indian Regiona Navigation Satellite System, Signal In Space ICD +* for standard positioning service, version 1.1" +* +* @author Bryan Cazabonne +* @since 10.1 +* +*/ +public interface IRNSSOrbitalElements extends GNSSOrbitalElements { + + /** WGS 84 value of the Earth's universal gravitational parameter for IRNSS user in m³/s². */ + double IRNSS_MU = 3.986005e+14; + + /** Value of Pi for conversion from semicircles to radian. */ + double IRNSS_PI = 3.1415926535898; + + /** Duration of the IRNSS week in seconds. */ + double IRNSS_WEEK_IN_SECONDS = 604800.; + + /** Number of weeks in the IRNSS cycle. */ + int IRNSS_WEEK_NB = 1024; + + /** + * Gets the Issue Of Data Ephemeris and Clock (IODEC). + * + * @return the Issue Of Data Ephemeris and Clock (IODEC) + */ + default int getIODEC() { + return 0; + } + + /** + * Gets the estimated group delay differential TGD for L5-S correction. + * + * @return the estimated group delay differential TGD for L5-S correction (s) + */ + default double getTGD() { + return 0.0; + } + +} diff --git a/src/main/java/org/orekit/propagation/analytical/gnss/IRNSSPropagator.java b/src/main/java/org/orekit/propagation/analytical/gnss/IRNSSPropagator.java new file mode 100644 index 0000000000000000000000000000000000000000..50a6582837ba6eacc549599ac49b312f408d7f8a --- /dev/null +++ b/src/main/java/org/orekit/propagation/analytical/gnss/IRNSSPropagator.java @@ -0,0 +1,163 @@ +/* Copyright 2002-2019 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.propagation.analytical.gnss; + +import org.orekit.attitudes.AttitudeProvider; +import org.orekit.frames.Frame; +import org.orekit.frames.FramesFactory; +import org.orekit.utils.IERSConventions; + +/** + * This class aims at propagating a IRNSS orbit from {@link IRNSSOrbitalElements}. + * + * @see "Indian Regiona Navigation Satellite System, Signal In Space ICD + * for standard positioning service, version 1.1" + * + * @author Bryan Cazabonne + * @since 10.1 + */ +public class IRNSSPropagator extends AbstractGNSSPropagator { + + // Constants + /** WGS 84 value of the earth's rotation rate in rad/s. */ + private static final double IRNSS_AV = 7.2921151467e-5; + + /** Duration of the IRNSS cycle in seconds. */ + private static final double IRNSS_CYCLE_DURATION = IRNSSOrbitalElements.IRNSS_WEEK_IN_SECONDS * + IRNSSOrbitalElements.IRNSS_WEEK_NB; + + // Fields + /** The IRNSS orbital elements used. */ + private final IRNSSOrbitalElements irnssOrbit; + + /** + * This nested class aims at building a IRNSSPropagator. + *

    It implements the classical builder pattern.

    + * + */ + public static class Builder { + + // Required parameter + /** The IRNSS orbital elements. */ + private final IRNSSOrbitalElements orbit; + + // Optional parameters + /** The attitude provider. */ + private AttitudeProvider attitudeProvider = DEFAULT_LAW; + /** The mass. */ + private double mass = DEFAULT_MASS; + /** The ECI frame. */ + private Frame eci = null; + /** The ECEF frame. */ + private Frame ecef = null; + + /** Initializes the builder. + *

    The IRNSS orbital elements is the only requested parameter to build a IRNSSPropagator.

    + *

    The attitude provider is set by default to the + * {@link org.orekit.propagation.Propagator#DEFAULT_LAW DEFAULT_LAW}.
    + * The mass is set by default to the + * {@link org.orekit.propagation.Propagator#DEFAULT_MASS DEFAULT_MASS}.
    + * The ECI frame is set by default to the + * {@link org.orekit.frames.Predefined#EME2000 EME2000 frame}.
    + * The ECEF frame is set by default to the + * {@link org.orekit.frames.Predefined#ITRF_CIO_CONV_2010_SIMPLE_EOP CIO/2010-based ITRF simple EOP}. + *

    + * + * @param irnssOrbElt the IRNSS orbital elements to be used by the IRNSSpropagator. + * @see #attitudeProvider(AttitudeProvider provider) + * @see #mass(double mass) + * @see #eci(Frame inertial) + * @see #ecef(Frame bodyFixed) + */ + public Builder(final IRNSSOrbitalElements irnssOrbElt) { + this.orbit = irnssOrbElt; + this.eci = FramesFactory.getEME2000(); + this.ecef = FramesFactory.getITRF(IERSConventions.IERS_2010, true); + } + + /** Sets the attitude provider. + * + * @param userProvider the attitude provider + * @return the updated builder + */ + public Builder attitudeProvider(final AttitudeProvider userProvider) { + this.attitudeProvider = userProvider; + return this; + } + + /** Sets the mass. + * + * @param userMass the mass (in kg) + * @return the updated builder + */ + public Builder mass(final double userMass) { + this.mass = userMass; + return this; + } + + /** Sets the Earth Centered Inertial frame used for propagation. + * + * @param inertial the ECI frame + * @return the updated builder + */ + public Builder eci(final Frame inertial) { + this.eci = inertial; + return this; + } + + /** Sets the Earth Centered Earth Fixed frame assimilated to the WGS84 ECEF. + * + * @param bodyFixed the ECEF frame + * @return the updated builder + */ + public Builder ecef(final Frame bodyFixed) { + this.ecef = bodyFixed; + return this; + } + + /** Finalizes the build. + * + * @return the built IRNSSPropagator + */ + public IRNSSPropagator build() { + return new IRNSSPropagator(this); + } + } + + /** + * Private constructor. + * + * @param builder the builder + */ + private IRNSSPropagator(final Builder builder) { + super(builder.orbit, builder.attitudeProvider, + builder.eci, builder.ecef, builder.mass, + IRNSS_AV, IRNSS_CYCLE_DURATION, IRNSSOrbitalElements.IRNSS_MU); + // Stores the IRNSS orbital elements + this.irnssOrbit = builder.orbit; + } + + /** + * Gets the underlying IRNSS orbital elements. + * + * @return the underlying IRNSS orbital elements + */ + public IRNSSOrbitalElements getIRNSSOrbitalElements() { + return irnssOrbit; + } + +} diff --git a/src/main/java/org/orekit/propagation/analytical/gnss/SBASOrbitalElements.java b/src/main/java/org/orekit/propagation/analytical/gnss/SBASOrbitalElements.java new file mode 100644 index 0000000000000000000000000000000000000000..5112dd5087c33f5770045b96b23c13cdd40b8964 --- /dev/null +++ b/src/main/java/org/orekit/propagation/analytical/gnss/SBASOrbitalElements.java @@ -0,0 +1,152 @@ +/* Copyright 2002-2019 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.propagation.analytical.gnss; + +import org.orekit.time.TimeStamped; + +/** This interface provides the minimal set of orbital elements needed by the {@link SBASPropagator}. +* +* @author Bryan Cazabonne +* @since 10.1 +* +*/ +public interface SBASOrbitalElements extends TimeStamped { + + /** WGS 84 value of the Earth's universal gravitational parameter for SBAS user in m³/s². */ + double SBAS_MU = 3.986005e+14; + + /** + * Gets the PRN number of the SBAS satellite. + * + * @return the PRN number of the SBAS satellite + */ + int getPRN(); + + /** + * Gets the Reference Week of the SBAS orbit. + * + * @return the Reference Week of the SBAS orbit + */ + int getWeek(); + + /** + * Gets the Reference Time of the SBAS orbit in GPS seconds of the week. + * + * @return the Reference Time of the SBAS orbit (s) + */ + double getTime(); + + /** + * Get the ECEF-X component of satellite coordinates. + * + * @return the ECEF-X component of satellite coordinates (m) + */ + double getX(); + + /** + * Get the ECEF-X component of satellite velocity vector. + * + * @return the the ECEF-X component of satellite velocity vector (m/s) + */ + double getXDot(); + + /** + * Get the ECEF-X component of satellite acceleration vector. + * + * @return the GLONASS ECEF-X component of satellite acceleration vector (m/s²) + */ + double getXDotDot(); + + /** + * Get the ECEF-Y component of satellite coordinates. + * + * @return the ECEF-Y component of satellite coordinates (m) + */ + double getY(); + + /** + * Get the ECEF-Y component of satellite velocity vector. + * + * @return the ECEF-Y component of satellite velocity vector (m/s) + */ + double getYDot(); + + /** + * Get the ECEF-Y component of satellite acceleration vector. + * + * @return the ECEF-Y component of satellite acceleration vector (m/s²) + */ + double getYDotDot(); + + /** + * Get the ECEF-Z component of satellite coordinates. + * + * @return the ECEF-Z component of satellite coordinates (m) + */ + double getZ(); + + /** + * Get the ECEF-Z component of satellite velocity vector. + * + * @return the the ECEF-Z component of satellite velocity vector (m/s) + */ + double getZDot(); + + /** + * Get the ECEF-Z component of satellite acceleration vector. + * + * @return the ECEF-Z component of satellite acceleration vector (m/s²) + */ + double getZDotDot(); + + /** + * Gets the Issue Of Data Navigation (IODN). + * + * @return the IODN + */ + default int getIODN() { + return 0; + } + + /** + * Gets the Zeroth Order Clock Correction. + * + * @return the Zeroth Order Clock Correction (s) + */ + default double getAGf0() { + return 0.0; + } + + /** + * Gets the First Order Clock Correction. + * + * @return the First Order Clock Correction (s/s) + */ + default double getAGf1() { + return 0.0; + } + + /** + * Gets the clock correction reference time toc. + * + * @return the clock correction reference time (s) + */ + default double getToc() { + return 0.0; + } + +} diff --git a/src/main/java/org/orekit/propagation/analytical/gnss/SBASPropagator.java b/src/main/java/org/orekit/propagation/analytical/gnss/SBASPropagator.java new file mode 100644 index 0000000000000000000000000000000000000000..ab3e2419d7150a8cb7f00dc89de763fe54bbaa11 --- /dev/null +++ b/src/main/java/org/orekit/propagation/analytical/gnss/SBASPropagator.java @@ -0,0 +1,296 @@ +/* Copyright 2002-2019 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.propagation.analytical.gnss; + +import org.hipparchus.analysis.differentiation.DSFactory; +import org.hipparchus.analysis.differentiation.DerivativeStructure; +import org.hipparchus.geometry.euclidean.threed.FieldVector3D; +import org.orekit.attitudes.AttitudeProvider; +import org.orekit.errors.OrekitException; +import org.orekit.errors.OrekitMessages; +import org.orekit.frames.Frame; +import org.orekit.frames.FramesFactory; +import org.orekit.orbits.CartesianOrbit; +import org.orekit.orbits.Orbit; +import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.analytical.AbstractAnalyticalPropagator; +import org.orekit.time.AbsoluteDate; +import org.orekit.utils.IERSConventions; +import org.orekit.utils.PVCoordinates; + +/** + * This class aims at propagating a SBAS orbit from {@link SBASOrbitalElements}. + * + * @see "Tyler Reid, Todd Walker, Per Enge, L1/L5 SBAS MOPS Ephemeris Message to + * Support Multiple Orbit Classes, ION ITM, 2013" + * + * @author Bryan Cazabonne + * @since 10.1 + * + */ +public class SBASPropagator extends AbstractAnalyticalPropagator { + + /** The SBAS orbital elements used. */ + private final SBASOrbitalElements sbasOrbit; + + /** The spacecraft mass (kg). */ + private final double mass; + + /** The Earth gravity coefficient used for SBAS propagation. */ + private final double mu; + + /** The ECI frame used for SBAS propagation. */ + private final Frame eci; + + /** The ECEF frame used for SBAS propagation. */ + private final Frame ecef; + + /** Factory for the DerivativeStructure instances. */ + private final DSFactory factory; + + /** + * This nested class aims at building a SBASPropagator. + *

    It implements the classical builder pattern.

    + * + */ + public static class Builder { + + /** The SBAS orbital elements. */ + private final SBASOrbitalElements orbit; + + /** The Earth gravity coefficient used for SBAS propagation. */ + private double mu; + + /** The attitude provider. */ + private AttitudeProvider attitudeProvider = DEFAULT_LAW; + + /** The mass. */ + private double mass = DEFAULT_MASS; + + /** The ECI frame. */ + private Frame eci = null; + + /** The ECEF frame. */ + private Frame ecef = null; + + /** Initializes the builder. + *

    The SBAS orbital elements is the only requested parameter to build a SBASPropagator.

    + *

    The attitude provider is set by default to the + * {@link org.orekit.propagation.Propagator#DEFAULT_LAW DEFAULT_LAW}.
    + * The Earth gravity coefficient is set by default to the + * {@link org.orekit.propagation.analytical.gnss.SBASOrbitalElements#SBAS_MU SBAS_MU}.
    + * The mass is set by default to the + * {@link org.orekit.propagation.Propagator#DEFAULT_MASS DEFAULT_MASS}.
    + * The ECI frame is set by default to the + * {@link org.orekit.frames.Predefined#EME2000 EME2000 frame}.
    + * The ECEF frame is set by default to the + * {@link org.orekit.frames.Predefined#ITRF_CIO_CONV_2010_SIMPLE_EOP CIO/2010-based ITRF simple EOP}. + *

    + * + * @param sbasOrbElt the SBAS orbital elements to be used by the SBAS propagator. + * @see #attitudeProvider(AttitudeProvider provider) + * @see #mu(double coefficient) + * @see #mass(double mass) + * @see #eci(Frame inertial) + * @see #ecef(Frame bodyFixed) + */ + public Builder(final SBASOrbitalElements sbasOrbElt) { + this.orbit = sbasOrbElt; + this.eci = FramesFactory.getEME2000(); + this.ecef = FramesFactory.getITRF(IERSConventions.IERS_2010, true); + this.mu = SBASOrbitalElements.SBAS_MU; + } + + /** Sets the attitude provider. + * + * @param userProvider the attitude provider + * @return the updated builder + */ + public Builder attitudeProvider(final AttitudeProvider userProvider) { + this.attitudeProvider = userProvider; + return this; + } + + /** Sets the Earth gravity coefficient. + * + * @param coefficient the Earth gravity coefficient + * @return the updated builder + */ + public Builder mu(final double coefficient) { + this.mu = coefficient; + return this; + } + + /** Sets the mass. + * + * @param userMass the mass (in kg) + * @return the updated builder + */ + public Builder mass(final double userMass) { + this.mass = userMass; + return this; + } + + /** Sets the Earth Centered Inertial frame used for propagation. + * + * @param inertial the ECI frame + * @return the updated builder + */ + public Builder eci(final Frame inertial) { + this.eci = inertial; + return this; + } + + /** Sets the Earth Centered Earth Fixed frame assimilated to the WGS84 ECEF. + * + * @param bodyFixed the ECEF frame + * @return the updated builder + */ + public Builder ecef(final Frame bodyFixed) { + this.ecef = bodyFixed; + return this; + } + + /** Finalizes the build. + * + * @return the built SBASPropagator + */ + public SBASPropagator build() { + return new SBASPropagator(this); + } + + } + + /** + * Private constructor. + * @param builder the builder + */ + private SBASPropagator(final Builder builder) { + super(builder.attitudeProvider); + // Stores the SBAS orbital elements + this.sbasOrbit = builder.orbit; + // Sets the start date as the date of the orbital elements + setStartDate(sbasOrbit.getDate()); + // Sets the mu + this.mu = builder.mu; + // Sets the mass + this.mass = builder.mass; + // Sets the Earth Centered Inertial frame + this.eci = builder.eci; + // Sets the Earth Centered Earth Fixed frame + this.ecef = builder.ecef; + + this.factory = new DSFactory(1, 2); + } + + /** + * Gets the PVCoordinates of the GNSS SV in {@link #getECEF() ECEF frame}. + * + *

    The algorithm uses automatic differentiation to compute velocity and + * acceleration.

    + * + * @param date the computation date + * @return the GNSS SV PVCoordinates in {@link #getECEF() ECEF frame} + */ + public PVCoordinates propagateInEcef(final AbsoluteDate date) { + // Duration from SBAS ephemeris Reference date + final DerivativeStructure dt = factory.variable(0, getDT(date)); + // Satellite coordinates + final DerivativeStructure x = dt.multiply(dt.multiply(0.5 * sbasOrbit.getXDotDot()).add(sbasOrbit.getXDot())).add(sbasOrbit.getX()); + final DerivativeStructure y = dt.multiply(dt.multiply(0.5 * sbasOrbit.getYDotDot()).add(sbasOrbit.getYDot())).add(sbasOrbit.getY()); + final DerivativeStructure z = dt.multiply(dt.multiply(0.5 * sbasOrbit.getZDotDot()).add(sbasOrbit.getZDot())).add(sbasOrbit.getZ()); + // Returns the Earth-fixed coordinates + final FieldVector3D positionwithDerivatives = + new FieldVector3D<>(x, y, z); + return new PVCoordinates(positionwithDerivatives); + } + + /** {@inheritDoc} */ + protected Orbit propagateOrbit(final AbsoluteDate date) { + // Gets the PVCoordinates in ECEF frame + final PVCoordinates pvaInECEF = propagateInEcef(date); + // Transforms the PVCoordinates to ECI frame + final PVCoordinates pvaInECI = ecef.getTransformTo(eci, date).transformPVCoordinates(pvaInECEF); + // Returns the Cartesian orbit + return new CartesianOrbit(pvaInECI, eci, date, mu); + } + + /** + * Get the Earth gravity coefficient used for SBAS propagation. + * @return the Earth gravity coefficient. + */ + public double getMU() { + return mu; + } + + /** + * Gets the Earth Centered Inertial frame used to propagate the orbit. + * + * @return the ECI frame + */ + public Frame getECI() { + return eci; + } + + /** + * Gets the Earth Centered Earth Fixed frame used to propagate GNSS orbits. + * + * @return the ECEF frame + */ + public Frame getECEF() { + return ecef; + } + + /** + * Get the underlying SBAS orbital elements. + * + * @return the underlying SBAS orbital elements + */ + public SBASOrbitalElements getSBASOrbitalElements() { + return sbasOrbit; + } + + /** {@inheritDoc} */ + public Frame getFrame() { + return eci; + } + + /** {@inheritDoc} */ + public void resetInitialState(final SpacecraftState state) { + throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE); + } + + /** {@inheritDoc} */ + protected double getMass(final AbsoluteDate date) { + return mass; + } + + /** {@inheritDoc} */ + protected void resetIntermediateState(final SpacecraftState state, final boolean forward) { + throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE); + } + + /** Get the duration from SBAS Reference epoch. + * @param date the considered date + * @return the duration from SBAS orbit Reference epoch (s) + */ + private double getDT(final AbsoluteDate date) { + // Time from ephemeris reference epoch + return date.durationFrom(sbasOrbit.getDate()); + } + +} diff --git a/src/main/java/org/orekit/propagation/conversion/AbstractPropagatorBuilder.java b/src/main/java/org/orekit/propagation/conversion/AbstractPropagatorBuilder.java index 51cac983f67382c4dfeac71eb692c451fa661bc4..4220b14077c3eb381326af42536db1c3c3b997a3 100644 --- a/src/main/java/org/orekit/propagation/conversion/AbstractPropagatorBuilder.java +++ b/src/main/java/org/orekit/propagation/conversion/AbstractPropagatorBuilder.java @@ -16,6 +16,7 @@ */ package org.orekit.propagation.conversion; +import java.util.ArrayList; import java.util.List; import org.hipparchus.exception.LocalizedCoreFormats; @@ -26,6 +27,7 @@ import org.orekit.frames.Frame; import org.orekit.orbits.Orbit; import org.orekit.orbits.OrbitType; import org.orekit.orbits.PositionAngle; +import org.orekit.propagation.integration.AdditionalEquations; import org.orekit.time.AbsoluteDate; import org.orekit.utils.ParameterDriver; import org.orekit.utils.ParameterDriversList; @@ -70,6 +72,9 @@ public abstract class AbstractPropagatorBuilder implements PropagatorBuilder { /** Position scale to use for the orbital drivers. */ private final double positionScale; + /** Additional equations. */ + private List additionalEquations; + /** Build a new instance. *

    * The template orbit is used as a model to {@link @@ -110,6 +115,8 @@ public abstract class AbstractPropagatorBuilder implements PropagatorBuilder { driver.setSelected(true); } + this.additionalEquations = new ArrayList(); + if (addDriverForCentralAttraction) { final ParameterDriver muDriver = new ParameterDriver(NewtonianAttraction.CENTRAL_ATTRACTION_COEFFICIENT, mu, MU_SCALE, 0, Double.POSITIVE_INFINITY); @@ -293,4 +300,23 @@ public abstract class AbstractPropagatorBuilder implements PropagatorBuilder { // Change the initial orbit date in the builder this.initialOrbitDate = newOrbit.getDate(); } + + /** Add a set of user-specified equations to be integrated along with the orbit propagation (author Shiva Iyer). + * @param additional additional equations + * @since 10.1 + */ + public void addAdditionalEquations(final AdditionalEquations additional) { + + additionalEquations.add(additional); + + } + + /** Get the list of additional equations. + * @return the list of additional equations + * @since 10.1 + */ + protected List getAdditionalEquations() { + return additionalEquations; + } + } diff --git a/src/main/java/org/orekit/propagation/conversion/DSSTPropagatorBuilder.java b/src/main/java/org/orekit/propagation/conversion/DSSTPropagatorBuilder.java index ff8f90e7e4504fa6ff4c2c164e6d51988c1bf751..9a7475cb71d23212e766eec61b33ab19793162c0 100644 --- a/src/main/java/org/orekit/propagation/conversion/DSSTPropagatorBuilder.java +++ b/src/main/java/org/orekit/propagation/conversion/DSSTPropagatorBuilder.java @@ -34,8 +34,10 @@ import org.orekit.orbits.PositionAngle; import org.orekit.propagation.PropagationType; import org.orekit.propagation.Propagator; import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.integration.AdditionalEquations; import org.orekit.propagation.semianalytical.dsst.DSSTPropagator; import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel; +import org.orekit.propagation.semianalytical.dsst.forces.DSSTNewtonianAttraction; import org.orekit.utils.ParameterDriver; import org.orekit.utils.ParameterDriversList; @@ -163,7 +165,27 @@ public class DSSTPropagatorBuilder extends AbstractPropagatorBuilder implements * @param model perturbing {@link DSSTForceModel} to add */ public void addForceModel(final DSSTForceModel model) { - forceModels.add(model); + if (model instanceof DSSTNewtonianAttraction) { + // we want to add the central attraction force model + if (hasNewtonianAttraction()) { + // there is already a central attraction model, replace it + forceModels.set(forceModels.size() - 1, model); + } else { + // there are no central attraction model yet, add it at the end of the list + forceModels.add(model); + } + } else { + // we want to add a perturbing force model + if (hasNewtonianAttraction()) { + // insert the new force model before Newtonian attraction, + // which should always be the last one in the list + forceModels.add(forceModels.size() - 1, model); + } else { + // we only have perturbing force models up to now, just append at the end of the list + forceModels.add(model); + } + } + for (final ParameterDriver driver : model.getParametersDrivers()) { addSupportedParameter(driver); } @@ -179,11 +201,23 @@ public class DSSTPropagatorBuilder extends AbstractPropagatorBuilder implements final DSSTPropagator propagator = new DSSTPropagator(builder.buildIntegrator(orbit, OrbitType.EQUINOCTIAL), propagationType); propagator.setAttitudeProvider(attProvider); + + // Configure force models + if (!hasNewtonianAttraction()) { + // There are no central attraction model yet, add it at the end of the list + addForceModel(new DSSTNewtonianAttraction(orbit.getMu())); + } for (DSSTForceModel model : forceModels) { propagator.addForceModel(model); } + propagator.setInitialState(state, stateType); + // Add additional equations to the propagator + for (AdditionalEquations equation: getAdditionalEquations()) { + propagator.addAdditionalEquations(equation); + } + return propagator; } @@ -209,4 +243,15 @@ public class DSSTPropagatorBuilder extends AbstractPropagatorBuilder implements propagationType, stateType); } + /** Check if Newtonian attraction force model is available. + *

    + * Newtonian attraction is always the last force model in the list. + *

    + * @return true if Newtonian attraction force model is available + */ + private boolean hasNewtonianAttraction() { + final int last = forceModels.size() - 1; + return last >= 0 && forceModels.get(last) instanceof DSSTNewtonianAttraction; + } + } diff --git a/src/main/java/org/orekit/propagation/conversion/NumericalPropagatorBuilder.java b/src/main/java/org/orekit/propagation/conversion/NumericalPropagatorBuilder.java index 6e47997720b1c6fe83818dba12fa3612151faf98..447697cc8038e2ad70da9cd1dab3d0c7f891667f 100644 --- a/src/main/java/org/orekit/propagation/conversion/NumericalPropagatorBuilder.java +++ b/src/main/java/org/orekit/propagation/conversion/NumericalPropagatorBuilder.java @@ -28,10 +28,12 @@ import org.orekit.estimation.measurements.ObservedMeasurement; import org.orekit.estimation.sequential.CovarianceMatrixProvider; import org.orekit.estimation.sequential.KalmanModel; import org.orekit.forces.ForceModel; +import org.orekit.forces.gravity.NewtonianAttraction; import org.orekit.orbits.Orbit; import org.orekit.orbits.PositionAngle; import org.orekit.propagation.Propagator; import org.orekit.propagation.SpacecraftState; +import org.orekit.propagation.integration.AdditionalEquations; import org.orekit.propagation.numerical.NumericalPropagator; import org.orekit.utils.ParameterDriver; import org.orekit.utils.ParameterDriversList; @@ -122,7 +124,27 @@ public class NumericalPropagatorBuilder extends AbstractPropagatorBuilder implem * @param model perturbing {@link ForceModel} to add */ public void addForceModel(final ForceModel model) { - forceModels.add(model); + if (model instanceof NewtonianAttraction) { + // we want to add the central attraction force model + if (hasNewtonianAttraction()) { + // there is already a central attraction model, replace it + forceModels.set(forceModels.size() - 1, model); + } else { + // there are no central attraction model yet, add it at the end of the list + forceModels.add(model); + } + } else { + // we want to add a perturbing force model + if (hasNewtonianAttraction()) { + // insert the new force model before Newtonian attraction, + // which should always be the last one in the list + forceModels.add(forceModels.size() - 1, model); + } else { + // we only have perturbing force models up to now, just append at the end of the list + forceModels.add(model); + } + } + for (final ParameterDriver driver : model.getParametersDrivers()) { addSupportedParameter(driver); } @@ -172,11 +194,23 @@ public class NumericalPropagatorBuilder extends AbstractPropagatorBuilder implem propagator.setOrbitType(getOrbitType()); propagator.setPositionAngleType(getPositionAngle()); propagator.setAttitudeProvider(attProvider); + + // Configure force models + if (!hasNewtonianAttraction()) { + // There are no central attraction model yet, add it at the end of the list + addForceModel(new NewtonianAttraction(orbit.getMu())); + } for (ForceModel model : forceModels) { propagator.addForceModel(model); } + propagator.resetInitialState(state); + // Add additional equations to the propagator + for (AdditionalEquations equation: getAdditionalEquations()) { + propagator.addAdditionalEquations(equation); + } + return propagator; } @@ -195,4 +229,15 @@ public class NumericalPropagatorBuilder extends AbstractPropagatorBuilder implem return new KalmanModel(propagatorBuilders, covarianceMatricesProviders, estimatedMeasurementsParameters); } + /** Check if Newtonian attraction force model is available. + *

    + * Newtonian attraction is always the last force model in the list. + *

    + * @return true if Newtonian attraction force model is available + */ + private boolean hasNewtonianAttraction() { + final int last = forceModels.size() - 1; + return last >= 0 && forceModels.get(last) instanceof NewtonianAttraction; + } + } diff --git a/src/main/java/org/orekit/propagation/events/CircularFieldOfViewDetector.java b/src/main/java/org/orekit/propagation/events/CircularFieldOfViewDetector.java index 179f9708440f8900b4db05fcb4db2ba6ebc22a73..03204e08954ef60d56fb5aa84cb07f21e6f1f0c1 100644 --- a/src/main/java/org/orekit/propagation/events/CircularFieldOfViewDetector.java +++ b/src/main/java/org/orekit/propagation/events/CircularFieldOfViewDetector.java @@ -18,7 +18,7 @@ package org.orekit.propagation.events; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.ode.events.Action; -import org.hipparchus.util.FastMath; +import org.orekit.geometry.fov.CircularFieldOfView; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.events.handlers.EventHandler; import org.orekit.propagation.events.handlers.StopOnDecreasing; @@ -34,23 +34,13 @@ import org.orekit.utils.PVCoordinatesProvider; * @see FieldOfViewDetector * @see VisibilityTrigger * @author Véronique Pommier-Maurussane + * @deprecated as of 10.1, replaced by {@link FieldOfViewDetector} and {@link CircularFieldOfView} */ +@Deprecated public class CircularFieldOfViewDetector extends AbstractDetector { - /** Position/velocity provider of the considered target. */ - private final PVCoordinatesProvider targetPVProvider; - - /** Radius of the target, considered to be a spherical body (m). */ - private final double radiusTarget; - - /** Visibility trigger for spherical bodies. */ - private final VisibilityTrigger trigger; - - /** Direction of the FOV center. */ - private final Vector3D center; - - /** FOV half aperture angle. */ - private final double halfAperture; + /** General detector. */ + private final FieldOfViewDetector generalDetector; /** Build a new instance. *

    The maximal interval between distance to FOV boundary checks should @@ -108,41 +98,57 @@ public class CircularFieldOfViewDetector extends AbstractDetector handler, final PVCoordinatesProvider pvTarget, final double radiusTarget, final VisibilityTrigger trigger, final Vector3D center, final double halfAperture) { + this(maxCheck, threshold, maxIter, handler, + new FieldOfViewDetector(pvTarget, radiusTarget, trigger, + new CircularFieldOfView(center, halfAperture, 0.0))); + } + + /** Private constructor with full parameters. + *

    + * This constructor is private as users are expected to use the builder + * API with the various {@code withXxx()} methods to set up the instance + * in a readable manner without using a huge amount of parameters. + *

    + * @param maxCheck maximum checking interval (s) + * @param threshold convergence threshold (s) + * @param maxIter maximum number of iterations in the event time search + * @param handler event handler to call at event occurrences + * @param generalDetector general detector + * @since 10.1 + */ + private CircularFieldOfViewDetector(final double maxCheck, final double threshold, + final int maxIter, final EventHandler handler, + final FieldOfViewDetector generalDetector) { super(maxCheck, threshold, maxIter, handler); - this.targetPVProvider = pvTarget; - this.radiusTarget = radiusTarget; - this.trigger = trigger; - this.center = center; - this.halfAperture = halfAperture; + this.generalDetector = generalDetector; } /** {@inheritDoc} */ @Override protected CircularFieldOfViewDetector create(final double newMaxCheck, final double newThreshold, final int newMaxIter, final EventHandler newHandler) { - return new CircularFieldOfViewDetector(newMaxCheck, newThreshold, newMaxIter, newHandler, - targetPVProvider, radiusTarget, trigger, center, halfAperture); + return new CircularFieldOfViewDetector(newMaxCheck, newThreshold, newMaxIter, newHandler, generalDetector); } /** Get the position/velocity provider of the target . * @return the position/velocity provider of the target */ public PVCoordinatesProvider getPVTarget() { - return targetPVProvider; + return generalDetector.getPVTarget(); } /** Get the direction of FOV center. * @return the direction of FOV center */ public Vector3D getCenter() { - return center; + return ((CircularFieldOfView) generalDetector.getFOV()).getCenter(); } /** Get FOV half aperture angle. * @return the FOV half aperture angle */ public double getHalfAperture() { - return halfAperture; + return ((CircularFieldOfView) generalDetector.getFOV()).getHalfAperture(); } /** {@inheritDoc} @@ -154,17 +160,7 @@ public class CircularFieldOfViewDetector extends AbstractDetector */ public double g(final SpacecraftState s) { - - // Compute target position/velocity at date in spacecraft frame - final Vector3D targetPosInert = new Vector3D(1, targetPVProvider.getPVCoordinates(s.getDate(), s.getFrame()).getPosition(), - -1, s.getPVCoordinates().getPosition()); - final Vector3D targetPosSat = s.getAttitude().getRotation().applyTo(targetPosInert); - final double angularRadius = FastMath.asin(radiusTarget / targetPosSat.getNorm()); - - // Target is in the field of view if the absolute value that angle is smaller than FOV half aperture. - // g function value is the difference between FOV half aperture and the absolute value of the angle between - // target direction and field of view center. It is positive inside the FOV and negative outside. - return halfAperture - Vector3D.angle(targetPosSat, center) - FastMath.copySign(angularRadius, trigger.getSign()); + return generalDetector.g(s); } } diff --git a/src/main/java/org/orekit/propagation/events/FieldOfView.java b/src/main/java/org/orekit/propagation/events/FieldOfView.java index 480b5d09ec0af88c652bffcbc15951fc1bb9bf1c..a4f4293367975ad365a2aa6c3e3559e5acc1c6e0 100644 --- a/src/main/java/org/orekit/propagation/events/FieldOfView.java +++ b/src/main/java/org/orekit/propagation/events/FieldOfView.java @@ -16,30 +16,17 @@ */ package org.orekit.propagation.events; -import java.util.ArrayList; -import java.util.List; - import org.hipparchus.exception.LocalizedCoreFormats; -import org.hipparchus.geometry.enclosing.EnclosingBall; -import org.hipparchus.geometry.euclidean.threed.Line; import org.hipparchus.geometry.euclidean.threed.Rotation; import org.hipparchus.geometry.euclidean.threed.RotationConvention; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.geometry.partitioning.Region; import org.hipparchus.geometry.partitioning.RegionFactory; -import org.hipparchus.geometry.spherical.twod.Edge; -import org.hipparchus.geometry.spherical.twod.S2Point; import org.hipparchus.geometry.spherical.twod.Sphere2D; import org.hipparchus.geometry.spherical.twod.SphericalPolygonsSet; -import org.hipparchus.geometry.spherical.twod.Vertex; import org.hipparchus.util.FastMath; -import org.hipparchus.util.MathUtils; -import org.orekit.bodies.GeodeticPoint; -import org.orekit.bodies.OneAxisEllipsoid; import org.orekit.errors.OrekitException; -import org.orekit.errors.OrekitMessages; -import org.orekit.frames.Frame; -import org.orekit.frames.Transform; +import org.orekit.geometry.fov.PolygonalFieldOfView; /** Class representing a spacecraft sensor Field Of View. *

    Fields Of View are zones defined on the unit sphere centered on the @@ -48,17 +35,10 @@ import org.orekit.frames.Transform; * @see org.orekit.propagation.events.FootprintOverlapDetector * @author Luc Maisonobe * @since 7.1 + * @deprecated as of 10.1, replaced by {@link PolygonalFieldOfView} */ -public class FieldOfView { - - /** Spherical zone. */ - private final SphericalPolygonsSet zone; - - /** Margin to apply to the zone. */ - private final double margin; - - /** Spherical cap surrounding the zone. */ - private final EnclosingBall cap; +@Deprecated +public class FieldOfView extends PolygonalFieldOfView { /** Build a new instance. * @param zone interior of the Field Of View, in spacecraft frame @@ -67,9 +47,7 @@ public class FieldOfView { * zone are still visible) */ public FieldOfView(final SphericalPolygonsSet zone, final double margin) { - this.zone = zone; - this.margin = margin; - this.cap = zone.getEnclosingCap(); + super(zone, margin); } /** Build a Field Of View with dihedral shape (i.e. rectangular shape). @@ -90,18 +68,7 @@ public class FieldOfView { final Vector3D axis1, final double halfAperture1, final Vector3D axis2, final double halfAperture2, final double margin) { - - // build zone - final RegionFactory factory = new RegionFactory(); - final double tolerance = FastMath.max(FastMath.ulp(2.0 * FastMath.PI), - 1.0e-12 * FastMath.max(halfAperture1, halfAperture2)); - final Region dihedra1 = buildDihedra(factory, tolerance, center, axis1, halfAperture1); - final Region dihedra2 = buildDihedra(factory, tolerance, center, axis2, halfAperture2); - this.zone = (SphericalPolygonsSet) factory.intersection(dihedra1, dihedra2); - - this.margin = margin; - this.cap = zone.getEnclosingCap(); - + super(createPolygon(center, axis1, halfAperture1, axis2, halfAperture2), margin); } /** Build Field Of View with a regular polygon shape. @@ -116,28 +83,32 @@ public class FieldOfView { */ public FieldOfView(final Vector3D center, final Vector3D meridian, final double insideRadius, final int n, final double margin) { + super(center, + PolygonalFieldOfView.DefiningConeType.INSIDE_CONE_TOUCHING_POLYGON_AT_EDGES_MIDDLE, + meridian, insideRadius, n, margin); + } - // convert the representation based on middle edge points - // to Hipparchus convention based on vertices - final Rotation r = new Rotation(center, MathUtils.TWO_PI / n, - RotationConvention.VECTOR_OPERATOR); - final Vector3D orthogonal = Vector3D.crossProduct(Vector3D.crossProduct(center, meridian), center); - final Vector3D firstEdgeNormal = new Vector3D( FastMath.sin(insideRadius), center.normalize(), - -FastMath.cos(insideRadius), orthogonal.normalize()); - final Vector3D secondEdgeNormal = r.applyTo(firstEdgeNormal); - final Vector3D vertex = Vector3D.crossProduct(firstEdgeNormal, secondEdgeNormal); - final double outsideRadius = Vector3D.angle(center, vertex); - this.zone = new SphericalPolygonsSet(center, vertex, outsideRadius, n, 1.0e-12 * insideRadius); - - this.margin = margin; - - final S2Point[] support = new S2Point[n]; - support[0] = new S2Point(vertex); - for (int i = 1; i < n; ++i) { - support[i] = new S2Point(r.applyTo(support[i - 1].getVector())); - } - this.cap = new EnclosingBall(new S2Point(center), outsideRadius, support); - + /** Create polygon. + * @param center Direction of the FOV center, in spacecraft frame + * @param axis1 FOV dihedral axis 1, in spacecraft frame + * @param halfAperture1 FOV dihedral half aperture angle 1, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @param axis2 FOV dihedral axis 2, in spacecraft frame + * @param halfAperture2 FOV dihedral half aperture angle 2, + * must be less than π/2, i.e. full dihedra must be smaller then + * an hemisphere + * @return built polygon + */ + private static SphericalPolygonsSet createPolygon(final Vector3D center, + final Vector3D axis1, final double halfAperture1, + final Vector3D axis2, final double halfAperture2) { + final RegionFactory factory = new RegionFactory(); + final double tolerance = FastMath.max(FastMath.ulp(2.0 * FastMath.PI), + 1.0e-12 * FastMath.max(halfAperture1, halfAperture2)); + final Region dihedra1 = buildDihedra(factory, tolerance, center, axis1, halfAperture1); + final Region dihedra2 = buildDihedra(factory, tolerance, center, axis2, halfAperture2); + return (SphericalPolygonsSet) factory.intersection(dihedra1, dihedra2); } /** Build a dihedra. @@ -150,9 +121,9 @@ public class FieldOfView { * an hemisphere * @return dihedra */ - private Region buildDihedra(final RegionFactory factory, - final double tolerance, final Vector3D center, - final Vector3D axis, final double halfAperture) { + private static Region buildDihedra(final RegionFactory factory, + final double tolerance, final Vector3D center, + final Vector3D axis, final double halfAperture) { if (halfAperture > 0.5 * FastMath.PI) { throw new OrekitException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, halfAperture, 0.0, 0.5 * FastMath.PI); @@ -168,214 +139,4 @@ public class FieldOfView { } - /** Get the interior zone. - * @return the interior zone - */ - public SphericalPolygonsSet getZone() { - return zone; - } - - /** Get the angular margin to apply (radians). - * @return the angular margin to apply (radians) - */ - public double getMargin() { - return margin; - } - - /** Get the angular offset of target point with respect to the Field Of View Boundary. - *

    - * The offset is roughly an angle with respect to the closest boundary point, - * corrected by the margin and using some approximation far from the Field Of View. - * It is positive if the target is outside of the Field Of view, negative inside, - * and zero if the point is exactly on the boundary (always taking the margin - * into account). - *

    - *

    - * As Field Of View can have complex shapes that may require long computation, - * when the target point can be proven to be outside of the Field Of View, a - * faster but approximate computation is done, that underestimate the offset. - * This approximation is only performed about 0.01 radians outside of the zone - * and is designed to still return a positive value if the full accurate computation - * would return a positive value. When target point is close to the zone (and - * furthermore when it is inside the zone), the full accurate computation is - * performed. This setup allows this offset to be used as a reliable way to - * detect Field Of View boundary crossings, which correspond to sign changes of - * the offset. - *

    - * @param lineOfSight line of sight from the center of the Field Of View support - * unit sphere to the target in Field Of View canonical frame - * @return an angular offset negative if the target is visible within the Field Of - * View and positive if it is outside of the Field Of View, including the margin - * (note that this cannot take into account interposing bodies) - */ - public double offsetFromBoundary(final Vector3D lineOfSight) { - - final S2Point los = new S2Point(lineOfSight); - - // for faster computation, we start using only the surrounding cap, to filter out - // far away points (which correspond to most of the points if the Field Of View is small) - final double crudeDistance = cap.getCenter().distance(los) - cap.getRadius(); - if (crudeDistance - margin > FastMath.max(FastMath.abs(margin), 0.01)) { - // we know we are strictly outside of the zone, - // use the crude distance to compute the (positive) return value - return crudeDistance - margin; - } - - // we are close, we need to compute carefully the exact offset; - // we project the point to the closest zone boundary - return zone.projectToBoundary(los).getOffset() - margin; - - } - - /** Get the footprint of the field Of View on ground. - *

    - * This method assumes the Field Of View is centered on some carrier, - * which will typically be a spacecraft or a ground station antenna. - * The points in the footprint boundary loops are all at altitude zero - * with respect to the ellipsoid, they correspond either to projection - * on ground of the edges of the Field Of View, or to points on the body - * limb if the Field Of View goes past horizon. The points on the limb - * see the carrier origin at zero elevation. If the Field Of View is so - * large it contains entirely the body, all points will correspond to - * points at limb. If the Field Of View looks away from body, the - * boundary loops will be an empty list. The points within footprint - * the loops are sorted in trigonometric order as seen from the carrier. - * This implies that someone traveling on ground from one point to the - * next one will have the points visible from the carrier on his left - * hand side, and the points not visible from the carrier on his right - * hand side. - *

    - *

    - * The truncation of Field Of View at limb can induce strange results - * for complex Fields Of View. If for example a Field Of View is a - * ring with a hole and part of the ring goes past horizon, then instead - * of having a single loop with a C-shaped boundary, the method will - * still return two loops truncated at the limb, one clockwise and one - * counterclockwise, hence "closing" the C-shape twice. This behavior - * is considered acceptable. - *

    - *

    - * If the carrier is a spacecraft, then the {@code fovToBody} transform - * can be computed from a {@link org.orekit.propagation.SpacecraftState} - * as follows: - *

    - *
    -     * Transform inertToBody = state.getFrame().getTransformTo(body.getBodyFrame(), state.getDate());
    -     * Transform fovToBody   = new Transform(state.getDate(),
    -     *                                       state.toTransform().getInverse(),
    -     *                                       inertToBody);
    -     * 
    - *

    - * If the carrier is a ground station, located using a topocentric frame - * and managing its pointing direction using a transform between the - * dish frame and the topocentric frame, then the {@code fovToBody} transform - * can be computed as follows: - *

    - *
    -     * Transform topoToBody = topocentricFrame.getTransformTo(body.getBodyFrame(), date);
    -     * Transform topoToDish = ...
    -     * Transform fovToBody  = new Transform(date,
    -     *                                      topoToDish.getInverse(),
    -     *                                      topoToBody);
    -     * 
    - *

    - * Only the raw zone is used, the angular margin is ignored here. - *

    - * @param fovToBody transform between the frame in which the Field Of View - * is defined and body frame. - * @param body body surface the Field Of View will be projected on - * @param angularStep step used for boundary loops sampling (radians) - * @return list footprint boundary loops (there may be several independent - * loops if the Field Of View shape is complex) - */ - List> getFootprint(final Transform fovToBody, final OneAxisEllipsoid body, - final double angularStep) { - - final Frame bodyFrame = body.getBodyFrame(); - final Vector3D position = fovToBody.transformPosition(Vector3D.ZERO); - final double r = position.getNorm(); - if (body.isInside(position)) { - throw new OrekitException(OrekitMessages.POINT_INSIDE_ELLIPSOID); - } - - final List> footprint = new ArrayList>(); - - final List boundary = zone.getBoundaryLoops(); - for (final Vertex loopStart : boundary) { - int count = 0; - final List loop = new ArrayList(); - boolean intersectionsFound = false; - for (Edge edge = loopStart.getOutgoing(); - count == 0 || edge.getStart() != loopStart; - edge = edge.getEnd().getOutgoing()) { - ++count; - final int n = (int) FastMath.ceil(edge.getLength() / angularStep); - final double delta = edge.getLength() / n; - for (int i = 0; i < n; ++i) { - final Vector3D awaySC = new Vector3D(r, edge.getPointAt(i * delta)); - final Vector3D awayBody = fovToBody.transformPosition(awaySC); - final Line lineOfSight = new Line(position, awayBody, 1.0e-3); - GeodeticPoint gp = body.getIntersectionPoint(lineOfSight, position, - bodyFrame, null); - if (gp != null && - Vector3D.dotProduct(awayBody.subtract(position), - body.transform(gp).subtract(position)) < 0) { - // the intersection is in fact on the half-line pointing - // towards the back side, it is a spurious intersection - gp = null; - } - - if (gp != null) { - // the line of sight does intersect the body - intersectionsFound = true; - } else { - // the line of sight does not intersect body - // we use a point on the limb - gp = body.transform(body.pointOnLimb(position, awayBody), bodyFrame, null); - } - - // add the point in front of the list - // (to ensure the loop will be in trigonometric orientation) - loop.add(0, gp); - - } - } - - if (intersectionsFound) { - // at least some of the points did intersect the body, - // this loop contributes to the footprint - footprint.add(loop); - } - - } - - if (footprint.isEmpty()) { - // none of the Field Of View loops cross the body - // either the body is outside of Field Of View, or it is fully contained - // we check the center - final Vector3D bodyCenter = fovToBody.getInverse().transformPosition(Vector3D.ZERO); - if (zone.checkPoint(new S2Point(bodyCenter)) != Region.Location.OUTSIDE) { - // the body is fully contained in the Field Of View - // we use the full limb as the footprint - final Vector3D x = bodyCenter.orthogonal(); - final Vector3D y = Vector3D.crossProduct(bodyCenter, x).normalize(); - final double sinEta = body.getEquatorialRadius() / r; - final double sinEta2 = sinEta * sinEta; - final double cosAlpha = (FastMath.cos(angularStep) + sinEta2 - 1) / sinEta2; - final int n = (int) FastMath.ceil(MathUtils.TWO_PI / FastMath.acos(cosAlpha)); - final double delta = MathUtils.TWO_PI / n; - final List loop = new ArrayList(n); - for (int i = 0; i < n; ++i) { - final Vector3D outside = new Vector3D(r * FastMath.cos(i * delta), x, - r * FastMath.sin(i * delta), y); - loop.add(body.transform(body.pointOnLimb(position, outside), bodyFrame, null)); - } - footprint.add(loop); - } - } - - return footprint; - - } - } diff --git a/src/main/java/org/orekit/propagation/events/FieldOfViewDetector.java b/src/main/java/org/orekit/propagation/events/FieldOfViewDetector.java index 7aa996e3a157f953fbc684b8f398ad56c077c033..147d496fe15a0d46f0ffd9be60c4f0d2e7320779 100644 --- a/src/main/java/org/orekit/propagation/events/FieldOfViewDetector.java +++ b/src/main/java/org/orekit/propagation/events/FieldOfViewDetector.java @@ -19,6 +19,7 @@ package org.orekit.propagation.events; import org.hipparchus.geometry.euclidean.threed.Vector3D; import org.hipparchus.ode.events.Action; import org.hipparchus.util.FastMath; +import org.orekit.geometry.fov.FieldOfView; import org.orekit.propagation.SpacecraftState; import org.orekit.propagation.events.handlers.EventHandler; import org.orekit.propagation.events.handlers.StopOnIncreasing; @@ -68,7 +69,7 @@ public class FieldOfViewDetector extends AbstractDetector { * otherwise some short passes could be missed.

    * @param pvTarget Position/velocity provider of the considered target * @param radiusTarget radius of the target, considered to be a spherical body (m) - * @param trigger visibility trigger for spherical bodie + * @param trigger visibility trigger for spherical bodies * @param fov Field Of View * @since 10.0 */ @@ -91,7 +92,7 @@ public class FieldOfViewDetector extends AbstractDetector { * @param handler event handler to call at event occurrences * @param pvTarget Position/velocity provider of the considered target * @param radiusTarget radius of the target, considered to be a spherical body (m) - * @param trigger visibility trigger for spherical bodie + * @param trigger visibility trigger for spherical bodies * @param fov Field Of View */ private FieldOfViewDetector(final double maxCheck, final double threshold, final int maxIter, @@ -123,20 +124,34 @@ public class FieldOfViewDetector extends AbstractDetector { /** Get the Field Of View. * @return Field Of View + * @since 10.1 */ - public FieldOfView getFieldOfView() { + public FieldOfView getFOV() { return fov; } + /** Get the Field Of View. + * @return Field Of View, if detector has been built from a + * {@link org.orekit.propagation.events.FieldOfView}, or null of the + * detector was built from another implementation of {@link FieldOfView} + * @deprecated as of 10.1, replaced by {@link #getFOV()} + */ + @Deprecated + public org.orekit.propagation.events.FieldOfView getFieldOfView() { + return fov instanceof org.orekit.propagation.events.FieldOfView ? + (org.orekit.propagation.events.FieldOfView) fov : + null; + } + /** {@inheritDoc} *

    * The g function value is the angular offset between the - * target center and the {@link FieldOfView#offsetFromBoundary(Vector3D) - * Field Of View boundary}, plus or minus the target angular radius - * depending on the {@link VisibilityTrigger}, minus the {@link - * FieldOfView#getMargin() Field Of View margin}. It is therefore negative - * if the target is visible within the Field Of View and positive if it is - * outside of the Field Of View. + * target center and the {@link FieldOfView#offsetFromBoundary(Vector3D, + * double, VisibilityTrigger) Field Of View boundary}, plus or minus the + * target angular radius depending on the {@link VisibilityTrigger}, minus + * the {@link FieldOfView#getMargin() Field Of View margin}. It is therefore + * negative if the target is visible within the Field Of View and positive + * if it is outside of the Field Of View. *

    *

    * As per the previous definition, when the target enters the Field Of @@ -152,7 +167,7 @@ public class FieldOfViewDetector extends AbstractDetector { final Vector3D lineOfSightSC = s.toTransform().transformPosition(targetPosInert); final double angularRadius = FastMath.asin(radiusTarget / lineOfSightSC.getNorm()); - return fov.offsetFromBoundary(lineOfSightSC) + FastMath.copySign(angularRadius, trigger.getSign()); + return fov.offsetFromBoundary(lineOfSightSC, angularRadius, trigger); } diff --git a/src/main/java/org/orekit/propagation/events/FootprintOverlapDetector.java b/src/main/java/org/orekit/propagation/events/FootprintOverlapDetector.java index 2ccc4447b8eda204a75ce52ffba9dc188b5c63a9..adeefabb1a363e271530c8cb15def7e7f417f5ac 100644 --- a/src/main/java/org/orekit/propagation/events/FootprintOverlapDetector.java +++ b/src/main/java/org/orekit/propagation/events/FootprintOverlapDetector.java @@ -32,6 +32,7 @@ import org.orekit.bodies.BodyShape; import org.orekit.bodies.GeodeticPoint; import org.orekit.bodies.OneAxisEllipsoid; import org.orekit.frames.Transform; +import org.orekit.geometry.fov.FieldOfView; import org.orekit.models.earth.tessellation.DivertedSingularityAiming; import org.orekit.models.earth.tessellation.EllipsoidTessellator; import org.orekit.propagation.SpacecraftState; @@ -207,11 +208,25 @@ public class FootprintOverlapDetector extends AbstractDetector The g function value is the angular offset between the satellite and - * the {@link FieldOfView#offsetFromBoundary(Vector3D) Field Of View - * boundary}. It is negative if the satellite is visible within the Field Of - * View and positive if it is outside of the Field Of View, including the - * margin.

    + * the {@link FieldOfView#offsetFromBoundary(Vector3D, double, VisibilityTrigger) + * Field Of View boundary}. It is negative if the satellite is visible within + * the Field Of View and positive if it is outside of the Field Of View, + * including the margin.

    * *

    As per the previous definition, when the satellite enters the Field * Of View, a decreasing event is generated, and when the satellite leaves @@ -137,7 +150,7 @@ public class GroundFieldOfViewDetector extends AbstractDetector propagate(final FieldAbsoluteDate tEnd, final boolean activateHandlers) { try { + initializePropagation(); + if (getInitialState().getDate().equals(tEnd)) { // don't extrapolate return getInitialState(); @@ -814,6 +816,7 @@ public abstract class FieldAbstractIntegratedPropagator oldState = getCompleteState(s.getTime(), s.getCompleteState(), s.getCompleteDerivative()); final FieldSpacecraftState newState = detector.resetState(oldState); + stateChanged(newState); // main part final T[] primary = MathArrays.buildArray(getField(), s.getPrimaryStateDimension()); @@ -826,8 +829,9 @@ public abstract class FieldAbstractIntegratedPropagator additional = additionalEquations.get(i); final T[] NState = newState.getAdditionalState(additional.getName()); secondary[i] = MathArrays.buildArray(getField(), NState.length); - for (int j = 0; j < NState.length; j++) + for (int j = 0; j < NState.length; j++) { secondary[i][j] = NState[j]; + } } return new FieldODEState<>(newState.getDate().durationFrom(getStartDate()), diff --git a/src/main/java/org/orekit/propagation/numerical/DSConverter.java b/src/main/java/org/orekit/propagation/numerical/DSConverter.java index bd27f90ae8105010385af548ffbfa7e165c1f731..1ece3fcde80b1f5c20617708f8002cc61eecc8f4 100644 --- a/src/main/java/org/orekit/propagation/numerical/DSConverter.java +++ b/src/main/java/org/orekit/propagation/numerical/DSConverter.java @@ -50,7 +50,6 @@ class DSConverter extends AbstractDSConverter { private final List> dsStates; /** Simple constructor. - * @param state * @param state regular state * @param freeStateParameters number of free parameters, either 3 (position) or 6 (position-velocity) * @param provider provider to use if attitude needs to be recomputed diff --git a/src/main/java/org/orekit/propagation/numerical/FieldNumericalPropagator.java b/src/main/java/org/orekit/propagation/numerical/FieldNumericalPropagator.java index b7472b7b0293b0d1411bddb9e56b69ac031fc9dc..f6190e6b3e4934ff55ad2e95b3459bdce478e022 100644 --- a/src/main/java/org/orekit/propagation/numerical/FieldNumericalPropagator.java +++ b/src/main/java/org/orekit/propagation/numerical/FieldNumericalPropagator.java @@ -180,6 +180,10 @@ public class FieldNumericalPropagator> extends Fie setPositionAngleType(PositionAngle.TRUE); } + /** Set the flag to ignore or not the creation of a {@link NewtonianAttraction}. + * @param ignoreCentralAttraction if true, {@link NewtonianAttraction} is not + * added automatically if missing + */ public void setIgnoreCentralAttraction(final boolean ignoreCentralAttraction) { this.ignoreCentralAttraction = ignoreCentralAttraction; } @@ -632,9 +636,7 @@ public class FieldNumericalPropagator> extends Fie Arrays.fill(relTol, dP.divide(r2.sqrt()).getReal()); - return new double[][]{ - absTol, relTol - }; + return new double[][] { absTol, relTol }; } diff --git a/src/main/java/org/orekit/propagation/numerical/GLONASSNumericalPropagator.java b/src/main/java/org/orekit/propagation/numerical/GLONASSNumericalPropagator.java index 1c221a3ca1ef5f90f2a8c6b36ecf2970c1a8e105..65bac13edf5dd01503f25dfd98995b2f78d9238a 100644 --- a/src/main/java/org/orekit/propagation/numerical/GLONASSNumericalPropagator.java +++ b/src/main/java/org/orekit/propagation/numerical/GLONASSNumericalPropagator.java @@ -42,8 +42,11 @@ import org.orekit.propagation.integration.AbstractIntegratedPropagator; import org.orekit.propagation.integration.StateMapper; import org.orekit.time.AbsoluteDate; import org.orekit.time.GLONASSDate; +import org.orekit.utils.AbsolutePVCoordinates; import org.orekit.utils.Constants; +import org.orekit.utils.IERSConventions; import org.orekit.utils.PVCoordinates; +import org.orekit.utils.TimeStampedPVCoordinates; /** * This class propagates GLONASS orbits using numerical integration. @@ -275,6 +278,24 @@ public class GLONASSNumericalPropagator extends AbstractIntegratedPropagator { return glonassOrbit; } + /** {@inheritDoc} */ + @Override + public SpacecraftState propagate(final AbsoluteDate date) { + // Spacecraft state in inertial frame + final SpacecraftState stateInInertial = super.propagate(date); + + // Build the spacecraft state in inertial frame + final PVCoordinates pvInPZ90 = getPVInPZ90(stateInInertial); + final AbsolutePVCoordinates absPV = new AbsolutePVCoordinates(FramesFactory.getPZ9011(IERSConventions.IERS_2010, true), + stateInInertial.getDate(), pvInPZ90); + final TimeStampedPVCoordinates pvInInertial = absPV.getPVCoordinates(eci); + final SpacecraftState transformedState = new SpacecraftState(new CartesianOrbit(pvInInertial, eci, pvInInertial.getDate(), GLONASSOrbitalElements.GLONASS_MU), + stateInInertial.getAttitude(), + stateInInertial.getMass(), stateInInertial.getAdditionalStates()); + + return transformedState; + } + /** * Set the initial state. *

    diff --git a/src/main/java/org/orekit/propagation/numerical/NumericalPropagator.java b/src/main/java/org/orekit/propagation/numerical/NumericalPropagator.java index f79d22d0dd9411e68bea086b5b4c6ac80892a15b..da10097b6c6e96102b4be4be238b8eaa8fc4e95e 100644 --- a/src/main/java/org/orekit/propagation/numerical/NumericalPropagator.java +++ b/src/main/java/org/orekit/propagation/numerical/NumericalPropagator.java @@ -170,6 +170,10 @@ public class NumericalPropagator extends AbstractIntegratedPropagator { setPositionAngleType(PositionAngle.TRUE); } + /** Set the flag to ignore or not the creation of a {@link NewtonianAttraction}. + * @param ignoreCentralAttraction if true, {@link NewtonianAttraction} is not + * added automatically if missing + */ public void setIgnoreCentralAttraction(final boolean ignoreCentralAttraction) { this.ignoreCentralAttraction = ignoreCentralAttraction; } diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/DSSTPropagator.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/DSSTPropagator.java index 83189c8e28a5ca9ea4cb990ea394b848570194d4..b0e753c27702a5eddb3ce44280f99fe45ff1d78f 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/DSSTPropagator.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/DSSTPropagator.java @@ -136,6 +136,12 @@ public class DSSTPropagator extends AbstractIntegratedPropagator { */ private static final int I = 1; + /** Default value for epsilon. */ + private static final double EPSILON_DEFAULT = 1.0e-13; + + /** Default value for maxIterations. */ + private static final int MAX_ITERATIONS_DEFAULT = 200; + /** Number of grid points per integration step to be used in interpolation of short periodics coefficients.*/ private static final int INTERPOLATION_POINTS_PER_STEP = 3; @@ -477,7 +483,36 @@ public class DSSTPropagator extends AbstractIntegratedPropagator { public static SpacecraftState computeMeanState(final SpacecraftState osculating, final AttitudeProvider attitudeProvider, final Collection forceModels) { - final Orbit meanOrbit = computeMeanOrbit(osculating, attitudeProvider, forceModels); + return computeMeanState(osculating, attitudeProvider, forceModels, EPSILON_DEFAULT, MAX_ITERATIONS_DEFAULT); + } + + /** Conversion from osculating to mean orbit. + *

    + * Compute mean state in a DSST sense, corresponding to the + * osculating SpacecraftState in input, and according to the Force models + * taken into account. + *

    + * Since the osculating state is obtained with the computation of + * short-periodic variation of each force model, the resulting output will + * depend on the force models parameterized in input. + *

    + * The computation is done through a fixed-point iteration process. + *

    + * @param osculating Osculating state to convert + * @param attitudeProvider attitude provider (may be null if there are no Gaussian force models + * like atmospheric drag, radiation pressure or specific user-defined models) + * @param forceModels Forces to take into account + * @param epsilon convergence threshold for mean parameters conversion + * @param maxIterations maximum iterations for mean parameters conversion + * @return mean state in a DSST sense + * @since 10.1 + */ + public static SpacecraftState computeMeanState(final SpacecraftState osculating, + final AttitudeProvider attitudeProvider, + final Collection forceModels, + final double epsilon, + final int maxIterations) { + final Orbit meanOrbit = computeMeanOrbit(osculating, attitudeProvider, forceModels, epsilon, maxIterations); return new SpacecraftState(meanOrbit, osculating.getAttitude(), osculating.getMass(), osculating.getAdditionalStates()); } @@ -587,17 +622,18 @@ public class DSSTPropagator extends AbstractIntegratedPropagator { * @param attitudeProvider attitude provider (may be null if there are no Gaussian force models * like atmospheric drag, radiation pressure or specific user-defined models) * @param forceModels force models + * @param epsilon convergence threshold for mean parameters conversion + * @param maxIterations maximum iterations for mean parameters conversion * @return mean state */ private static Orbit computeMeanOrbit(final SpacecraftState osculating, final AttitudeProvider attitudeProvider, - final Collection forceModels) { + final Collection forceModels, final double epsilon, final int maxIterations) { // rough initialization of the mean parameters EquinoctialOrbit meanOrbit = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(osculating.getOrbit()); // threshold for each parameter - final double epsilon = 1.0e-13; final double thresholdA = epsilon * (1 + FastMath.abs(meanOrbit.getA())); final double thresholdE = epsilon * (1 + meanOrbit.getE()); final double thresholdI = epsilon * (1 + meanOrbit.getI()); @@ -609,7 +645,7 @@ public class DSSTPropagator extends AbstractIntegratedPropagator { } int i = 0; - while (i++ < 200) { + while (i++ < maxIterations) { final SpacecraftState meanState = new SpacecraftState(meanOrbit, osculating.getAttitude(), osculating.getMass()); diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/FieldDSSTPropagator.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/FieldDSSTPropagator.java index 0c350bb0dc50d82d5b6bd48d98070c12702e1c9c..1bac56462c4d272172cc24892679889f2a9bdb2d 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/FieldDSSTPropagator.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/FieldDSSTPropagator.java @@ -34,6 +34,7 @@ import org.hipparchus.ode.sampling.FieldODEStateInterpolator; import org.hipparchus.ode.sampling.FieldODEStepHandler; import org.hipparchus.util.FastMath; import org.hipparchus.util.MathArrays; +import org.hipparchus.util.MathUtils; import org.orekit.attitudes.AttitudeProvider; import org.orekit.attitudes.FieldAttitude; import org.orekit.errors.OrekitException; @@ -143,6 +144,12 @@ public class FieldDSSTPropagator> extends FieldAbs /** Number of grid points per integration step to be used in interpolation of short periodics coefficients.*/ private static final int INTERPOLATION_POINTS_PER_STEP = 3; + /** Default value for epsilon. */ + private static final double EPSILON_DEFAULT = 1.0e-13; + + /** Default value for maxIterations. */ + private static final int MAX_ITERATIONS_DEFAULT = 200; + /** Flag specifying whether the initial orbital state is given with osculating elements. */ private boolean initialIsOsculating; @@ -493,7 +500,36 @@ public class FieldDSSTPropagator> extends FieldAbs public FieldSpacecraftState computeMeanState(final FieldSpacecraftState osculating, final AttitudeProvider attitudeProvider, final Collection forceModel) { - final FieldOrbit meanOrbit = computeMeanOrbit(osculating, attitudeProvider, forceModel); + return computeMeanState(osculating, attitudeProvider, forceModel, EPSILON_DEFAULT, MAX_ITERATIONS_DEFAULT); + } + + /** Conversion from osculating to mean orbit. + *

    + * Compute mean state in a DSST sense, corresponding to the + * osculating SpacecraftState in input, and according to the Force models + * taken into account. + *

    + * Since the osculating state is obtained with the computation of + * short-periodic variation of each force model, the resulting output will + * depend on the force models parameterized in input. + *

    + * The computation is done through a fixed-point iteration process. + *

    + * @param osculating Osculating state to convert + * @param attitudeProvider attitude provider (may be null if there are no Gaussian force models + * like atmospheric drag, radiation pressure or specific user-defined models) + * @param forceModel Forces to take into account + * @param epsilon convergence threshold for mean parameters conversion + * @param maxIterations maximum iterations for mean parameters conversion + * @return mean state in a DSST sense + * @since 10.1 + */ + public FieldSpacecraftState computeMeanState(final FieldSpacecraftState osculating, + final AttitudeProvider attitudeProvider, + final Collection forceModel, + final double epsilon, + final int maxIterations) { + final FieldOrbit meanOrbit = computeMeanOrbit(osculating, attitudeProvider, forceModel, epsilon, maxIterations); return new FieldSpacecraftState<>(meanOrbit, osculating.getAttitude(), osculating.getMass(), osculating.getAdditionalStates()); } @@ -598,12 +634,14 @@ public class FieldDSSTPropagator> extends FieldAbs * @param attitudeProvider attitude provider (may be null if there are no Gaussian force models * like atmospheric drag, radiation pressure or specific user-defined models) * @param forceModel force models + * @param epsilon convergence threshold for mean parameters conversion + * @param maxIterations maximum iterations for mean parameters conversion * @return mean state + * @since 10.1 */ @SuppressWarnings("unchecked") - private FieldOrbit computeMeanOrbit(final FieldSpacecraftState osculating, - final AttitudeProvider attitudeProvider, - final Collection forceModel) { + private FieldOrbit computeMeanOrbit(final FieldSpacecraftState osculating, final AttitudeProvider attitudeProvider, final Collection forceModel, + final double epsilon, final int maxIterations) { // zero final T zero = field.getZero(); @@ -612,11 +650,11 @@ public class FieldDSSTPropagator> extends FieldAbs FieldEquinoctialOrbit meanOrbit = (FieldEquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(osculating.getOrbit()); // threshold for each parameter - final T epsilon = zero.add(1.0e-13); - final T thresholdA = epsilon.multiply(FastMath.abs(meanOrbit.getA()).add(1.)); - final T thresholdE = epsilon.multiply(meanOrbit.getE().add(1.)); - final T thresholdI = epsilon.multiply(meanOrbit.getI().add(1.)); - final T thresholdL = epsilon.multiply(FastMath.PI); + final T epsilonT = zero.add(epsilon); + final T thresholdA = epsilonT.multiply(FastMath.abs(meanOrbit.getA()).add(1.)); + final T thresholdE = epsilonT.multiply(meanOrbit.getE().add(1.)); + final T thresholdI = epsilonT.multiply(meanOrbit.getI().add(1.)); + final T thresholdL = epsilonT.multiply(FastMath.PI); // ensure all Gaussian force models can rely on attitude for (final DSSTForceModel force : forceModel) { @@ -624,7 +662,7 @@ public class FieldDSSTPropagator> extends FieldAbs } int i = 0; - while (i++ < 200) { + while (i++ < maxIterations) { final FieldSpacecraftState meanState = new FieldSpacecraftState<>(meanOrbit, osculating.getAttitude(), osculating.getMass()); @@ -647,7 +685,7 @@ public class FieldDSSTPropagator> extends FieldAbs final T deltaEy = osculating.getEquinoctialEy().subtract(rebuilt.getEquinoctialEy()); final T deltaHx = osculating.getHx().subtract(rebuilt.getHx()); final T deltaHy = osculating.getHy().subtract(rebuilt.getHy()); - final T deltaLv = aux.normalizeAngle(osculating.getLv().subtract(rebuilt.getLv()), zero); + final T deltaLv = MathUtils.normalizeAngle(osculating.getLv().subtract(rebuilt.getLv()), zero); // check convergence if (FastMath.abs(deltaA).getReal() < thresholdA.getReal() && diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/AbstractGaussianContribution.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/AbstractGaussianContribution.java index dfcf01c92c05bfdc4eb9184102a6c321cc95fe85..68959f1857920e6a2bc87e3fc27290f80c041120 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/AbstractGaussianContribution.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/AbstractGaussianContribution.java @@ -421,8 +421,7 @@ public abstract class AbstractGaussianContribution implements DSSTForceModel { double maxDiff = FastMath.abs(meanRef[0] - meanCur[0]) / auxiliaryElements.getSma(); // Corrects mean element rates for (int i = 1; i < meanRef.length; i++) { - final double diff = FastMath.abs(meanRef[i] - meanCur[i]); - if (maxDiff < diff) maxDiff = diff; + maxDiff = FastMath.max(maxDiff, FastMath.abs(meanRef[i] - meanCur[i])); } return maxDiff; } @@ -443,8 +442,7 @@ public abstract class AbstractGaussianContribution implements DSSTForceModel { T maxDiff = FastMath.abs(meanRef[0].subtract(meanCur[0])).divide(auxiliaryElements.getSma());; // Corrects mean element rates for (int i = 1; i < meanRef.length; i++) { - final T diff = FastMath.abs(meanRef[i].subtract(meanCur[i])); - if (maxDiff.getReal() < diff.getReal()) maxDiff = diff; + maxDiff = FastMath.max(maxDiff, FastMath.abs(meanRef[i].subtract(meanCur[i]))); } return maxDiff; } diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTAtmosphericDrag.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTAtmosphericDrag.java index 61f03936ae43c24e9cd89a3378f4770906481403..c635acfe0892e6071bbc35a46f9c1326cc316dce 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTAtmosphericDrag.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTAtmosphericDrag.java @@ -127,8 +127,8 @@ public class DSSTAtmosphericDrag extends AbstractGaussianContribution { final double apogee = auxiliaryElements.getSma() * (1. + auxiliaryElements.getEcc()); // Trajectory entirely within of the atmosphere if (apogee < rbar) { - return new double[]{-FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0), - FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0)}; + return new double[] { -FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0), + FastMath.PI + MathUtils.normalizeAngle(state.getLv(), 0) }; } // Else, trajectory partialy within of the atmosphere final double fb = FastMath.acos(((auxiliaryElements.getSma() * (1. - auxiliaryElements.getEcc() * auxiliaryElements.getEcc()) / rbar) - 1.) / auxiliaryElements.getEcc()); @@ -153,8 +153,8 @@ public class DSSTAtmosphericDrag extends AbstractGaussianContribution { final T apogee = auxiliaryElements.getSma().multiply(auxiliaryElements.getEcc().add(1.)); // Trajectory entirely within of the atmosphere if (apogee.getReal() < rbar) { - tab[0] = auxiliaryElements.normalizeAngle(state.getLv(), zero).subtract(FastMath.PI); - tab[1] = auxiliaryElements.normalizeAngle(state.getLv(), zero).add(FastMath.PI); + tab[0] = MathUtils.normalizeAngle(state.getLv(), zero).subtract(FastMath.PI); + tab[1] = MathUtils.normalizeAngle(state.getLv(), zero).add(FastMath.PI); return tab; } // Else, trajectory partialy within of the atmosphere diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTSolarRadiationPressure.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTSolarRadiationPressure.java index 65a601e3da6a7d42c494d22088c7e4a49e96cac1..39fbc59477474d3f36036837b42eb6fb5e3525a8 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTSolarRadiationPressure.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTSolarRadiationPressure.java @@ -307,8 +307,8 @@ public class DSSTSolarRadiationPressure extends AbstractGaussianContribution { // Default bounds without shadow [-PI, PI] final T[] ll = MathArrays.buildArray(field, 2); - ll[0] = auxiliaryElements.normalizeAngle(state.getLv(), zero).subtract(FastMath.PI); - ll[1] = auxiliaryElements.normalizeAngle(state.getLv(), zero).add(FastMath.PI); + ll[0] = MathUtils.normalizeAngle(state.getLv(), zero).subtract(FastMath.PI); + ll[1] = MathUtils.normalizeAngle(state.getLv(), zero).add(FastMath.PI); // Direction cosines of the Sun in the equinoctial frame final FieldVector3D sunDir = sun.getPVCoordinates(state.getDate(), state.getFrame()).getPosition().normalize(); diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTTesseral.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTTesseral.java index 47bd1aa28acd56f1e9f97b877c0d5791d1b96328..3e69d8fd3e118f04ab19f2a8b325822a39fa5aba 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTTesseral.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTTesseral.java @@ -199,6 +199,35 @@ public class DSSTTesseral implements DSSTForceModel { /** Flag for force model initialization with field elements. */ private boolean pendingInitialization; + /** Simple constructor with default reference values. + *

    + * When this constructor is used, maximum allowed values are used + * for the short periodic coefficients: + *

    + *
      + *
    • {@link #maxDegreeTesseralSP} is set to {@code provider.getMaxDegree()}
    • + *
    • {@link #maxOrderTesseralSP} is set to {@code provider.getMaxOrder()}.
    • + *
    • {@link #maxEccPowTesseralSP} is set to 4
    • + *
    • {@link #maxFrequencyShortPeriodics} is set to {@code min(provider.getMaxDegree() + 4, 12)}. + * This parameter should not exceed 12 as higher values will exceed computer capacity
    • + *
    • {@link #maxDegreeMdailyTesseralSP} is set to {@code provider.getMaxDegree()}
    • + *
    • {@link #maxOrderMdailyTesseralSP} is set to {@code provider.getMaxOrder()}
    • + *
    • {@link #maxEccPowMdailyTesseralSP} is set to min(provider.getMaxDegree() - 2, 4). + * This parameter should not exceed 4 as higher values will exceed computer capacity
    • + *
    + * @param centralBodyFrame rotating body frame + * @param centralBodyRotationRate central body rotation rate (rad/s) + * @param provider provider for spherical harmonics + * @since 10.1 + */ + public DSSTTesseral(final Frame centralBodyFrame, + final double centralBodyRotationRate, + final UnnormalizedSphericalHarmonicsProvider provider) { + this(centralBodyFrame, centralBodyRotationRate, provider, provider.getMaxDegree(), + provider.getMaxOrder(), 4, FastMath.min(12, provider.getMaxDegree() + 4), + provider.getMaxDegree(), provider.getMaxOrder(), FastMath.min(4, provider.getMaxDegree() - 2)); + } + /** Simple constructor. * @param centralBodyFrame rotating body frame * @param centralBodyRotationRate central body rotation rate (rad/s) @@ -918,13 +947,13 @@ public class DSSTTesseral implements DSSTForceModel { } } - return new double[][] {{dUdaCos, dUdaSin}, - {dUdhCos, dUdhSin}, - {dUdkCos, dUdkSin}, - {dUdlCos, dUdlSin}, - {dUdAlCos, dUdAlSin}, - {dUdBeCos, dUdBeSin}, - {dUdGaCos, dUdGaSin}}; + return new double[][] { { dUdaCos, dUdaSin }, + { dUdhCos, dUdhSin }, + { dUdkCos, dUdkSin }, + { dUdlCos, dUdlSin }, + { dUdAlCos, dUdAlSin }, + { dUdBeCos, dUdBeSin }, + { dUdGaCos, dUdGaSin } }; } /** Compute the n-SUM for potential derivatives components. diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTZonal.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTZonal.java index 6eb75ce078c7090aa7cfb56e3efce03ebaefd582..b1c576ff8eee5fda9e1811138324f5e38fcf16e9 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTZonal.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/forces/DSSTZonal.java @@ -147,6 +147,24 @@ public class DSSTZonal implements DSSTForceModel { /** Flag for force model initialization with field elements. */ private boolean pendingInitialization; + /** Constructor with default reference values. + *

    + * When this constructor is used, maximum allowed values are used + * for the short periodic coefficients: + *

    + *
      + *
    • {@link #maxDegreeShortPeriodics} is set to {@code provider.getMaxDegree()}
    • + *
    • {@link #maxEccPowShortPeriodics} is set to {@code min(provider.getMaxDegree() - 1, 4)}. + * This parameter should not exceed 4 as higher values will exceed computer capacity
    • + *
    • {@link #maxFrequencyShortPeriodics} is set to {@code 2 * provider.getMaxDegree() + 1}
    • + *
    + * @param provider provider for spherical harmonics + * @since 10.1 + */ + public DSSTZonal(final UnnormalizedSphericalHarmonicsProvider provider) { + this(provider, provider.getMaxDegree(), FastMath.min(4, provider.getMaxDegree() - 1), 2 * provider.getMaxDegree() + 1); + } + /** Simple constructor. * @param provider provider for spherical harmonics * @param maxDegreeShortPeriodics maximum degree to consider for short periodics zonal harmonics potential @@ -347,7 +365,9 @@ public class DSSTZonal implements DSSTForceModel { final double cnm = harmonics.getUnnormalizedCnm(maxDeg, m); final double snm = harmonics.getUnnormalizedSnm(maxDeg, m); final double csnm = FastMath.hypot(cnm, snm); - if (csnm == 0.) break; + if (csnm == 0.) { + break; + } // Set magnitude of last spherical harmonic term. double lastTerm = 0.; // Set current power of e and related indices. @@ -451,7 +471,9 @@ public class DSSTZonal implements DSSTForceModel { final T cnm = zero.add(harmonics.getUnnormalizedCnm(maxDeg, m)); final T snm = zero.add(harmonics.getUnnormalizedSnm(maxDeg, m)); final T csnm = FastMath.hypot(cnm, snm); - if (csnm.getReal() == 0.) break; + if (csnm.getReal() == 0.) { + break; + } // Set magnitude of last spherical harmonic term. T lastTerm = zero; // Set current power of e and related indices. diff --git a/src/main/java/org/orekit/propagation/semianalytical/dsst/utilities/FieldAuxiliaryElements.java b/src/main/java/org/orekit/propagation/semianalytical/dsst/utilities/FieldAuxiliaryElements.java index 522cfd0eb2d5edafedfe550f22dee4ed693b20da..bab420562e554b37d8b99b3a8d44079c28423710 100644 --- a/src/main/java/org/orekit/propagation/semianalytical/dsst/utilities/FieldAuxiliaryElements.java +++ b/src/main/java/org/orekit/propagation/semianalytical/dsst/utilities/FieldAuxiliaryElements.java @@ -20,6 +20,7 @@ import org.hipparchus.Field; import org.hipparchus.RealFieldElement; import org.hipparchus.geometry.euclidean.threed.FieldVector3D; import org.hipparchus.util.FastMath; +import org.hipparchus.util.MathUtils; import org.orekit.frames.Frame; import org.orekit.orbits.FieldOrbit; import org.orekit.time.FieldAbsoluteDate; @@ -143,9 +144,9 @@ public class FieldAuxiliaryElements> { h = orbit.getEquinoctialEy(); q = orbit.getHx(); p = orbit.getHy(); - lm = normalizeAngle(orbit.getLM(), pi); - lv = normalizeAngle(orbit.getLv(), pi); - le = normalizeAngle(orbit.getLE(), pi); + lm = MathUtils.normalizeAngle(orbit.getLM(), pi); + lv = MathUtils.normalizeAngle(orbit.getLv(), pi); + le = MathUtils.normalizeAngle(orbit.getLE(), pi); // Retrograde factor [Eq. 2.1.2-(2)] I = retrogradeFactor; @@ -191,7 +192,9 @@ public class FieldAuxiliaryElements> { * @param a angle to normalize * @param center center of the desired 2π interval for the result * @return a-2kπ with integer k and center-π <= a-2kπ <= center+π + * @deprecated replaced by {@link MathUtils#normalizeAngle(RealFieldElement, RealFieldElement)} */ + @Deprecated public T normalizeAngle(final T a, final T center) { return a.subtract(FastMath.floor((a.add(FastMath.PI).subtract(center)).divide(TWO_PI)).multiply(TWO_PI)); } diff --git a/src/main/java/org/orekit/time/AbsoluteDate.java b/src/main/java/org/orekit/time/AbsoluteDate.java index 2636a1314df8374122e96949a232af3b7a84d354..6e7e776adf5916f7908ba904a612904d03a56ae4 100644 --- a/src/main/java/org/orekit/time/AbsoluteDate.java +++ b/src/main/java/org/orekit/time/AbsoluteDate.java @@ -134,6 +134,10 @@ public class AbsoluteDate public static final AbsoluteDate QZSS_EPOCH = new AbsoluteDate(DateComponents.QZSS_EPOCH, TimeComponents.H00, TimeScalesFactory.getQZSS()); + /** Reference epoch for IRNSS weeks: 1999-08-22T00:00:00 IRNSS time. */ + public static final AbsoluteDate IRNSS_EPOCH = + new AbsoluteDate(DateComponents.IRNSS_EPOCH, TimeComponents.H00, TimeScalesFactory.getIRNSS()); + /** Reference epoch for BeiDou weeks: 2006-01-01T00:00:00 UTC. */ public static final AbsoluteDate BEIDOU_EPOCH = new AbsoluteDate(DateComponents.BEIDOU_EPOCH, TimeComponents.H00, TimeScalesFactory.getBDT()); @@ -963,7 +967,12 @@ public class AbsoluteDate * is before, simultaneous, or after the specified date. */ public int compareTo(final AbsoluteDate date) { - return Double.compare(durationFrom(date), 0); + final double duration = durationFrom(date); + if (!Double.isNaN(duration)) { + return Double.compare(duration, 0.0); + } + // both dates are infinity or one is NaN or both are NaN + return Double.compare(offset, date.offset); } /** {@inheritDoc} */ @@ -971,7 +980,7 @@ public class AbsoluteDate return this; } - /** Check if the instance represent the same time as another instance. + /** Check if the instance represents the same time as another instance. * @param date other date * @return true if the instance and the other date refer to the same instant */ @@ -990,6 +999,105 @@ public class AbsoluteDate } + /** Check if the instance represents the same time as another. + * @param other the instant to compare this date to + * @return true if the instance and the argument refer to the same instant + * @see #isCloseTo(TimeStamped, double) + * @since 10.1 + */ + public boolean isEqualTo(final TimeStamped other) { + return this.equals(other.getDate()); + } + + /** Check if the instance time is close to another. + * @param other the instant to compare this date to + * @param tolerance the separation, in seconds, under which the two instants will be considered close to each other + * @return true if the duration between the instance and the argument is strictly below the tolerance + * @see #isEqualTo(TimeStamped) + * @since 10.1 + */ + public boolean isCloseTo(final TimeStamped other, final double tolerance) { + return FastMath.abs(this.durationFrom(other.getDate())) < tolerance; + } + + /** Check if the instance represents a time that is strictly before another. + * @param other the instant to compare this date to + * @return true if the instance is strictly before the argument when ordering chronologically + * @see #isBeforeOrEqualTo(TimeStamped) + * @since 10.1 + */ + public boolean isBefore(final TimeStamped other) { + return this.compareTo(other.getDate()) < 0; + } + + /** Check if the instance represents a time that is strictly after another. + * @param other the instant to compare this date to + * @return true if the instance is strictly after the argument when ordering chronologically + * @see #isAfterOrEqualTo(TimeStamped) + * @since 10.1 + */ + public boolean isAfter(final TimeStamped other) { + return this.compareTo(other.getDate()) > 0; + } + + /** Check if the instance represents a time that is before or equal to another. + * @param other the instant to compare this date to + * @return true if the instance is before (or equal to) the argument when ordering chronologically + * @see #isBefore(TimeStamped) + * @since 10.1 + */ + public boolean isBeforeOrEqualTo(final TimeStamped other) { + return this.isEqualTo(other) || this.isBefore(other); + } + + /** Check if the instance represents a time that is after or equal to another. + * @param other the instant to compare this date to + * @return true if the instance is after (or equal to) the argument when ordering chronologically + * @see #isAfterOrEqualTo(TimeStamped) + * @since 10.1 + */ + public boolean isAfterOrEqualTo(final TimeStamped other) { + return this.isEqualTo(other) || this.isAfter(other); + } + + /** Check if the instance represents a time that is strictly between two others representing + * the boundaries of a time span. The two boundaries can be provided in any order: in other words, + * whether boundary represents a time that is before or after otherBoundary will + * not change the result of this method. + * @param boundary one end of the time span + * @param otherBoundary the other end of the time span + * @return true if the instance is strictly between the two arguments when ordering chronologically + * @see #isBetweenOrEqualTo(TimeStamped, TimeStamped) + * @since 10.1 + */ + public boolean isBetween(final TimeStamped boundary, final TimeStamped otherBoundary) { + final TimeStamped beginning; + final TimeStamped end; + if (boundary.getDate().isBefore(otherBoundary)) { + beginning = boundary; + end = otherBoundary; + } else { + beginning = otherBoundary; + end = boundary; + } + return this.isAfter(beginning) && this.isBefore(end); + } + + /** Check if the instance represents a time that is between two others representing + * the boundaries of a time span, or equal to one of them. The two boundaries can be provided in any order: + * in other words, whether boundary represents a time that is before or after + * otherBoundary will not change the result of this method. + * @param boundary one end of the time span + * @param otherBoundary the other end of the time span + * @return true if the instance is between the two arguments (or equal to at least one of them) + * when ordering chronologically + * @see #isBetween(TimeStamped, TimeStamped) + * @since 10.1 + */ + public boolean isBetweenOrEqualTo(final TimeStamped boundary, final TimeStamped otherBoundary) { + return this.isEqualTo(boundary) || this.isEqualTo(otherBoundary) || this.isBetween(boundary, otherBoundary); + } + /** Get a hashcode for this date. * @return hashcode */ diff --git a/src/main/java/org/orekit/time/DateComponents.java b/src/main/java/org/orekit/time/DateComponents.java index 8f82e78e0026fa603f6495cab2e1f5174c5d6f67..1723f552131ed5fbb8fe5df56305c9f41e2f19e0 100644 --- a/src/main/java/org/orekit/time/DateComponents.java +++ b/src/main/java/org/orekit/time/DateComponents.java @@ -68,6 +68,9 @@ public class DateComponents implements Serializable, Comparable /** Reference epoch for QZSS weeks: 1980-01-06. */ public static final DateComponents QZSS_EPOCH; + /** Reference epoch for IRNSS weeks: 1999-08-22. */ + public static final DateComponents IRNSS_EPOCH; + /** Reference epoch for BeiDou weeks: 2006-01-01. */ public static final DateComponents BEIDOU_EPOCH; @@ -144,6 +147,7 @@ public class DateComponents implements Serializable, Comparable GALILEO_EPOCH = new DateComponents(1999, 8, 22); GPS_EPOCH = new DateComponents(1980, 1, 6); QZSS_EPOCH = new DateComponents(1980, 1, 6); + IRNSS_EPOCH = new DateComponents(1999, 8, 22); BEIDOU_EPOCH = new DateComponents(2006, 1, 1); GLONASS_EPOCH = new DateComponents(1996, 1, 1); J2000_EPOCH = new DateComponents(2000, 1, 1); diff --git a/src/main/java/org/orekit/time/FieldAbsoluteDate.java b/src/main/java/org/orekit/time/FieldAbsoluteDate.java index 484d17b88c9b577801492e9eb6f87d9bbfa8fac0..03bcdcd98d395368cfb0a7ff9fc3e705340831c8 100644 --- a/src/main/java/org/orekit/time/FieldAbsoluteDate.java +++ b/src/main/java/org/orekit/time/FieldAbsoluteDate.java @@ -1065,7 +1065,7 @@ public class FieldAbsoluteDate> } - /** Check if the instance represent the same time as another instance. + /** Check if the instance represents the same time as another instance. * @param date other date * @return true if the instance and the other date refer to the same instant */ @@ -1085,6 +1085,105 @@ public class FieldAbsoluteDate> } + /** Check if the instance represents the same time as another. + * @param other the instant to compare this date to + * @return true if the instance and the argument refer to the same instant + * @see #isCloseTo(FieldTimeStamped, double) + * @since 10.1 + */ + public boolean isEqualTo(final FieldTimeStamped other) { + return this.equals(other.getDate()); + } + + /** Check if the instance time is close to another. + * @param other the instant to compare this date to + * @param tolerance the separation, in seconds, under which the two instants will be considered close to each other + * @return true if the duration between the instance and the argument is strictly below the tolerance + * @see #isEqualTo(FieldTimeStamped) + * @since 10.1 + */ + public boolean isCloseTo(final FieldTimeStamped other, final double tolerance) { + return FastMath.abs(this.durationFrom(other.getDate()).getReal()) < tolerance; + } + + /** Check if the instance represents a time that is strictly before another. + * @param other the instant to compare this date to + * @return true if the instance is strictly before the argument when ordering chronologically + * @see #isBeforeOrEqualTo(FieldTimeStamped) + * @since 10.1 + */ + public boolean isBefore(final FieldTimeStamped other) { + return this.compareTo(other.getDate()) < 0; + } + + /** Check if the instance represents a time that is strictly after another. + * @param other the instant to compare this date to + * @return true if the instance is strictly after the argument when ordering chronologically + * @see #isAfterOrEqualTo(FieldTimeStamped) + * @since 10.1 + */ + public boolean isAfter(final FieldTimeStamped other) { + return this.compareTo(other.getDate()) > 0; + } + + /** Check if the instance represents a time that is before or equal to another. + * @param other the instant to compare this date to + * @return true if the instance is before (or equal to) the argument when ordering chronologically + * @see #isBefore(FieldTimeStamped) + * @since 10.1 + */ + public boolean isBeforeOrEqualTo(final FieldTimeStamped other) { + return this.isEqualTo(other) || this.isBefore(other); + } + + /** Check if the instance represents a time that is after or equal to another. + * @param other the instant to compare this date to + * @return true if the instance is after (or equal to) the argument when ordering chronologically + * @see #isAfterOrEqualTo(FieldTimeStamped) + * @since 10.1 + */ + public boolean isAfterOrEqualTo(final FieldTimeStamped other) { + return this.isEqualTo(other) || this.isAfter(other); + } + + /** Check if the instance represents a time that is strictly between two others representing + * the boundaries of a time span. The two boundaries can be provided in any order: in other words, + * whether boundary represents a time that is before or after otherBoundary will + * not change the result of this method. + * @param boundary one end of the time span + * @param otherBoundary the other end of the time span + * @return true if the instance is strictly between the two arguments when ordering chronologically + * @see #isBetweenOrEqualTo(FieldTimeStamped, FieldTimeStamped) + * @since 10.1 + */ + public boolean isBetween(final FieldTimeStamped boundary, final FieldTimeStamped otherBoundary) { + final FieldTimeStamped beginning; + final FieldTimeStamped end; + if (boundary.getDate().isBefore(otherBoundary)) { + beginning = boundary; + end = otherBoundary; + } else { + beginning = otherBoundary; + end = boundary; + } + return this.isAfter(beginning) && this.isBefore(end); + } + + /** Check if the instance represents a time that is between two others representing + * the boundaries of a time span, or equal to one of them. The two boundaries can be provided in any order: + * in other words, whether boundary represents a time that is before or after + * otherBoundary will not change the result of this method. + * @param boundary one end of the time span + * @param otherBoundary the other end of the time span + * @return true if the instance is between the two arguments (or equal to at least one of them) + * when ordering chronologically + * @see #isBetween(FieldTimeStamped, FieldTimeStamped) + * @since 10.1 + */ + public boolean isBetweenOrEqualTo(final FieldTimeStamped boundary, final FieldTimeStamped otherBoundary) { + return this.isEqualTo(boundary) || this.isEqualTo(otherBoundary) || this.isBetween(boundary, otherBoundary); + } + /** Get a hashcode for this date. * @return hashcode */ diff --git a/src/main/java/org/orekit/time/GNSSDate.java b/src/main/java/org/orekit/time/GNSSDate.java index 3f03cc4af48a0b35c06c899f5ff80d9c0de9e189..5db8e909a3dab762bf291dfe0b7b7bc2d081f221 100644 --- a/src/main/java/org/orekit/time/GNSSDate.java +++ b/src/main/java/org/orekit/time/GNSSDate.java @@ -204,6 +204,8 @@ public class GNSSDate implements Serializable, TimeStamped { case GALILEO : return TimeScalesFactory.getGST(); case QZSS : return TimeScalesFactory.getQZSS(); case BEIDOU : return TimeScalesFactory.getBDT(); + case IRNSS : return TimeScalesFactory.getIRNSS(); + case SBAS : return TimeScalesFactory.getGPS(); default : throw new OrekitException(OrekitMessages.INVALID_SATELLITE_SYSTEM, satellite); } } @@ -219,6 +221,8 @@ public class GNSSDate implements Serializable, TimeStamped { case GALILEO : return AbsoluteDate.GALILEO_EPOCH; case QZSS : return AbsoluteDate.QZSS_EPOCH; case BEIDOU : return AbsoluteDate.BEIDOU_EPOCH; + case IRNSS : return AbsoluteDate.IRNSS_EPOCH; + case SBAS : return AbsoluteDate.GPS_EPOCH; default : throw new OrekitException(OrekitMessages.INVALID_SATELLITE_SYSTEM, satellite); } } @@ -234,6 +238,8 @@ public class GNSSDate implements Serializable, TimeStamped { case GALILEO : return DateComponents.GALILEO_EPOCH; case QZSS : return DateComponents.QZSS_EPOCH; case BEIDOU : return DateComponents.BEIDOU_EPOCH; + case IRNSS : return DateComponents.IRNSS_EPOCH; + case SBAS : return DateComponents.GPS_EPOCH; default : throw new OrekitException(OrekitMessages.INVALID_SATELLITE_SYSTEM, satellite); } } @@ -294,7 +300,13 @@ public class GNSSDate implements Serializable, TimeStamped { QZSS(SatelliteSystem.QZSS, 1024), /** BeiDou. */ - BEIDOU(SatelliteSystem.BEIDOU, 8192); + BEIDOU(SatelliteSystem.BEIDOU, 8192), + + /** IRNSS. */ + IRNSS(SatelliteSystem.IRNSS, 1024), + + /** SBAS. */ + SBAS(SatelliteSystem.SBAS, 1024); /** Map for the number of week in one GNSS rollover cycle. */ private static final Map CYCLE_MAP = new HashMap(); diff --git a/src/main/java/org/orekit/time/TAIUTCDatFilesLoader.java b/src/main/java/org/orekit/time/TAIUTCDatFilesLoader.java index b6f6b7cdd6035a26f8f2d81a8f0667924a61f78c..86f53edfd00287ae761400ca3c95a1e21f17b692 100644 --- a/src/main/java/org/orekit/time/TAIUTCDatFilesLoader.java +++ b/src/main/java/org/orekit/time/TAIUTCDatFilesLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -163,7 +164,7 @@ public class TAIUTCDatFilesLoader implements UTCTAIOffsetsLoader { offsets.clear(); // set up a reader for line-oriented file - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); // read all file, ignoring not recognized lines int lineNumber = 0; diff --git a/src/main/java/org/orekit/time/UTCTAIBulletinAFilesLoader.java b/src/main/java/org/orekit/time/UTCTAIBulletinAFilesLoader.java index 32a4d503217f067a337f01aadd1642957f553e64..37e00af2260b9fc0e64d2aaae654b9227ea2279b 100644 --- a/src/main/java/org/orekit/time/UTCTAIBulletinAFilesLoader.java +++ b/src/main/java/org/orekit/time/UTCTAIBulletinAFilesLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -390,7 +391,7 @@ public class UTCTAIBulletinAFilesLoader implements UTCTAIOffsetsLoader { throws IOException { // set up a reader for line-oriented bulletin A files - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); lineNumber = 0; // loop over sections diff --git a/src/main/java/org/orekit/time/UTCTAIHistoryFilesLoader.java b/src/main/java/org/orekit/time/UTCTAIHistoryFilesLoader.java index 7999f810fd9f2031c681deecc0774333c69cbb2b..60fc58b0e402e49bf28726aafef985500336e0cc 100644 --- a/src/main/java/org/orekit/time/UTCTAIHistoryFilesLoader.java +++ b/src/main/java/org/orekit/time/UTCTAIHistoryFilesLoader.java @@ -20,6 +20,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -144,7 +145,7 @@ public class UTCTAIHistoryFilesLoader implements UTCTAIOffsetsLoader { offsets.clear(); // set up a reader for line-oriented file - final BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8")); + final BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); // read all file, ignoring not recognized lines final String emptyYear = " "; diff --git a/src/main/java/org/orekit/utils/Constants.java b/src/main/java/org/orekit/utils/Constants.java index 10dc38176dbee75c0f9e0a7c7c2683b56c0a0106..e278f4014d82a50605cc96be079293bff22069a8 100644 --- a/src/main/java/org/orekit/utils/Constants.java +++ b/src/main/java/org/orekit/utils/Constants.java @@ -21,6 +21,7 @@ import org.hipparchus.util.MathUtils; /** Set of useful physical constants. * @author Luc Maisonobe + * @author Guylaine Prat */ public interface Constants { @@ -191,6 +192,50 @@ public interface Constants { /** Earth un-normalized sixth zonal coefficient from EIGEN5C model: -5.406653715879098e-7. */ double EIGEN5C_EARTH_C60 = -5.406653715879098e-7; + /** Earth equatorial radius from IERS96 model: 6378136.49 m. */ + double IERS96_EARTH_EQUATORIAL_RADIUS = 6378136.49; + + /** Earth flattening from IERS96 model: 1.0 / 298.25642. */ + double IERS96_EARTH_FLATTENING = 1.0 / 298.25642; + + /** Earth angular velocity from IERS96 model: 7.292115e-5 rad/s. */ + double IERS96_EARTH_ANGULAR_VELOCITY = 7.292115e-5; + + /** Earth gravitational constant from IERS96 model: 3.986004418e14 m³/s². */ + double IERS96_EARTH_MU = 3.986004418e14; + + /** Earth un-normalized second zonal coefficient from IERS96 model: -1.0826359e-3. */ + double IERS96_EARTH_C20 = -1.0826359e-3; + + /** Earth equatorial radius from IERS2003 model: 6378136.6 m. */ + double IERS2003_EARTH_EQUATORIAL_RADIUS = 6378136.6; + + /** Earth flattening from IERS2003 model: 1.0 / 298.25642. */ + double IERS2003_EARTH_FLATTENING = 1.0 / 298.25642; + + /** Earth angular velocity from IERS2003 model: 7.292115e-5 rad/s. */ + double IERS2003_EARTH_ANGULAR_VELOCITY = 7.292115e-5; + + /** Earth gravitational constant from IERS2003 model: 3.986004418e14 m³/s². */ + double IERS2003_EARTH_MU = 3.986004418e14; + + /** Earth un-normalized second zonal coefficient from IERS2003 model: -1.0826359e-3. */ + double IERS2003_EARTH_C20 = -1.0826359e-3; + + /** Earth equatorial radius from IERS2010 model: 6378136.6 m. */ + double IERS2010_EARTH_EQUATORIAL_RADIUS = 6378136.6; + + /** Earth flattening from IERS2010 model: 1.0 / 298.25642. */ + double IERS2010_EARTH_FLATTENING = 1.0 / 298.25642; + + /** Earth angular velocity from IERS2010 model: 7.292115e-5 rad/s. */ + double IERS2010_EARTH_ANGULAR_VELOCITY = 7.292115e-5; + + /** Earth gravitational constant from IERS2010 model: 3.986004418e14 m³/s². */ + double IERS2010_EARTH_MU = 3.986004418e14; + + /** Earth un-normalized second zonal coefficient from IERS2010 model: -1.0826359e-3. */ + double IERS2010_EARTH_C20 = -1.0826359e-3; /** Gaussian gravitational constant: 0.01720209895 √(AU³/d²). */ double JPL_SSD_GAUSSIAN_GRAVITATIONAL_CONSTANT = 0.01720209895; diff --git a/src/main/java/org/orekit/utils/IERSConventions.java b/src/main/java/org/orekit/utils/IERSConventions.java index d8fd885ae333cf2304b26bb9e5f6e66f649f253f..7de0137c731de23568b1f135a7c1f6e6cb723795 100644 --- a/src/main/java/org/orekit/utils/IERSConventions.java +++ b/src/main/java/org/orekit/utils/IERSConventions.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Serializable; +import java.nio.charset.StandardCharsets; import java.util.List; import org.hipparchus.RealFieldElement; @@ -2751,7 +2752,7 @@ public enum IERSConventions { } // setup the reader - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { String line = reader.readLine(); int lineNumber = 1; diff --git a/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java b/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java index 9368bccf90eb50df81c33f52c682bdbb993e51ad..bcade4e4618d2603c69410197e360b05cd23de14 100644 --- a/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java +++ b/src/main/java/org/orekit/utils/ImmutableTimeStampedCache.java @@ -155,14 +155,17 @@ public class ImmutableTimeStampedCache return i; } + /** {@inheritDoc} */ public int getNeighborsSize() { return this.neighborsSize; } + /** {@inheritDoc} */ public T getEarliest() { return this.data.get(0); } + /** {@inheritDoc} */ public T getLatest() { return this.data.get(this.data.size() - 1); } diff --git a/src/main/java/org/orekit/utils/InterpolationTableLoader.java b/src/main/java/org/orekit/utils/InterpolationTableLoader.java index 033a2ac58858f65b6443d5972b7884508a07581b..4cd7e44c3df97b1f2e854faf7df8f5357984427a 100644 --- a/src/main/java/org/orekit/utils/InterpolationTableLoader.java +++ b/src/main/java/org/orekit/utils/InterpolationTableLoader.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StreamTokenizer; +import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.LinkedList; import java.util.List; @@ -93,7 +94,7 @@ public class InterpolationTableLoader implements DataLoader { final LinkedList> cellValues = new LinkedList>(); final StreamTokenizer tokenizer = - new StreamTokenizer(new BufferedReader(new InputStreamReader(input, "UTF-8"))); + new StreamTokenizer(new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))); // ignore comments starting with a # tokenizer.commentChar('#'); diff --git a/src/main/java/org/orekit/utils/ParameterDriver.java b/src/main/java/org/orekit/utils/ParameterDriver.java index 87c19893a62b0cf2ab06b2c9e93a0ca08887e741..ae7dbda78f70d38ddca56ab411cc7e703e2df210 100644 --- a/src/main/java/org/orekit/utils/ParameterDriver.java +++ b/src/main/java/org/orekit/utils/ParameterDriver.java @@ -154,6 +154,19 @@ public class ParameterDriver { } } + /** Replace an observer. + * @param oldObserver observer to replace + * @param newObserver new observer to use + * @since 10.1 + */ + public void replaceObserver(final ParameterObserver oldObserver, final ParameterObserver newObserver) { + for (int i = 0; i < observers.size(); ++i) { + if (observers.get(i) == oldObserver) { + observers.set(i, newObserver); + } + } + } + /** Get the observers for this driver. * @return an unmodifiable view of the observers for this driver * @since 9.1 diff --git a/src/main/java/org/orekit/utils/ParameterDriversList.java b/src/main/java/org/orekit/utils/ParameterDriversList.java index 0b2b3a414f5a229de962c51629910777f506914a..01d5de8afe5cf49a382cbd6d10f96ac39c917ccd 100644 --- a/src/main/java/org/orekit/utils/ParameterDriversList.java +++ b/src/main/java/org/orekit/utils/ParameterDriversList.java @@ -53,7 +53,7 @@ public class ParameterDriversList { /** Creates an empty list. */ public ParameterDriversList() { - this.delegating = new ArrayList(); + this.delegating = new ArrayList<>(); } /** Add a driver. @@ -73,8 +73,8 @@ public class ParameterDriversList { if (existingHere != null) { if (alreadyBound != null) { - // ensure we don't get intermixed change forwarders that call each other recursively - existingHere.setForwarder(alreadyBound.getForwarder()); + // merge the two delegating drivers + existingHere.merge(alreadyBound); } else { // this is a new driver for an already managed parameter existingHere.add(driver); @@ -83,12 +83,10 @@ public class ParameterDriversList { if (alreadyBound != null) { // the driver is new here, but already bound to other drivers in other lists delegating.add(alreadyBound); + alreadyBound.addOwner(this); } else { // this is the first driver we have for this parameter name - final DelegatingDriver created = new DelegatingDriver(driver); - final ChangesForwarder forwarder = new ChangesForwarder(created); - created.setForwarder(forwarder); - delegating.add(created); + delegating.add(new DelegatingDriver(this, driver)); } } @@ -109,6 +107,19 @@ public class ParameterDriversList { return null; } + /** Replace a {@link DelegatingDriver delegating driver}. + * @param oldDelegating delegating driver to replace + * @param newDelegating new delegating driver to use + * @since 10.1 + */ + private void replaceDelegating(final DelegatingDriver oldDelegating, final DelegatingDriver newDelegating) { + for (int i = 0; i < delegating.size(); ++i) { + if (delegating.get(i) == oldDelegating) { + delegating.set(i, newDelegating); + } + } + } + /** Find a {@link DelegatingDriver delegating driver} by name. * @param name name to check * @return a {@link DelegatingDriver delegating driver} managing this parameter name @@ -141,8 +152,10 @@ public class ParameterDriversList { */ public void filter(final boolean selected) { for (final Iterator iterator = delegating.iterator(); iterator.hasNext();) { - if (iterator.next().isSelected() != selected) { + final DelegatingDriver delegatingDriver = iterator.next(); + if (delegatingDriver.isSelected() != selected) { iterator.remove(); + delegatingDriver.removeOwner(this); } } } @@ -173,55 +186,51 @@ public class ParameterDriversList { */ public static class DelegatingDriver extends ParameterDriver { - /** Drivers managing the same parameter. */ - private final List drivers; + /** Lists owning this delegating driver. */ + private final List owners; /** Observer for propagating changes between all drivers. */ private ChangesForwarder forwarder; /** Simple constructor. + * @param owner list owning this delegating driver * @param driver first driver in the series */ - DelegatingDriver(final ParameterDriver driver) { + DelegatingDriver(final ParameterDriversList owner, final ParameterDriver driver) { super(driver.getName(), driver.getReferenceValue(), driver.getScale(), driver.getMinValue(), driver.getMaxValue()); - drivers = new ArrayList(); - drivers.add(driver); + + owners = new ArrayList<>(); + addOwner(owner); setValue(driver.getValue()); setReferenceDate(driver.getReferenceDate()); setSelected(driver.isSelected()); + // set up a change forwarder observing both the raw driver and the delegating driver + this.forwarder = new ChangesForwarder(this, driver); + addObserver(forwarder); + driver.addObserver(forwarder); + } - /** Set the changes forwarder. - * @param forwarder new changes forwarder - * @since 9.1 + /** Add an owner for this delegating driver. + * @param owner owner to add */ - void setForwarder(final ChangesForwarder forwarder) { - - // remove the previous observer if any - if (this.forwarder != null) { - removeObserver(this.forwarder); - for (final ParameterDriver driver : drivers) { - driver.removeObserver(this.forwarder); - } - } - - // add the new observer - this.forwarder = forwarder; - addObserver(forwarder); - for (final ParameterDriver driver : drivers) { - driver.addObserver(forwarder); - } - + void addOwner(final ParameterDriversList owner) { + owners.add(owner); } - /** Get the changes forwarder. - * @return changes forwarder + /** Remove one owner of this driver. + * @param owner owner to remove delegating driver from + * @since 10.1 */ - ChangesForwarder getForwarder() { - return forwarder; + private void removeOwner(final ParameterDriversList owner) { + for (final Iterator iterator = owners.iterator(); iterator.hasNext();) { + if (iterator.next() == owner) { + iterator.remove(); + } + } } /** Add a driver. @@ -229,13 +238,6 @@ public class ParameterDriversList { */ private void add(final ParameterDriver driver) { - for (final ParameterDriver d : drivers) { - if (d == driver) { - // the driver is already known, don't add it again - return; - } - } - setValue(driver.getValue()); setReferenceDate(driver.getReferenceDate()); @@ -247,7 +249,55 @@ public class ParameterDriversList { } driver.addObserver(forwarder); - drivers.add(driver); + forwarder.add(driver); + + } + + /** Merge another instance. + *

    + * After merging, the other instance is merely empty and preserved + * only as a child of the current instance. Changes are therefore + * still forwarded to it, but it is itself not responsible anymore + * for forwarding change. + *

    + * @param other instance to merge + */ + private void merge(final DelegatingDriver other) { + + if (other.forwarder == forwarder) { + // we are attempting to merge an instance with either itself + // or an already embedded one, just ignore the request + return; + } + + // synchronize parameter + setValue(other.getValue()); + setReferenceDate(other.getReferenceDate()); + if (isSelected()) { + other.setSelected(true); + } else { + setSelected(other.isSelected()); + } + + // move around drivers + for (final ParameterDriver otherDriver : other.forwarder.getDrivers()) { + // as drivers are added one at a time and always refer back to a single + // DelegatingDriver (through the ChangesForwarder), they cannot be + // referenced by two different DelegatingDriver. We can blindly move + // around all drivers, there cannot be any duplicates + forwarder.add(otherDriver); + otherDriver.replaceObserver(other.forwarder, forwarder); + } + + // forwarding is now delegated to current instance + other.replaceObserver(other.forwarder, forwarder); + other.forwarder = forwarder; + + // replace merged instance with current instance in former owners + for (final ParameterDriversList otherOwner : other.owners) { + owners.add(otherOwner); + otherOwner.replaceDelegating(other, this); + } } @@ -258,7 +308,7 @@ public class ParameterDriversList { * @return raw drivers to which this one delegates */ public List getRawDrivers() { - return Collections.unmodifiableList(drivers); + return Collections.unmodifiableList(forwarder.getDrivers()); } } @@ -269,6 +319,9 @@ public class ParameterDriversList { /** DelegatingDriver we are associated with. */ private final DelegatingDriver delegating; + /** Drivers synchronized together by the instance. */ + private final List drivers; + /** Root of the current update chain. */ private ParameterDriver root; @@ -277,9 +330,12 @@ public class ParameterDriversList { /** Simple constructor. * @param delegating delegatingDriver we are associated with + * @param driver first driver in the series */ - ChangesForwarder(final DelegatingDriver delegating) { + ChangesForwarder(final DelegatingDriver delegating, final ParameterDriver driver) { this.delegating = delegating; + this.drivers = new ArrayList<>(); + drivers.add(driver); } /** Get the {@link DelegatingDriver} associated with this instance. @@ -290,12 +346,26 @@ public class ParameterDriversList { return delegating; } + /** Add a driver to the list synchronized together by the instance. + * @param driver driver to add + * @since 10.1 + */ + void add(final ParameterDriver driver) { + drivers.add(driver); + } + + /** Get the drivers synchronized together by the instance. + * @return drivers synchronized together by the instance. + * @since 10.1 + */ + public List getDrivers() { + return drivers; + } + /** {@inheritDoc} */ @Override public void valueChanged(final double previousValue, final ParameterDriver driver) { - updateAll(driver, d -> { - d.setValue(driver.getValue()); - }); + updateAll(driver, d -> d.setValue(driver.getValue())); } /** {@inheritDoc} */ @@ -353,7 +423,7 @@ public class ParameterDriversList { if (driver == getDelegatingDriver()) { // propagate change downwards, which will trigger recursive calls - for (final ParameterDriver d : delegating.drivers) { + for (final ParameterDriver d : drivers) { if (d != root) { updater.update(d); } diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8 index 1b27e32a3c24e380cc6ec1a47cda3ee4c16a033f..678dde70961aef6e217d92e95e4665c1087a9903 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_da.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8 index 44c731433e3c5e1640a906455dbad99eb9bb1f84..9dd9117a3c01566400ec006ec2472398d90ec2d6 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_de.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8 index 1a50a7c75350c4117c500b5e02000a47c5da7801..d72e620f1edb496e55c7edbb6834635d0707c2f3 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_el.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8 index 65112144f7d4cbcf71e29e62799fe1423dc86723..4c6194f5dc0e2823d8bedc9b654af4b911c51471 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_en.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = IONEX file {0} does not contain TEC data for date # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = number of maps {0} is inconsistent with header specification: {1} +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = file {0} does not contain latitude or longitude bondaries in its header section + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = file {0} does not contain epoch of first or last map in its header section + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -549,3 +555,23 @@ ITRF_VERSIONS_PREFIX_ONLY = The first column of itrf-versions.conf is a plain pr # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = STEC integration did not converge + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = MODIP grid not be loaded from {0} + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = NeQuick coefficient f2 or fm3 not be loaded from {0} + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = file {0} is not a supported Hatanaka-compressed file + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = invalid measurement types {0} and {1} for the combination of measurements {2} + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = frequencies {0} and {1} are incompatibles for the {2} combination + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = observations {0} and {1} are not in chronological dates diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8 index 6685d11214711cf237591b7f2bb710eea7dfa631..b2338764a6da56a64d9694aea98db838b0f62d0c 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_es.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8 index a869fdb318962bc10b54bb6e8d1fa580754d76d5..a006310a58ed8675edf2ba7dcb9313f952057886 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_fr.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = le fichier IONEX {0} ne contient pas de données # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = le nombre de cartes {0} est incompatible avec les specifications de l''en-tête: {1} +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = {0} ne contient pas de limites en latitude ou en longitude dans son en-tête + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = {0} ne contient pas de date de début ou de fin de carte dans son en-tête + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = la première colonne du fichier itrf-versions.conf e # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = impossible de calculer la direction de pointage pour le point singulier: latitude = {0}, longitude = {1} + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = l''integration du STEC n''a pas convergée + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = impossible de charger la grille de MODIP depuis {0} + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = impossible de charger les coefficients NeQuick f2 et fm3 depuis {0} + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = le fichier {0} n''est pas reconnu en tant que fichier compressé par la méthode d''Hatakana + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = les types de mesure {0} et {1} sont incompatibles pour la combinaison de mesures {2} + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = les fréquences {0} et {1} sont incompatibles pour la combinaison {2} + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = les observations aux dates {0} et {1} ne sont pas dans l''ordre chronologique diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8 index 96a47ada75093f0f34e2c5e538d58b9cc7221b20..74db6c70cd88d12d44f409f4ef1b3894181debf6 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_gl.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude or longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8 index c045d4784d78c805ff1646a3f6ccc0560718bd8d..40bb95f4076ee7b83d230855a95d159f2b152e93 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_it.utf8 @@ -542,6 +542,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = il file IONEX {0} non contiene dati TEC per la da # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = il numero di mappe {0} è incoerente con le specifiche dell''intestazione: {1} +# file {0} does not contain latitude and longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -549,3 +555,24 @@ ITRF_VERSIONS_PREFIX_ONLY = la prima colonna di itrf-versions.conf è un prefiss # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = impossibile calcolare la direzione di mira al punto singolare: latitudine = {0}, longitudine = {1} + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8 index 180800946b0e4587b937531b4dc8a58c71589eee..2ad9f921cd861d322d0000ed334fe1f0181790fe 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_no.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude and longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8 b/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8 index 678e9b8aeb6ba96fde49ec410d89f4f615e50dce..7ca29a7197cbc0262c92e3137b1f978f00cc3212 100644 --- a/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8 +++ b/src/main/resources/assets/org/orekit/localization/OrekitMessages_ro.utf8 @@ -541,6 +541,12 @@ NO_TEC_DATA_IN_FILE_FOR_DATE = # number of maps {0} is inconsistent with header specification: {1} INCONSISTENT_NUMBER_OF_TEC_MAPS_IN_FILE = +# file {0} does not contain latitude and longitude bondaries in its header section +NO_LATITUDE_LONGITUDE_BONDARIES_IN_IONEX_HEADER = + +# file {0} does not contain epoch of first or last map in its header section +NO_EPOCH_IN_IONEX_HEADER = + # The first column of itrf-versions.conf is a plain prefix that is matched against the # name of each loaded file. It should not contain any regular expression syntax or # directory components, i.e. \"/\" or \"\\\". Actual value: \"{0}\". @@ -548,3 +554,24 @@ ITRF_VERSIONS_PREFIX_ONLY = # cannot compute aiming direction at singular point: latitude = {0}, longitude = {1} CANNOT_COMPUTE_AIMING_AT_SINGULAR_POINT = + +# STEC integration did not converge +STEC_INTEGRATION_DID_NOT_CONVERGE = + +# MODIP grid not be loaded from {0} +MODIP_GRID_NOT_LOADED = + +# NeQuick coefficient f2 or fm3 not be loaded from {0} +NEQUICK_F2_FM3_NOT_LOADED = + +# file {0} is not a supported Hatanaka-compressed file +NOT_A_SUPPORTED_HATANAKA_COMPRESSED_FILE = + +# invalid measurement types {0} and {1} for the combination of measurements {2} +INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS = + +# frequencies {0} and {1} are incompatibles for the {2} combination +INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS = + +# observations {0} and {1} are not in chronological dates +NON_CHRONOLOGICAL_DATES_FOR_OBSERVATIONS = diff --git a/src/main/resources/assets/org/orekit/nequick/ccir11.asc b/src/main/resources/assets/org/orekit/nequick/ccir11.asc new file mode 100644 index 0000000000000000000000000000000000000000..96b9e19c23877465e52031d0d7b7f3a0979c6a38 --- /dev/null +++ b/src/main/resources/assets/org/orekit/nequick/ccir11.asc @@ -0,0 +1,715 @@ + 0.52396593E+01 -0.56523629E-01 -0.18704616E-01 0.12128916E-01 + 0.79412200E-02 -0.10031432E-01 0.21567253E-01 -0.68602669E-02 + 0.37022347E-02 0.78359321E-02 0.63161589E-02 -0.10695398E-01 + 0.29390156E-01 0.93325400E+00 -0.28997501E-01 0.10946779E+00 + -0.30769539E+00 -0.37993371E+00 -0.23273271E+00 0.89480698E-01 + 0.33896312E-01 0.32839006E+00 -0.81993341E-01 -0.14348942E+00 + -0.27823284E-01 0.11266430E-01 0.80531130E+01 0.13981723E+01 + 0.47361961E+00 -0.11388183E+00 0.77816737E+00 -0.17388149E+00 + 0.29099107E+00 0.29059123E-01 -0.37210888E+00 -0.11191851E+00 + -0.43733008E-01 0.12193084E+00 -0.32639456E+00 -0.13390854E+02 + 0.62356526E+00 0.24597547E+01 0.44970918E+01 0.85659552E+01 + 0.40355291E+01 -0.79231381E+00 -0.67203265E+00 -0.47442722E+01 + 0.21074810E+01 0.33913581E+01 -0.10161762E+00 -0.69574165E+00 + -0.32273560E+02 -0.56248398E+01 -0.58702979E+01 -0.43174982E+01 + -0.32914648E+01 0.14731911E+01 -0.84157687E+00 -0.18629676E+00 + 0.36630039E+01 -0.49589831E+00 0.42669845E+00 -0.39217407E+00 + 0.15235480E+01 -0.10364820E+00 -0.17449903E+02 -0.18375046E+02 + -0.16429413E+02 -0.42843185E+02 -0.18512325E+02 0.29954519E+01 + 0.44427662E+01 0.22331482E+02 -0.11312364E+02 -0.17385391E+02 + 0.13743352E+01 0.49287653E+01 0.35317551E+02 0.78040109E+01 + 0.22017227E+02 0.19007368E+02 0.51486940E+01 -0.32355108E+01 + -0.70289177E+00 -0.18949838E-01 -0.10833931E+02 0.30533838E+01 + -0.15614651E+01 0.34174812E+00 -0.33425491E+01 0.10955017E+03 + 0.64495300E+02 0.39307388E+02 0.21447479E+02 0.88321732E+02 + 0.36022034E+02 -0.49279385E+01 -0.11266347E+02 -0.45660416E+02 + 0.24368757E+02 0.36402847E+02 -0.37913997E+01 -0.12354782E+02 + -0.15069657E+02 -0.54928751E+01 -0.30891768E+02 -0.26297501E+02 + -0.28576374E+01 0.23907242E+01 0.27161198E+01 0.10669556E+01 + 0.12239297E+02 -0.43662004E+01 0.20293264E+01 0.21851628E+00 + 0.34469430E+01 -0.18371088E+03 -0.78854767E+02 -0.32724579E+02 + -0.86944237E+01 -0.80539780E+02 -0.31638613E+02 0.32864110E+01 + 0.12187759E+02 0.42042587E+02 -0.23398041E+02 -0.33907745E+02 + 0.42148323E+01 0.12834593E+02 0.22537870E+01 0.19722795E+01 + 0.14214871E+02 0.11752550E+02 0.97573817E-01 -0.41853246E+00 + -0.14487734E+01 -0.91950285E+00 -0.47050495E+01 0.19138947E+01 + -0.85748470E+00 -0.30080920E+00 -0.13293972E+01 0.86102798E+02 + 0.31215927E+02 0.92085867E+01 -0.52750915E+00 0.26795362E+02 + 0.10308077E+02 -0.60259056E+00 -0.47401171E+01 -0.14323978E+02 + 0.83509979E+01 0.11643826E+02 -0.16808404E+01 -0.47212677E+01 + 0.53214841E-02 0.17079000E+01 0.16235819E+01 0.33274174E-01 + -0.12954264E-01 -0.36316011E-02 0.45543168E-01 -0.43191575E-02 + -0.25532668E-01 0.89464858E-02 0.23123840E-01 0.16921321E-01 + 0.33485752E-01 -0.22577250E+00 -0.16961775E+01 0.17585012E+01 + -0.36464982E-01 -0.46494432E-01 -0.19080851E-02 -0.31143920E-01 + 0.10176011E-01 -0.69593936E-02 -0.66427360E-02 0.23588387E-02 + -0.55617541E-02 -0.19860145E-01 -0.17363092E+01 0.18277779E+01 + 0.16650457E+01 -0.48928317E-01 -0.43136492E+00 -0.47681876E-01 + 0.25482827E+00 -0.18712924E+00 0.47013283E+00 -0.17417169E+00 + 0.78237891E-01 0.10381133E+00 0.17819384E-01 -0.14371651E+01 + -0.80177718E+00 0.61360812E+00 -0.59573972E+00 0.52904451E+00 + -0.10058826E+00 0.21083134E+00 0.78204811E-01 0.61967522E-02 + 0.11077179E+00 -0.40769760E-01 0.21807816E-01 0.20648648E-02 + 0.46911736E+01 0.78173609E+01 0.12199426E+02 -0.16422653E+01 + 0.37755156E+01 -0.40263683E+00 -0.52920252E+00 -0.21391793E+00 + 0.57929236E+00 0.80246806E-01 -0.18910320E+00 -0.50804532E+00 + -0.88265944E+00 0.69275224E+00 -0.12002476E+02 0.57374411E+01 + 0.13528374E+01 0.44981871E+01 -0.47366244E+00 0.36056972E+00 + 0.79039747E+00 -0.22344507E-01 -0.64753890E-01 0.46970186E+00 + -0.40660375E+00 0.44191416E-01 0.39014664E+02 -0.28619869E+02 + -0.15200558E+01 -0.19682380E+01 0.13416007E+02 0.27089479E+01 + -0.59305797E+01 0.31192074E+01 -0.91367607E+01 0.26589973E+01 + -0.11606407E+00 -0.35579135E+01 -0.89003718E+00 0.34678040E+02 + -0.52889097E+00 -0.57936335E+01 0.87519836E+01 -0.10267423E+02 + 0.12299099E+01 -0.30112038E+01 0.11044226E+01 -0.21466112E+01 + 0.45218792E-01 0.30407922E+01 -0.71307266E+00 -0.15156336E+01 + -0.52359818E+02 -0.65902924E+02 -0.30542084E+02 0.45587654E+01 + -0.33256969E+02 0.32021561E+01 0.60264254E+01 0.39931145E+01 + -0.21957395E+01 -0.14460715E+01 -0.62892985E+00 0.19364243E+01 + 0.71591697E+01 0.99375763E+01 0.36078583E+02 -0.38465439E+02 + -0.34042757E+01 -0.46145634E+02 0.20836172E+01 -0.37764752E+01 + -0.62155056E+01 -0.36285689E+00 0.83748114E+00 -0.11298742E+01 + 0.38863552E+01 0.14642849E+01 -0.22182346E+03 0.11115141E+03 + -0.16951050E+02 0.17158339E+02 -0.61797070E+02 -0.21725037E+02 + 0.33751068E+02 -0.20662018E+02 0.52077255E+02 -0.10576082E+02 + 0.19523580E+00 0.24283321E+02 0.39174993E+01 -0.22131870E+03 + 0.17304182E+02 -0.28861008E+02 -0.44697052E+02 0.53147095E+02 + -0.61317329E+01 0.16753128E+02 -0.89905109E+01 0.20872986E+02 + -0.63277898E+01 -0.26276548E+02 0.64804440E+01 0.11094950E+02 + 0.17550494E+03 0.16372993E+03 -0.21463623E+02 0.27199810E+01 + 0.99251190E+02 -0.79424791E+01 -0.21751923E+02 -0.18336348E+02 + 0.69923621E+00 0.50953040E+01 0.72605686E+01 -0.15412291E+01 + -0.22803528E+02 -0.56229095E+02 0.14818200E+01 0.69807755E+02 + 0.33564429E+01 0.14655196E+03 -0.27966242E+01 0.12579897E+02 + 0.17929474E+02 0.43725863E+01 -0.22176218E+01 -0.37626829E+01 + -0.10943099E+02 -0.52088385E+01 0.53665625E+03 -0.20060768E+03 + 0.17310242E+02 -0.54237484E+02 0.99595352E+02 0.66468887E+02 + -0.80023056E+02 0.58134548E+02 -0.12709148E+03 0.15493524E+02 + -0.31282263E+01 -0.65706467E+02 -0.49680538E+01 0.55392432E+03 + -0.46328995E+02 0.14449484E+03 0.10233987E+03 -0.11556945E+03 + 0.13084748E+02 -0.44251144E+02 0.22732941E+02 -0.62439159E+02 + 0.21050629E+02 0.77459229E+02 -0.19942720E+02 -0.28916519E+02 + -0.23239844E+03 -0.18225693E+03 0.10545852E+03 -0.16537476E+02 + -0.12225864E+03 0.72478418E+01 0.29107880E+02 0.29596209E+02 + 0.43757658E+01 -0.56305580E+01 -0.14893910E+02 -0.16775293E+01 + 0.30470701E+02 0.95573685E+02 -0.82114166E+02 -0.54173035E+02 + -0.28702698E+01 -0.18174020E+03 -0.33480752E+00 -0.15407215E+02 + -0.20705091E+02 -0.86905785E+01 0.13393048E+01 0.11856749E+02 + 0.11862598E+02 0.56412411E+01 -0.58746802E+03 0.17872774E+03 + 0.44170807E+02 0.71773788E+02 -0.55947525E+02 -0.85275742E+02 + 0.84508286E+02 -0.71050827E+02 0.13868575E+03 -0.73421702E+01 + 0.69255681E+01 0.76826965E+02 0.51061606E+00 -0.58909229E+03 + 0.41609573E+02 -0.19081409E+03 -0.10350249E+03 0.11202155E+03 + -0.11497140E+02 0.53446167E+02 -0.24178513E+02 0.73052414E+02 + -0.24337906E+02 -0.93695747E+02 0.24911682E+02 0.31728121E+02 + 0.10805178E+03 0.77080933E+02 -0.67569351E+02 0.11093395E+02 + 0.53251942E+02 -0.18096046E+01 -0.12874348E+02 -0.15589550E+02 + -0.36182413E+01 0.18153867E+01 0.87414274E+01 0.19512452E+01 + -0.14214748E+02 -0.53066940E+02 0.58636520E+02 0.16770859E+02 + 0.15051440E+01 0.77045029E+02 0.18778744E+01 0.61496325E+01 + 0.81532841E+01 0.46847639E+01 0.32412457E+00 -0.78524046E+01 + -0.42911911E+01 -0.19247580E+01 0.23769147E+03 -0.61533981E+02 + -0.47820068E+02 -0.34214539E+02 0.40193148E+01 0.38487625E+02 + -0.32399445E+02 0.30905640E+02 -0.55419479E+02 -0.24066786E+00 + -0.41797304E+01 -0.32275726E+02 0.15222616E+01 0.22423344E+03 + -0.12581700E+02 0.80397064E+02 0.37280334E+02 -0.41082153E+02 + 0.31536262E+01 -0.23678225E+02 0.94953613E+01 -0.29353226E+02 + 0.94907122E+01 0.40155743E+02 -0.10989324E+02 -0.12388154E+02 + 0.20844081E-01 -0.80697119E-01 0.30533599E-01 -0.64598644E+00 + -0.16657440E+00 -0.21123191E-01 0.92248209E-02 -0.25574602E-02 + -0.73007606E-02 0.12166508E-01 -0.12164735E-01 0.68045147E-02 + -0.77586402E-02 -0.69821604E-01 0.10285665E-01 0.30625435E-01 + 0.12556809E+00 -0.77144939E+00 0.14403919E-01 0.32232672E-02 + -0.18554740E-01 0.41907094E-02 -0.10089986E-02 0.43220967E-02 + 0.18566685E-02 -0.25719404E-01 -0.36431217E+00 -0.18156898E+00 + -0.11474407E+00 0.64775425E+00 0.20361812E+00 0.58565475E-02 + -0.85165560E-01 -0.11972089E+00 -0.25655258E+00 -0.12931144E+00 + -0.37106670E-01 -0.15892605E+00 -0.45120209E-01 0.10515985E+01 + 0.61001372E+00 0.23907983E+00 -0.96539229E+00 0.35442737E+00 + -0.22381258E+00 0.19057482E+00 -0.75943321E-02 0.47220100E-01 + -0.86490214E-02 0.44078577E-01 -0.37896220E-01 -0.78807138E-02 + 0.27450144E+00 -0.69624442E+00 -0.14316444E+01 0.18575619E+01 + 0.37408111E+01 -0.57409221E+00 -0.48675665E+00 0.22489710E+00 + -0.55995405E-01 0.24701400E+00 0.39949957E-01 0.95097050E-02 + 0.15562671E+00 0.29598873E+01 -0.22428036E+01 0.16291960E+01 + -0.38134632E+01 0.55432539E+01 -0.76043952E+00 -0.81076157E+00 + 0.97178990E+00 0.18208522E+00 -0.16950764E-01 0.58102113E+00 + -0.36130011E+00 0.14220279E+00 0.34898541E+01 0.21215763E+01 + 0.22773733E+01 -0.46729574E+01 0.32191401E+01 0.10207691E+01 + 0.40245906E+00 0.71286887E+00 0.25590410E+01 0.10251751E+01 + -0.47245732E+00 0.82578123E+00 -0.63747823E-01 -0.69263587E+01 + -0.71795802E+01 0.26847792E+01 0.42841091E+01 -0.33002298E+01 + 0.25364313E+01 -0.16150084E+01 0.56352544E+00 0.55770433E+00 + 0.44689545E+00 -0.62278980E+00 -0.38403079E+00 -0.24888089E+00 + -0.28185654E+01 0.10438053E+02 0.53413091E+01 0.12666808E+02 + 0.10997744E+02 0.27631533E+01 0.28622415E+01 -0.12079479E+01 + 0.16985101E+01 -0.21927738E+01 0.75003195E+00 0.98793447E-01 + -0.10628949E+01 -0.15150088E+02 0.23410826E+02 -0.12058938E+02 + -0.97661982E+01 -0.59994440E+01 0.12919569E+01 0.10240660E+01 + -0.46654778E+01 -0.17236118E+01 0.58620757E+00 -0.33529606E+01 + 0.26049087E+01 -0.11627923E+00 -0.76791868E+01 -0.53989239E+01 + -0.93963966E+01 0.89348898E+01 -0.13714699E+02 -0.40793180E+01 + -0.13703756E+01 -0.11329165E+01 -0.66214285E+01 -0.19741460E+01 + 0.19676807E+01 -0.15802439E+01 0.74486417E+00 0.10005783E+02 + 0.22066393E+02 -0.93126631E+01 -0.34220304E+01 0.73809199E+01 + -0.56643806E+01 0.28039863E+01 -0.20841558E+01 -0.25536554E+01 + -0.20768547E+01 0.14609889E+01 0.22773333E+01 0.10445652E+01 + 0.88902111E+01 -0.21831713E+02 -0.75236998E+01 -0.45947891E+02 + -0.52254837E+02 -0.43777103E+01 -0.65832410E+01 0.27934113E+01 + -0.51957226E+01 0.45358448E+01 -0.29035003E+01 -0.80293536E+00 + 0.31588888E+01 0.30450516E+02 -0.57946453E+02 0.24090500E+02 + 0.50759995E+02 -0.16110199E+02 0.35295737E+01 0.28397503E+01 + 0.93683434E+01 0.46508341E+01 -0.98472542E+00 0.71794257E+01 + -0.56259937E+01 0.42344132E+00 0.37496376E+01 0.41398544E+01 + 0.89929867E+01 -0.21592083E+01 0.15710482E+02 0.37366180E+01 + 0.12688894E+01 0.56009918E+00 0.45878363E+01 0.10043669E+01 + -0.15857162E+01 0.11541929E+01 -0.63341981E+00 -0.16841688E+01 + -0.19766066E+02 0.61021028E+01 -0.47736244E+01 -0.30741682E+01 + 0.37985227E+01 -0.14054888E+01 0.19982290E+01 0.24144678E+01 + 0.21827765E+01 -0.78220946E+00 -0.24638700E+01 -0.81352621E+00 + -0.86120291E+01 0.12768568E+02 0.40449324E+01 0.35735748E+02 + 0.45281525E+02 0.14536484E+01 0.48580322E+01 -0.21178226E+01 + 0.40526733E+01 -0.26759615E+01 0.23512812E+01 0.86008638E+00 + -0.27273741E+01 -0.23491455E+02 0.42392090E+02 -0.13589549E+02 + -0.45290329E+02 0.22402477E+02 -0.52239590E+01 -0.39634600E+01 + -0.66355686E+01 -0.30386248E+01 0.24522118E+00 -0.52094822E+01 + 0.38612597E+01 -0.76240206E+00 -0.14890508E+00 -0.24325430E-01 + -0.38893390E-01 0.66723585E-01 0.59333671E-01 -0.36929661E+00 + -0.60848284E+00 0.94836205E-02 0.54205763E-02 -0.15333357E-01 + -0.11106117E-02 0.22575625E-02 0.23593076E-02 -0.22660283E-01 + 0.45373969E-01 0.50671659E-01 -0.36677148E-01 0.63135207E-01 + 0.61916250E+00 -0.39381257E+00 -0.22737507E-01 0.37895910E-01 + -0.11128757E-01 -0.91112591E-02 -0.10985606E-01 0.15489354E-01 + -0.22802022E+00 0.26512158E+00 -0.22216138E+00 0.10585244E+00 + -0.16293722E+00 -0.69953334E+00 -0.20355964E+00 0.23573790E-01 + 0.29221946E-01 -0.58141429E-01 -0.10479218E+00 0.38031030E-01 + 0.34238581E-01 -0.32278049E+00 0.10433109E+00 -0.70636094E-01 + -0.45763809E-01 0.49903281E-01 0.49318543E+00 -0.80187607E+00 + -0.83227634E-01 0.23710171E-01 -0.30420637E-01 -0.10782067E-01 + 0.52331042E-01 0.40990692E-01 0.75721163E+00 -0.10054684E+00 + -0.43790364E+00 0.35622925E-01 -0.68008202E+00 0.13344153E+01 + 0.10325203E+01 0.21211478E+00 -0.52811492E-01 0.58822643E-01 + -0.29041560E-01 0.13278133E+00 0.60832471E-01 -0.51921064E+00 + 0.73404193E-01 -0.14045805E+00 0.56511676E+00 -0.10780087E+01 + -0.90128416E+00 0.18347826E+01 0.23589997E-01 0.19664788E+00 + 0.10371150E+00 0.16768134E+00 0.25422746E+00 -0.27516479E-01 + 0.47642750E+00 -0.12712888E+01 0.50919580E+00 -0.37558299E-01 + 0.41861004E+00 0.72344553E+00 0.58304828E+00 -0.37630741E-01 + -0.21993767E-01 0.15301681E+00 0.14597134E+00 -0.88676035E-01 + -0.34135389E-02 0.10227041E+01 -0.10414064E+00 0.21676075E+00 + -0.18772216E+00 0.27981550E+00 -0.11495647E+01 0.94243646E+00 + 0.13660997E+00 -0.18090218E+00 0.32121956E-01 0.75706482E-01 + -0.24605010E+00 -0.13862634E+00 -0.76268691E+00 0.10962811E+01 + 0.10399638E+01 0.96028931E-01 0.77267742E+00 -0.18069419E+01 + -0.60100138E+00 -0.48312187E+00 -0.72206438E-01 0.13322053E-02 + -0.17916759E-01 -0.28112435E+00 -0.19206631E-02 0.68990117E+00 + -0.17288911E+00 0.42733532E+00 -0.42356348E+00 0.20443859E+01 + 0.25324249E+00 -0.22968807E+01 0.21025424E+00 -0.64606422E+00 + -0.20289104E+00 -0.37085348E+00 -0.52354544E+00 -0.47585368E-01 + 0.59121333E-01 0.75014154E-02 0.32973830E-01 0.16474612E-01 + 0.32099038E-02 0.20523885E-01 0.14850209E-01 0.15989558E+00 + -0.22012539E+00 0.11682351E-01 0.37532365E-02 0.28839896E-02 + 0.90501495E-02 0.25123443E-01 -0.54974113E-01 -0.40254004E-01 + -0.64294338E-01 0.18476808E-01 0.54143369E-02 0.26773553E-01 + 0.22185428E+00 0.18453132E+00 0.40824944E-03 -0.20066461E-01 + 0.10584317E-01 -0.42071901E-02 -0.11119862E-01 -0.84521770E-01 + -0.72065473E-01 -0.10357255E+00 0.25481066E-01 -0.31697039E-01 + -0.34495179E-01 -0.12500072E+00 -0.29316074E+00 -0.50189231E-01 + 0.20690961E-01 0.20984368E-01 0.46142556E-01 0.31204319E-02 + -0.15957630E+00 -0.45523684E-01 0.11955297E-02 0.21015655E-01 + 0.35082825E-01 -0.32445975E-01 0.22741143E+00 -0.11440505E+00 + 0.16439868E-01 -0.42733327E-02 0.36579225E-01 -0.35476536E-01 + 0.20448798E-01 0.88741958E-01 -0.45464959E-01 -0.15399727E-01 + 0.49765371E-01 -0.19545292E-01 0.20340795E-01 -0.11448290E-01 + 0.21605458E-01 0.11625880E+00 0.15443806E+00 -0.68518184E-02 + 0.68731946E-02 0.44177953E-01 0.17190438E-01 -0.34843344E-01 + -0.55796959E-01 -0.18618047E-01 -0.13446326E-02 -0.13807907E-01 + 0.16442720E-01 -0.63370585E-01 -0.13994680E+00 0.10775572E+00 + 0.18059419E-01 -0.11631263E-02 0.56581873E-01 -0.43296669E-01 + 0.87594800E-02 -0.19183893E-01 0.22148753E-01 0.16138325E-01 + 0.35961125E-01 0.62827729E-02 -0.29091935E-02 0.17914118E-01 + 0.23472056E-01 -0.40293448E-01 0.52220736E-01 -0.28325748E-01 + 0.18121799E-01 -0.55669229E-01 -0.43550450E-01 -0.41511983E-01 + 0.28219912E-03 -0.45169748E-01 0.30541521E-01 -0.75302450E-02 + 0.11561215E-01 -0.71855858E-02 -0.42805452E-01 -0.74895382E-01 + -0.40362079E-01 0.39089802E-02 -0.43586571E-01 -0.13430197E-01 + 0.19074352E-01 -0.14927470E-02 -0.83385855E-02 0.12412880E-01 + -0.39789900E-02 -0.93350485E-02 0.31809625E-03 0.69165081E-02 + 0.16948409E-01 0.40239397E-01 0.21818380E-02 -0.23886045E-01 + -0.19706257E-02 0.17834106E-01 0.75256266E-02 -0.88512674E-02 + 0.25555318E-01 0.24699422E-01 -0.68906401E-02 -0.15585790E-02 + 0.12531396E-01 -0.15920259E-01 0.71578026E-01 0.36469545E-01 + -0.18202314E-01 0.23860380E-01 -0.15428271E-02 -0.31324875E-01 + 0.12997809E-01 0.49806461E-02 -0.13169400E-01 0.15163812E-01 + 0.45059994E-02 0.96705593E-02 0.32339197E-01 -0.71236551E-01 + 0.24793786E-03 0.38303077E-01 0.23001377E-01 -0.34666590E-02 + 0.19711128E-01 0.14156576E-01 -0.15163545E-02 0.14914330E-01 + -0.16906055E-01 0.68336162E-02 0.72287619E-02 -0.10352530E-01 + 0.84432192E+01 -0.17606992E-01 -0.12995031E-01 0.30051457E-01 + 0.45477945E-01 0.12136348E-01 -0.20886989E-01 -0.25218518E-01 + 0.38802756E-02 0.50634779E-02 0.17426118E-01 -0.19343944E-01 + 0.21120736E-01 0.13067626E+01 -0.19031614E+00 -0.47110277E+00 + 0.15309572E+00 -0.25000983E+00 -0.21639533E+00 0.13572133E+00 + 0.16442589E-01 0.29920632E+00 -0.35695665E-01 0.72213779E-02 + 0.36948244E-03 -0.19350249E+00 0.20192822E+02 0.10371314E+00 + -0.12936906E+01 -0.47384897E+00 0.43617851E+00 -0.88357633E+00 + 0.84384918E+00 0.40130624E+00 -0.24254838E+00 0.19504283E+00 + -0.32403553E+00 0.68768030E+00 -0.70447677E+00 0.10385976E+02 + 0.26844604E+01 0.91865940E+01 -0.28847568E+01 0.69040632E+01 + 0.30880928E+01 -0.16791334E+01 -0.77926904E+00 -0.40792050E+01 + 0.16587725E+01 0.11048365E+01 0.56877960E-01 0.26553493E+01 + -0.94894257E+02 -0.74020922E+00 0.97572689E+01 -0.13988618E+01 + -0.48308020E+01 0.61252832E+01 -0.29142206E+01 -0.31117847E+01 + 0.10199929E+01 -0.25860062E+01 0.15488663E+01 -0.52199421E+01 + 0.62431126E+01 -0.15947099E+03 -0.33153687E+02 -0.38277393E+02 + 0.16296082E+02 -0.37176071E+02 -0.16504715E+02 0.97844954E+01 + 0.60243282E+01 0.18602615E+02 -0.88784885E+01 -0.70023069E+01 + -0.85667688E+00 -0.10270858E+02 0.14434689E+03 0.40043659E+01 + -0.22543152E+02 0.10819620E+02 0.13452056E+02 -0.14324648E+02 + 0.14989967E+01 0.83210297E+01 -0.11521397E+01 0.86834040E+01 + -0.32280767E+01 0.13568054E+02 -0.17570890E+02 0.46371680E+03 + 0.11013431E+03 0.54929169E+02 -0.38762985E+02 0.82882599E+02 + 0.38311661E+02 -0.25024157E+02 -0.15210931E+02 -0.36635258E+02 + 0.18874268E+02 0.14921486E+02 0.31062038E+01 0.17111542E+02 + -0.10361340E+03 -0.10559740E+02 0.20353821E+02 -0.17083008E+02 + -0.12879773E+02 0.13625261E+02 0.28179274E+01 -0.85639162E+01 + -0.39836457E+00 -0.10996530E+02 0.32205973E+01 -0.14092369E+02 + 0.19663300E+02 -0.51334302E+03 -0.13410316E+03 -0.27003067E+02 + 0.40749176E+02 -0.81037048E+02 -0.38719090E+02 0.27226254E+02 + 0.15593899E+02 0.32171307E+02 -0.18132612E+02 -0.12962886E+02 + -0.39625752E+01 -0.13030040E+02 0.30432692E+02 0.74267564E+01 + -0.65251379E+01 0.81919823E+01 0.35932455E+01 -0.45463295E+01 + -0.21767292E+01 0.29457209E+01 0.77555543E+00 0.47232056E+01 + -0.12480307E+01 0.50437913E+01 -0.76494975E+01 0.19720856E+03 + 0.54842209E+02 0.14811363E+01 -0.15508769E+02 0.28584122E+02 + 0.13968619E+02 -0.10371296E+02 -0.56411085E+01 -0.10385418E+02 + 0.65630751E+01 0.39054108E+01 0.16419486E+01 0.37288153E+01 + 0.73617697E-01 0.15868282E+01 0.15948018E+01 -0.51909208E-01 + 0.10965754E+00 0.42061005E-01 0.86369067E-02 -0.35956562E-01 + -0.24439633E-01 0.13813863E-01 0.33473484E-01 -0.12541714E-01 + 0.13831582E-01 -0.22122268E+00 -0.16716870E+01 0.17568768E+01 + -0.10806261E+00 -0.60551725E-01 0.32627717E-01 -0.40097754E-01 + 0.32800335E-01 -0.22351673E-01 -0.30436331E-01 0.85034929E-02 + 0.44959597E-02 -0.57923377E-01 -0.13319710E+01 0.20320992E+00 + 0.28417444E+01 -0.26053953E+00 0.41736744E-01 0.48073849E+00 + 0.30752099E+00 0.27773428E+00 0.58028370E+00 -0.27988780E+00 + 0.20987780E+00 0.21454687E+00 -0.21824504E+00 -0.32366133E+00 + -0.18102025E+01 0.73649567E+00 -0.12784365E+01 0.13987559E+00 + 0.29401946E+00 -0.11734487E+00 0.30285734E+00 0.47187988E-01 + -0.40725452E+00 0.69726706E-01 -0.14392922E-01 -0.16440731E+00 + 0.43222733E+01 0.25277065E+02 -0.94375877E+01 0.12424450E+01 + 0.19729581E-01 -0.89677179E+00 -0.36436403E+00 0.90389621E+00 + -0.13076816E+00 0.15358768E+00 -0.36496457E+00 0.83983088E+00 + -0.97137809E-01 -0.39563198E+01 0.94551935E+01 0.17336027E+02 + 0.19375324E+01 0.29811149E+01 0.36434084E+00 0.96826065E+00 + 0.76319695E-01 0.63908470E+00 0.66578782E+00 -0.31862479E+00 + -0.63156575E+00 0.88741779E-01 0.31899078E+02 0.26338455E+02 + -0.26924988E+02 -0.28954153E+01 0.11245871E+01 -0.62383065E+01 + -0.71671295E+01 -0.44009342E+01 -0.11893279E+02 0.59641714E+01 + -0.12007704E+01 -0.48183508E+01 0.41470280E+01 0.29249303E+01 + 0.10189669E+02 0.64222164E+01 0.16846100E+02 -0.56195574E+01 + -0.38048904E+01 0.29024999E+01 -0.38915317E+01 -0.16548052E+01 + 0.71972713E+01 0.18794575E+01 0.20752628E+00 0.15136870E+01 + -0.47960709E+02 -0.14527844E+03 0.13558260E+03 -0.15012978E+02 + -0.89980879E+01 0.33358765E+01 0.65263829E+01 -0.57562590E+01 + 0.23737574E+01 -0.32089405E+01 0.66337514E+00 -0.98810377E+01 + -0.12185402E+01 0.54375408E+02 -0.13382069E+03 -0.69432632E+02 + -0.15594944E+02 -0.28076584E+02 -0.55643234E+01 -0.81322346E+01 + -0.26028937E+00 -0.52387094E+01 -0.39641640E+01 0.58208842E+01 + 0.58059583E+01 0.43214092E+01 -0.18676459E+03 -0.16449844E+03 + 0.18679526E+03 0.44028061E+02 0.67239270E+01 0.20764875E+02 + 0.43572433E+02 0.15105405E+02 0.72933273E+02 -0.35417358E+02 + -0.33102429E+01 0.33491135E+02 -0.28131254E+02 0.13132271E+02 + -0.71697983E+02 -0.14838393E+02 -0.88297775E+02 0.35739059E+02 + 0.24429443E+02 -0.19637222E+02 0.15767019E+02 0.12106134E+02 + -0.38460907E+02 -0.17444714E+02 -0.57627004E+00 -0.71105013E+01 + 0.16358971E+03 0.30532544E+03 -0.45578516E+03 0.51725407E+02 + 0.42051998E+02 -0.12835168E+01 -0.28778364E+02 0.11572843E+02 + -0.11792857E+02 0.97184315E+01 0.28023021E+01 0.34010326E+02 + 0.76306806E+01 -0.19060995E+03 0.45207544E+03 0.60605190E+02 + 0.49964783E+02 0.83181351E+02 0.17889481E+02 0.23796246E+02 + -0.10524483E+01 0.17759962E+02 0.98242826E+01 -0.24883148E+02 + -0.17036592E+02 -0.18363981E+02 0.47393289E+03 0.36210422E+03 + -0.54417676E+03 -0.15719067E+03 -0.48869659E+02 -0.19227539E+02 + -0.11137080E+03 -0.14016640E+02 -0.18484474E+03 0.86145981E+02 + 0.26243608E+02 -0.93299728E+02 0.76153839E+02 -0.10607855E+03 + 0.18373106E+03 -0.71254372E+02 0.21552979E+03 -0.88725647E+02 + -0.66744751E+02 0.48730530E+02 -0.28787106E+02 -0.34096436E+02 + 0.84370392E+02 0.52670151E+02 -0.46487325E+00 0.18449722E+02 + -0.22080928E+03 -0.29196875E+03 0.61042773E+03 -0.71494476E+02 + -0.68313873E+02 -0.85744400E+01 0.44273830E+02 -0.82676735E+01 + 0.20448517E+02 -0.80523005E+01 -0.84449396E+01 -0.45622375E+02 + -0.12797120E+02 0.25156477E+03 -0.59986981E+03 0.34923367E+02 + -0.63288605E+02 -0.98415482E+02 -0.20724581E+02 -0.28114670E+02 + 0.44651842E+01 -0.23789309E+02 -0.11882714E+02 0.37959538E+02 + 0.19314938E+02 0.25713852E+02 -0.54166943E+03 -0.33657813E+03 + 0.70614551E+03 0.21372903E+03 0.80236282E+02 -0.66625934E+01 + 0.12710116E+03 -0.65174899E+01 0.20572482E+03 -0.91904800E+02 + -0.43451691E+02 0.11079333E+03 -0.87262207E+02 0.19350168E+03 + -0.21782204E+03 0.19717970E+03 -0.23897548E+03 0.95249496E+02 + 0.76332977E+02 -0.49345139E+02 0.26176374E+02 0.39268753E+02 + -0.81754929E+02 -0.66510437E+02 0.24783337E+01 -0.23144760E+02 + 0.10398346E+03 0.10713031E+03 -0.28724731E+03 0.34307175E+02 + 0.36974197E+02 0.81658230E+01 -0.22095411E+02 0.13036776E+01 + -0.11200825E+02 0.97571474E+00 0.54882069E+01 0.21151993E+02 + 0.67120991E+01 -0.11383264E+03 0.27709839E+03 -0.45287552E+02 + 0.26823547E+02 0.40176468E+02 0.79526615E+01 0.11477461E+02 + -0.35184114E+01 0.10715306E+02 0.56945724E+01 -0.19063520E+02 + -0.72694082E+01 -0.11852451E+02 0.22522437E+03 0.11369880E+03 + -0.33281445E+03 -0.10020544E+03 -0.39448944E+02 0.11468914E+02 + -0.53004150E+02 0.10001610E+02 -0.83203133E+02 0.35805695E+02 + 0.21695694E+02 -0.46803162E+02 0.35515350E+02 -0.10584344E+03 + 0.98553574E+02 -0.12213637E+03 0.96482056E+02 -0.38166553E+02 + -0.30556108E+02 0.17174088E+02 -0.97377214E+01 -0.15434035E+02 + 0.29186674E+02 0.30085253E+02 -0.17299672E+01 0.10782919E+02 + -0.27865283E-01 -0.14160953E+00 -0.46167344E-01 -0.83359635E+00 + 0.54028988E+00 0.17667169E-01 -0.23999680E-02 -0.50582860E-01 + -0.34205619E-01 0.24929952E-01 -0.20637266E-01 -0.54828972E-02 + -0.16638442E-02 -0.99061310E-01 -0.61199148E-02 0.16169675E-01 + -0.50423771E+00 -0.87746030E+00 -0.14626429E-02 0.91258921E-02 + 0.41810907E-01 0.27339894E-02 -0.15622666E-02 0.32905261E-02 + 0.18039156E-01 -0.38937837E-01 -0.11977397E+00 -0.37973851E-01 + 0.51543677E+00 -0.18759679E+01 0.63566899E+00 0.28123093E+00 + -0.29566634E+00 -0.18840618E-01 -0.36266062E-01 -0.26874977E+00 + -0.17266949E+00 0.10599524E-01 -0.83736897E-01 0.49956435E+00 + 0.68339938E+00 0.18975423E+00 -0.11983262E+01 -0.20601561E+01 + 0.58113430E-01 0.15165168E+00 0.12512308E+00 0.19267316E+00 + -0.55146992E-01 0.15980951E+00 0.82305312E-01 -0.42632777E-01 + 0.23057375E+01 0.76537257E+00 0.43733454E+01 -0.50523310E+01 + 0.28448105E+01 0.51284903E+00 -0.16459599E+01 0.74293798E+00 + 0.66224158E-01 -0.41510162E+00 0.26375908E+00 0.37355471E+00 + -0.17590468E+00 0.11372099E+01 -0.12647939E+00 0.25441616E+01 + -0.39932528E+01 -0.41477356E+01 0.13616856E+01 -0.13583241E+00 + -0.12699012E+01 -0.66975020E-02 -0.43774168E-02 0.72404754E+00 + -0.79435599E+00 0.15491712E+00 0.19683876E+01 0.29083941E+01 + -0.72367458E+01 0.59465561E+01 -0.19175699E+01 -0.14585570E+01 + 0.16693544E+01 -0.56365871E+00 0.17722520E+01 0.32326117E+01 + 0.53729033E+00 -0.88220710E+00 -0.56293684E+00 -0.41296844E+01 + -0.31065302E+01 0.19166174E+01 0.91364346E+01 0.66980743E+01 + 0.77398407E+00 -0.30196124E+00 -0.13194684E+01 -0.16660861E+01 + 0.88819361E+00 -0.11270266E+01 -0.17106762E+01 0.95284760E-01 + -0.11591568E+02 0.10206954E+02 -0.44386230E+02 0.47346344E+02 + -0.79038382E+00 -0.90883474E+01 0.11115670E+02 -0.19898727E+01 + 0.37733057E+00 0.13326263E+01 -0.29739463E+00 -0.21107409E+01 + 0.19746448E+01 -0.77565370E+01 0.19142866E+02 -0.19318726E+02 + 0.79751487E+01 0.45732677E+02 -0.11700180E+02 -0.21409185E+01 + 0.95194101E+01 -0.12891825E+01 -0.70309067E+00 -0.49068880E+01 + 0.54949455E+01 0.72287112E+00 -0.51350603E+01 -0.88256531E+01 + 0.16213120E+02 -0.95362787E+01 -0.49770889E+01 0.10020866E+01 + -0.38989055E+01 0.27658882E+01 -0.65731020E+01 -0.83604736E+01 + -0.15559012E+00 0.25949469E+01 0.29289787E+01 0.96731539E+01 + 0.52264996E+01 -0.65303121E+01 -0.14551663E+02 -0.86602287E+01 + -0.16371937E+01 -0.16511115E+01 0.34544618E+01 0.35504465E+01 + -0.31492510E+01 0.25533752E+01 0.52310610E+01 -0.48787493E-01 + 0.20374847E+02 -0.30132751E+02 0.10810121E+03 -0.10528986E+03 + -0.18006439E+02 0.24039797E+02 -0.24310305E+02 0.27824402E+01 + -0.91876066E+00 -0.13190975E+01 -0.37454164E+00 0.39671352E+01 + -0.47484903E+01 0.22527529E+02 -0.60154236E+02 0.38476715E+02 + 0.45293003E+00 -0.10749376E+03 0.29633497E+02 0.56231308E+01 + -0.19200821E+02 0.49150085E+01 0.26779366E+01 0.99957170E+01 + -0.12485247E+02 -0.21405020E+01 0.15377274E+01 0.74568510E+01 + -0.10354220E+02 0.10922907E+02 0.13785338E+02 0.83337110E+00 + 0.27636354E+01 -0.27910290E+01 0.50508103E+01 0.60138636E+01 + -0.15283442E+00 -0.17226228E+01 -0.27341881E+01 -0.54970150E+01 + -0.42347345E+01 0.50668464E+01 0.30705661E+00 0.80789337E+01 + 0.52706480E+00 0.30988748E+01 -0.23904352E+01 -0.23165932E+01 + 0.27464485E+01 -0.15124301E+01 -0.44464521E+01 0.11784692E+00 + -0.12952716E+02 0.21251144E+02 -0.73948395E+02 0.71904922E+02 + 0.22982941E+02 -0.17152084E+02 0.16589584E+02 -0.19711390E+01 + 0.14029668E+00 0.53307498E+00 0.45210415E+00 -0.22865255E+01 + 0.31447535E+01 -0.21541489E+02 0.48531139E+02 -0.20743685E+02 + -0.97520981E+01 0.76132248E+02 -0.22496305E+02 -0.30357063E+01 + 0.11248891E+02 -0.39207582E+01 -0.22813702E+01 -0.63165541E+01 + 0.86511211E+01 0.12434311E+01 -0.15622103E+00 -0.59632380E-01 + -0.90208650E-01 0.19414157E-01 0.73269010E-01 -0.56129467E+00 + -0.63541585E+00 -0.16588993E-01 -0.34606468E-01 -0.21938423E-02 + -0.21088142E-01 -0.10219838E-01 0.62936135E-02 0.10229759E+00 + 0.31424814E-02 0.12619577E+00 -0.10478984E-01 0.10643310E+00 + 0.63880980E+00 -0.58100116E+00 -0.80984813E-03 -0.32982638E-02 + -0.10336743E-01 -0.12900263E-01 -0.13739295E-01 0.22639142E-01 + 0.11596614E+00 0.24706095E+00 -0.15466779E+00 -0.18783575E+00 + -0.65919518E-01 -0.62681043E+00 -0.66545188E+00 0.32444052E-01 + 0.13160098E+00 0.13321730E-01 -0.10927582E+00 0.71161747E-01 + 0.11962272E-01 -0.13758808E+00 -0.70412159E-01 0.23057576E+00 + -0.63733459E-01 -0.23197371E-02 0.77353519E+00 -0.66607165E+00 + -0.11856483E+00 0.19452100E+00 0.44829208E-01 0.53664814E-02 + 0.81992805E-01 -0.22440353E-01 0.17074039E+01 0.56844890E+00 + -0.19279140E+00 -0.48811179E+00 -0.82032901E+00 0.17906553E+01 + 0.46447378E+00 0.62934273E+00 0.11496824E+00 0.72347283E-01 + 0.16785286E+00 0.25202709E+00 0.64511716E-01 -0.21264601E+01 + 0.78551662E+00 -0.27990741E+00 0.20393796E+00 -0.17369803E+01 + -0.49138680E+00 0.25081100E+01 -0.13376951E+00 0.84815377E+00 + 0.67785092E-01 -0.21081494E-01 0.27407336E+00 -0.19572496E+00 + 0.22916570E+00 -0.89228177E+00 0.14403731E+00 0.62578565E+00 + 0.42053264E-01 -0.14299738E+00 0.10011272E+01 -0.10695213E+00 + -0.26902199E+00 0.31509314E-01 0.18015152E+00 -0.22677259E+00 + 0.45944665E-01 0.78097397E+00 0.17563754E+00 -0.79983294E+00 + -0.23202593E-01 0.51307887E+00 -0.12497673E+01 0.63095033E-01 + 0.27101773E+00 -0.64966005E+00 -0.12470670E+00 0.57328969E-01 + -0.25540155E+00 0.30125933E-01 -0.36262932E+01 0.51153998E-04 + 0.65369076E+00 0.12630243E+01 0.59161860E+00 -0.33515158E+01 + 0.12459384E+00 -0.92280024E+00 0.16300046E+00 -0.98683946E-02 + -0.39698187E+00 -0.33663473E+00 -0.30247193E-01 0.35409753E+01 + -0.94228369E+00 0.59330601E+00 -0.47572304E-01 0.26288929E+01 + -0.11341673E+00 -0.40985451E+01 0.55726737E+00 -0.15782919E+01 + -0.92821479E-01 -0.86877584E-01 -0.41220182E+00 0.23814104E+00 + 0.40369987E-01 0.69174051E-01 0.90490915E-02 0.33020664E-01 + 0.11527483E-01 0.12345884E-01 0.26705261E-01 0.19554184E+00 + -0.36173040E+00 0.22097258E-01 -0.12866686E-01 0.62658112E-02 + 0.24714431E-01 0.16548367E-01 -0.36080949E-01 -0.25610084E-01 + -0.21156788E-01 0.43353237E-01 -0.31337325E-01 0.13042551E-01 + 0.34459084E+00 0.21506377E+00 0.16185859E-01 -0.13301041E-01 + 0.14696218E-01 0.17140716E-01 0.11640609E+00 -0.35488158E-01 + -0.61050300E-01 -0.10260254E+00 0.45410369E-01 -0.78796074E-02 + -0.90719387E-02 -0.14850968E+00 -0.58185768E+00 -0.61733756E-01 + -0.32026162E-02 0.21957424E-01 0.52263442E-01 0.55307172E-01 + -0.17401585E-01 -0.41585356E-01 0.76646626E-01 -0.57702400E-02 + -0.12208955E+00 0.50012428E-01 0.47269493E+00 0.20059487E-02 + 0.50178029E-01 -0.18123775E-02 0.58514785E-01 -0.23311082E-01 + 0.39524499E-01 0.80552042E-01 -0.42998645E-01 0.16749270E-01 + 0.31579152E-01 -0.44717081E-02 -0.84887660E-03 -0.49433589E-01 + 0.10765206E-01 0.21353498E+00 0.13728052E+00 -0.10284929E-01 + 0.20548500E-01 0.99338472E-01 0.17302404E-02 0.41451101E-04 + -0.84679365E-01 -0.11557482E-01 -0.22574198E-01 -0.23921097E-01 + -0.82226358E-02 -0.69644861E-01 -0.13849449E+00 0.20419700E+00 + 0.16953167E-01 0.82117133E-02 0.72829008E-01 -0.41823316E-01 + 0.10375716E-01 -0.56614611E-01 0.41825403E-01 0.20270184E-01 + 0.12032609E-01 -0.24085417E-01 -0.12075845E-01 0.61627734E-02 + 0.59546161E-01 -0.69685983E-02 0.10623485E+00 0.54462729E-02 + -0.64947754E-02 -0.79987012E-02 -0.12688860E-01 -0.63994944E-01 + -0.21709124E-01 -0.43794498E-01 0.31835441E-01 -0.27470827E-01 + -0.70910007E-02 0.91979466E-02 -0.11307490E+00 -0.22885030E-01 + -0.13536140E-01 0.18244114E-01 -0.90564966E-01 0.45806579E-02 + 0.17037231E-01 0.58723767E-02 -0.15382155E-01 -0.81376947E-03 + -0.10111790E-01 -0.13766922E-01 0.88332891E-02 -0.10245700E-01 + 0.28617419E-02 0.21085771E-01 0.25080673E-01 -0.33543896E-01 + 0.24984222E-01 -0.45952462E-01 -0.19729603E-01 0.25285017E-01 + 0.50980870E-01 -0.13921152E-01 -0.91980696E-02 0.12159725E-01 + -0.17162612E-03 -0.10890554E-01 0.40087324E-01 0.82861662E-01 + -0.52096926E-01 -0.26000412E-01 -0.59353504E-01 -0.32921359E-01 + 0.14816161E-01 -0.14302544E-01 -0.12839499E-01 0.24855362E-01 + -0.25451362E-01 0.88601559E-03 0.27688907E-01 -0.54229580E-01 + 0.40404368E-01 0.11072409E+00 0.53175785E-01 -0.27590901E-01 + 0.21070372E-01 0.30208081E-01 0.12800894E-01 0.44277795E-02 + -0.28233778E-01 0.11693152E-02 0.20908633E-01 -0.11176487E-01 + 0.30831585E+01 0.36423465E-02 0.95374249E-02 -0.43797642E-02 + -0.18526373E-02 0.12529453E-02 -0.21983865E-02 0.29568165E-03 + 0.14598125E-02 0.46192217E+00 0.57096803E-03 0.68593979E-01 + 0.65610945E-01 -0.10962676E-01 -0.29499028E-01 -0.40161174E-01 + 0.90372525E-02 0.10792329E-01 0.59456217E+00 -0.58928523E-01 + -0.10835457E+00 0.15614104E-01 0.38582683E-01 0.23725564E-01 + 0.37873339E-01 -0.45640215E-01 -0.25683858E-01 -0.58345467E+00 + -0.27269018E+00 -0.13519895E+00 -0.14928317E+00 0.25888458E-01 + 0.10878223E+00 0.17128436E+00 -0.17555455E-01 -0.41636076E-01 + -0.47605807E+00 0.18886378E+00 0.18850458E+00 0.15938819E-02 + -0.82812428E-01 -0.16693853E-01 -0.74811757E-01 0.13277733E+00 + 0.68222947E-01 0.97611368E-01 0.27176988E+00 0.73444307E-01 + 0.79687834E-01 -0.56013237E-02 -0.85544765E-01 -0.14200658E+00 + 0.61242133E-02 0.28192678E-01 -0.89809708E-01 -0.11081779E+00 + -0.60269386E-01 -0.10322292E-01 0.58627546E-01 -0.12565222E-01 + 0.40889375E-01 -0.88073611E-01 -0.47065701E-01 0.50374344E-02 + -0.12933058E+00 -0.36687320E+00 0.13463667E-02 -0.39664879E-02 + 0.91926754E-02 -0.25788704E-02 0.42144693E-02 0.51479936E-02 + 0.33288822E-01 0.38233617E+00 -0.14407396E+00 0.14271196E-01 + 0.11049573E-01 -0.93471631E-02 -0.82618259E-02 -0.22260591E-02 + -0.10530116E-02 -0.19392333E-02 0.48438215E+00 0.80777757E-01 + 0.84854364E-01 0.67027092E-01 0.96795224E-02 -0.77769160E-02 + -0.18757643E-01 -0.34126833E-02 0.10197647E-01 -0.10353539E-01 + 0.50584143E+00 -0.11593372E+00 -0.44522554E-01 0.55989955E-01 + -0.29334025E-01 0.31971797E-01 -0.19206980E-01 -0.19130749E+00 + 0.67898893E+00 0.13500413E+01 -0.41417088E-01 -0.41389436E-01 + -0.11354161E+00 0.12479116E+00 -0.15671545E+00 -0.16941839E+00 + -0.69109058E+00 -0.15827084E+01 0.77499503E+00 -0.54360230E-01 + -0.76154411E-01 0.21804530E-01 0.12542558E+00 0.97710431E-01 + 0.15336754E-01 0.46886271E+00 -0.25143080E+01 0.51227117E+00 + 0.20739184E+00 -0.24356622E+00 -0.41955861E+00 -0.88255465E-01 + -0.11599702E+00 -0.16374969E+00 0.60307807E+00 -0.83648962E+00 + -0.31556289E+01 0.47265428E+00 0.62394643E+00 -0.54705191E+00 + 0.20412102E+00 -0.19938686E+00 0.61526429E-01 0.66733706E+00 + -0.84022295E+00 -0.36363816E+00 -0.47948975E-01 0.91792941E-01 + 0.36664313E+00 -0.50559235E+00 0.43860999E+00 0.55686808E+00 + 0.20355389E+01 0.71406549E+00 -0.12435474E+01 0.21483092E+00 + -0.53310115E-01 -0.59347369E-01 -0.33315623E+00 -0.25482255E+00 + -0.24464151E-02 -0.78910601E+00 0.37705989E+01 -0.86769474E+00 + -0.12256937E+01 0.33561516E+00 0.13111095E+01 0.17731486E+00 + 0.52530521E+00 0.42007923E+00 -0.23053181E+01 0.16463203E+01 + 0.60083599E+01 -0.67770946E+00 -0.16302880E+01 0.13140202E+01 + -0.39495337E+00 0.35773265E+00 -0.20983079E-01 -0.48089164E+00 + 0.39525765E+00 -0.48140708E+00 0.16104811E+00 -0.11935354E-01 + -0.33358169E+00 0.43848920E+00 -0.33588856E+00 -0.45440465E+00 + -0.16640767E+01 0.70364141E+00 0.72135723E+00 -0.26408893E+00 + 0.13320313E+00 0.60090341E-01 0.20128183E+00 0.18900406E+00 + -0.34622148E-01 0.22574456E+00 -0.15068558E+01 0.90492386E+00 + 0.10402929E+01 -0.16921981E+00 -0.10404444E+01 -0.66429377E-01 + -0.44397837E+00 -0.24560232E+00 0.19569387E+01 -0.13762980E+01 + -0.33979952E+01 0.37711105E+00 0.11398211E+01 -0.88892829E+00 + 0.24327640E+00 -0.19420272E+00 -0.70902789E-02 -0.20724721E-01 + -0.35504639E-01 -0.82354783E-03 0.36352225E-01 -0.11773664E+00 + -0.11033535E-01 0.95688138E-03 -0.97791515E-02 -0.58923662E-02 + 0.11510790E-01 -0.53077191E-02 -0.21679616E-01 0.12743253E+00 + 0.43944500E-01 -0.99055991E-02 -0.21604956E-02 -0.19020387E-02 + 0.15028873E-02 0.34215365E-01 0.19715220E+00 0.12483913E+00 + -0.11022669E+00 -0.31943321E-01 0.11501913E-02 -0.29224208E-01 + -0.21727003E-01 -0.48656184E-01 -0.12077172E+00 0.44407237E-01 + -0.50276600E-01 0.74237466E-01 -0.13876396E+00 0.50061855E-01 + -0.89441332E-04 -0.19618968E-01 0.77808690E-02 0.11498177E+00 + 0.30138892E+00 0.84145181E-01 0.52387480E-01 -0.16962320E+00 + 0.13028959E-01 0.83306365E-01 0.12248266E+00 -0.22928389E-01 + -0.18141045E+00 -0.73630512E-01 0.12350224E-01 0.22824010E+00 + 0.88408589E-01 -0.56969862E-01 0.44197980E-01 0.42088985E-01 + -0.97412877E-01 -0.15992832E+00 -0.10725375E+01 -0.37769395E+00 + 0.20365877E+00 -0.10712838E+00 -0.52147180E-01 0.11348373E+00 + 0.12272291E+00 0.21829335E+00 0.90741438E+00 0.27918214E+00 + 0.21284492E+00 -0.16413611E+00 0.20872624E+00 -0.26607728E-01 + -0.13638991E+00 0.10097219E+00 -0.90743773E-01 -0.16678727E+00 + -0.49267459E+00 -0.25228685E+00 -0.20995040E+00 0.35344943E+00 + -0.42392891E-01 -0.14291541E+00 -0.18131788E+00 0.37399545E-01 + 0.22921517E+00 -0.11525337E-01 0.10362251E+00 -0.50349134E+00 + -0.24221870E+00 0.16809082E+00 -0.94889171E-01 -0.70770025E-01 + 0.13145506E+00 0.21850900E+00 0.14192160E+01 0.37012821E+00 + -0.17118193E-01 0.49541607E+00 0.17686056E+00 -0.86773753E-01 + -0.13545221E+00 -0.20977926E+00 -0.10618935E+01 -0.52702361E+00 + -0.14100182E+00 -0.16452020E+00 0.87792039E-01 -0.11034584E+00 + 0.22220004E+00 -0.97200029E-01 0.10797976E+00 -0.20363387E-01 + -0.53697564E-02 0.68575102E-02 0.68112351E-02 0.10468056E-01 + 0.19557826E-01 -0.29966215E-01 0.26615837E-02 -0.39665846E-03 + -0.27748954E-02 -0.12629429E-01 -0.34522377E-02 -0.19603441E-01 + -0.74741095E-02 0.36278367E-01 0.38917959E-01 0.62133335E-02 + 0.52181520E-02 0.47905691E-01 0.42130254E-01 0.10669808E-01 + -0.42659171E-01 -0.48366003E-02 -0.12414150E+00 0.83759092E-02 + 0.88774711E-02 -0.24281682E-02 0.65088272E-02 -0.18100817E-01 + -0.99380650E-02 -0.49212314E-02 0.54735458E-03 -0.14428277E-01 + -0.12441480E+00 -0.92068017E-02 -0.31998195E-03 0.24573997E-01 + -0.10163296E+00 0.31056127E-01 0.11012294E-01 -0.45570403E-01 + -0.14161533E+00 -0.41898370E-01 0.22085365E-02 -0.13771434E-01 + -0.37635207E-01 -0.79316162E-02 -0.12239705E-01 0.54416321E-01 + -0.23432044E-01 0.64405203E-01 -0.15231901E+00 -0.39993413E-02 + 0.10142058E-01 -0.18101417E-01 -0.84799826E-02 0.34984993E-03 + 0.89346394E-02 0.47468557E-03 0.28572041E-02 -0.35473127E-02 + 0.14134600E-01 -0.84402598E-02 -0.24490006E-01 0.59575289E-02 + -0.83975270E-02 -0.10783281E-01 0.10519187E-01 0.37295430E-02 + 0.78448243E-02 0.11155127E-01 0.20005921E-01 0.62797785E-01 + 0.11900892E-01 -0.27039558E-01 -0.19209160E-01 0.50548911E-02 + -0.49631184E-04 -0.94857486E-03 -0.61566602E-02 -0.72145343E-01 + 0.32358173E-01 -0.47734085E-01 0.26209855E-01 0.28988879E-01 + 0.74443226E-02 -0.39548054E-02 0.37050033E-02 0.76541901E-01 + -0.17525801E-02 0.52079745E-02 -0.92345104E-02 0.14466229E-02 + -0.19333604E-02 -0.76571703E-02 0.36316391E-02 -0.43371283E-02 + -0.36561654E-02 0.67056157E-02 0.16525773E-02 0.18420488E-01 + -0.17318184E-01 -0.72389054E-02 -0.36425989E-02 0.67126667E-02 + 0.62284837E-02 -0.25143016E-02 -0.54201256E-02 -0.49585290E-02 + 0.72677061E-02 0.95763803E-02 0.33443144E-02 0.68702064E-02 + 0.38347978E-02 -0.47801472E-02 -0.56901607E-02 0.15504234E-02 + -0.65200366E-02 -0.13484795E-01 -0.16534761E-01 -0.93058534E-02 + -0.70031774E-02 0.61732740E-03 0.68263332E-02 0.85278712E-02 + 0.13020537E-03 0.26661365E+01 -0.11117877E-02 0.34222321E-02 + -0.20794710E-02 0.24010155E-02 -0.40831417E-02 -0.47719330E-02 + -0.29675064E-02 -0.20296485E-02 0.41117507E+00 0.10291319E-01 + 0.47319625E-01 0.31215116E-01 0.78935325E-02 -0.25743436E-01 + -0.38405076E-01 0.98825060E-02 0.67149173E-02 0.74506962E+00 + 0.48187733E-01 -0.71195960E-01 0.25079396E-01 -0.21259580E-01 + 0.67766905E-01 0.48439432E-01 -0.66096783E-02 0.20697495E-01 + -0.39045447E+00 -0.26972127E+00 -0.70841610E-01 -0.73414035E-01 + -0.12673206E-01 0.81827521E-01 0.14244866E+00 -0.26457300E-01 + -0.33021890E-01 -0.66143787E+00 -0.15479177E+00 0.11289430E+00 + -0.54646455E-01 0.28970569E-01 -0.14369094E+00 -0.10134429E+00 + 0.25818259E-01 -0.48019908E-01 0.53726792E-01 0.25038397E+00 + 0.37336461E-01 0.40437397E-01 0.14270316E-01 -0.59865795E-01 + -0.11061208E+00 0.18749859E-01 0.24053220E-01 -0.40976707E-01 + 0.14224786E+00 -0.30323654E-01 0.30423731E-01 -0.44295676E-02 + 0.87912492E-01 0.58721393E-01 -0.13916853E-01 0.28919088E-01 + 0.74064289E-02 -0.27877736E+00 -0.28779900E+00 0.39281845E-02 + -0.14419554E-02 -0.11547091E-02 0.31535965E-02 -0.72778360E-03 + 0.34911863E-02 0.19075761E-01 0.28820461E+00 -0.28949183E+00 + 0.22228619E-01 0.63713086E-02 -0.21684170E-02 -0.55248658E-02 + -0.13032343E-02 0.91081448E-02 -0.81327856E-01 0.27268976E+00 + 0.13500667E+00 0.54546636E-01 0.37922066E-01 -0.32600060E-01 + -0.10949604E-01 0.19963372E-01 0.26835289E-01 0.87298229E-02 + -0.22350941E-01 0.29820484E+00 0.20726327E-01 -0.52162141E-01 + 0.49364645E-01 -0.39931946E-02 0.40589683E-01 -0.22952456E-02 + -0.10790926E+00 0.83676583E+00 0.63060778E+00 -0.68363369E-01 + -0.99837855E-02 -0.66430080E-02 -0.12207447E-01 -0.76347291E-01 + -0.15965883E+00 -0.35241809E+00 -0.65478712E+00 0.11052341E+01 + -0.12858538E+00 0.48155159E-01 0.30722397E-02 0.79846025E-01 + 0.70853233E-01 -0.98708272E-01 0.10073023E+01 -0.17845335E+01 + -0.80092162E+00 -0.46188459E-01 -0.14296985E+00 0.64327180E-01 + -0.35780568E-01 -0.21253629E+00 -0.38209793E+00 0.28986448E+00 + 0.20012248E+00 -0.21629677E+01 -0.28332931E+00 0.53812021E+00 + -0.36693877E+00 0.39688271E-01 -0.34019375E+00 -0.44371121E-01 + 0.21445230E+00 -0.62239212E+00 0.50726289E+00 0.12845743E+00 + -0.50081644E-01 0.10264900E-01 -0.10842125E-01 0.25324762E+00 + 0.47339383E+00 0.98013794E+00 -0.77179390E+00 -0.15949878E+01 + 0.26540798E+00 -0.23207286E+00 -0.71822703E-01 -0.27238446E+00 + -0.25130802E+00 0.26421374E+00 -0.21762607E+01 0.31028824E+01 + 0.20128746E+01 -0.15856741E+00 0.15671609E+00 -0.83239712E-02 + 0.12464355E+00 0.52468282E+00 0.88304269E+00 -0.13928699E+01 + -0.54484451E+00 0.43236532E+01 0.72512794E+00 -0.13013943E+01 + 0.80244911E+00 -0.15787379E+00 0.71791559E+00 0.87640762E-01 + -0.90506792E-01 0.29343450E+00 -0.64716011E+00 -0.85126460E-02 + 0.86700082E-01 -0.19545073E-01 0.22539424E-01 -0.21825898E+00 + -0.35119236E+00 -0.77049863E+00 0.13025292E+01 0.10195141E+01 + -0.17070550E+00 0.19100779E+00 0.10148967E+00 0.19473384E+00 + 0.22605895E+00 -0.21595259E+00 0.12541904E+01 -0.14151649E+01 + -0.76735258E+00 0.20479742E+00 -0.57303511E-01 -0.61315093E-01 + -0.67472458E-01 -0.35682023E+00 -0.55211598E+00 0.12503937E+01 + -0.19497246E+00 -0.25232332E+01 -0.48834428E+00 0.95700103E+00 + -0.50639713E+00 0.15538096E+00 -0.43736929E+00 -0.24403555E-02 + 0.58859177E-02 -0.32317564E-01 0.18789642E-02 0.81562936E-01 + -0.10188312E+00 -0.16970166E-02 0.10929942E-01 -0.80213174E-02 + -0.64339079E-02 0.12977692E-01 -0.20233873E-01 -0.87966025E-02 + 0.10940552E+00 0.84022999E-01 -0.43360288E-02 0.49938266E-02 + -0.24055215E-02 0.34415219E-02 0.13273510E-01 0.11690063E+00 + 0.11301345E+00 -0.53855576E-01 0.71545350E-02 0.26712853E-02 + -0.65927994E-02 -0.43166098E-02 -0.16314678E-01 -0.76610744E-01 + 0.31374007E-01 -0.51425260E-01 0.29726736E-01 -0.10468842E+00 + 0.35839195E-02 0.31228568E-01 -0.15449938E-02 0.10545071E-01 + 0.31877272E-01 0.21496820E+00 0.69084771E-01 -0.39078760E+00 + 0.10721207E+00 -0.50794110E-02 -0.28492520E-01 0.88592887E-01 + 0.17780274E-01 -0.14039850E+00 -0.13015021E-01 -0.97526431E-01 + -0.13987684E+00 -0.35487771E+00 -0.44129573E-01 0.44898987E-02 + 0.47013648E-01 -0.73569477E-01 -0.59302974E-01 -0.65177017E+00 + -0.36309087E+00 -0.23424511E+00 -0.13430981E+00 -0.32746036E-01 + 0.60699228E-01 0.33282299E-01 0.85893095E-01 0.49057350E+00 + 0.21044838E+00 0.23838104E+00 0.10888346E-01 -0.39147530E-01 + 0.10908669E+00 -0.18488687E+00 0.53481311E-01 -0.13602662E+00 + -0.10266942E+00 -0.34125087E+00 -0.22209170E+00 0.21323264E+00 + -0.73764920E-01 -0.42999983E-01 0.28910642E-01 -0.12368566E+00 + -0.24522580E-01 0.17222381E+00 -0.45565147E-01 0.26528454E+00 + 0.10084933E+00 0.18232720E+00 0.10636825E+00 -0.40960643E-01 + -0.71175873E-01 0.91745019E-01 0.48435759E-01 0.88375968E+00 + 0.36494935E+00 0.37522811E+00 0.38870537E+00 0.11076623E+00 + -0.87760687E-01 -0.44668164E-01 -0.12374670E+00 -0.56823587E+00 + -0.31550622E+00 -0.23784252E+00 -0.28017616E+00 0.20619076E+00 + -0.18672664E+00 0.23123896E+00 -0.66964269E-01 0.16415411E+00 + -0.73595010E-02 -0.61682202E-02 0.89407265E-02 0.50872304E-02 + 0.11877637E-01 0.35297506E-01 -0.39307773E-01 0.14423404E-02 + 0.44433936E-03 -0.74655705E-04 -0.16662818E-02 -0.57203509E-02 + -0.14137457E-01 -0.46855919E-02 0.45804936E-01 0.35633922E-01 + 0.30760854E-02 -0.23319600E-02 0.12941353E-01 0.44963382E-01 + 0.54211020E-02 -0.12041886E-01 -0.95001571E-02 -0.11241354E+00 + -0.19248098E-01 0.27269039E-02 -0.30035621E-02 0.59964396E-02 + -0.13195523E-02 -0.46101660E-02 0.39474592E-02 -0.64694285E-02 + 0.15680537E-01 -0.11271560E+00 -0.32720950E-02 -0.51417272E-02 + 0.48678979E-01 -0.73544323E-01 0.30441813E-01 0.96263885E-02 + -0.39520711E-01 -0.17735022E+00 -0.45016337E-01 0.51114708E-02 + -0.11839547E-01 -0.81728883E-02 -0.23926420E-01 0.60986388E-02 + 0.40335935E-01 -0.35920464E-02 0.41258313E-01 -0.14260805E+00 + -0.34774819E-02 0.18476749E-01 -0.10441232E-01 -0.13517551E-01 + 0.34676611E-02 -0.14249105E-02 0.14872111E-02 -0.32633503E-02 + -0.21993518E-02 0.17342657E-01 -0.17490787E-02 -0.15205594E-01 + 0.49438253E-02 -0.87333806E-02 -0.87372363E-02 0.14296354E-02 + 0.37051601E-03 0.55464767E-02 0.15304494E-03 0.21174494E-01 + 0.39107338E-01 0.80265291E-02 -0.22919754E-01 -0.76330574E-02 + -0.77880700E-02 -0.70988768E-04 0.10868076E-01 0.58998386E-02 + -0.64436138E-01 0.41344304E-01 -0.33050463E-01 0.35609435E-01 + 0.15621076E-01 0.52525136E-02 -0.76148473E-02 0.10637492E-01 + 0.63588083E-01 0.85605606E-02 0.37736224E-02 -0.12569183E-02 + -0.73067169E-03 -0.55869143E-02 -0.57651363E-02 -0.35552052E-03 + -0.52995868E-02 -0.63682459E-02 0.34755846E-02 0.33890575E-02 + 0.20352293E-01 -0.10258363E-01 -0.16343703E-02 -0.76323338E-02 + 0.61682425E-02 0.74977577E-02 -0.10669790E-02 -0.31994097E-02 + -0.56459676E-02 0.10195385E-01 0.95578730E-02 0.39921701E-02 + 0.18846112E-02 -0.28111460E-03 -0.14161777E-03 -0.63958354E-02 + -0.16010746E-03 0.83076097E-02 -0.32676377E-02 -0.81046112E-02 + -0.20230603E-02 -0.86054020E-02 0.55735968E-02 0.49315915E-02 + 0.46230294E-02 0.80582750E-03 diff --git a/src/main/resources/assets/org/orekit/nequick/ccir12.asc b/src/main/resources/assets/org/orekit/nequick/ccir12.asc new file mode 100644 index 0000000000000000000000000000000000000000..d06f159566a6a401004b8efda10f4f5468f8511e --- /dev/null +++ b/src/main/resources/assets/org/orekit/nequick/ccir12.asc @@ -0,0 +1,715 @@ + 0.58852777E+01 -0.96291304E-01 -0.24346260E-02 0.59140641E-01 + -0.63641071E-02 -0.26449412E-02 -0.31942982E-01 -0.10096008E-02 + 0.14919641E-01 -0.31421110E-02 -0.46499595E-02 -0.67822039E-02 + 0.15032778E-01 0.16458445E+01 -0.18067592E+00 0.30474961E+00 + -0.21605857E+00 -0.49374825E+00 -0.62353790E-01 -0.34158051E-01 + -0.12912387E+00 0.10613750E+00 0.29181529E-01 -0.23050727E-01 + 0.40541515E-01 -0.11224717E+00 0.10501717E+02 0.15741062E+01 + -0.14308901E+01 -0.48761311E+00 0.94652450E+00 -0.30434477E+00 + 0.10839930E+01 -0.10534966E+00 -0.51447511E+00 -0.91966093E-01 + 0.29239577E+00 0.20149441E-01 -0.39589244E+00 -0.23581301E+02 + 0.36677198E+01 -0.80632627E-01 0.43846779E+01 0.81138687E+01 + 0.20209017E+01 0.32430315E+01 0.27812090E+01 -0.52667058E+00 + 0.26251918E+00 0.75711906E+00 -0.62242740E+00 0.95958686E+00 + -0.55303650E+02 -0.63127480E+01 0.83682976E+01 -0.49186344E+01 + -0.69345770E+01 0.62089682E+01 -0.60723085E+01 0.13838013E+01 + 0.38213997E+01 -0.14319527E+00 -0.18019360E+01 0.50669366E+00 + 0.23809681E+01 0.59686279E+02 -0.30755753E+02 -0.12747594E+02 + -0.16911804E+02 -0.32807720E+02 -0.12712320E+02 -0.21192411E+02 + -0.12855251E+02 -0.71364403E-01 -0.14239577E+01 -0.39535253E+01 + 0.33811417E+01 -0.32125998E+01 0.87687027E+02 0.13251464E+02 + -0.15531276E+02 0.25012054E+02 0.18020905E+02 -0.21276217E+02 + 0.13908660E+02 -0.47290392E+01 -0.11022417E+02 0.16285952E+01 + 0.42395010E+01 -0.24118853E+01 -0.54046259E+01 -0.23993408E+02 + 0.89517502E+02 0.42279510E+02 0.22479492E+02 0.54392288E+02 + 0.30301132E+02 0.50255482E+02 0.23656769E+02 0.32564287E+01 + 0.28625791E+01 0.82307177E+01 -0.78404713E+01 0.53785992E+01 + -0.66045975E+02 -0.16009598E+02 0.10073885E+02 -0.35849014E+02 + -0.18812134E+02 0.25561323E+02 -0.14358001E+02 0.62677321E+01 + 0.13022477E+02 -0.24407015E+01 -0.45216808E+01 0.35019357E+01 + 0.52684317E+01 -0.57186352E+02 -0.10306863E+03 -0.47426025E+02 + -0.90657444E+01 -0.39237549E+02 -0.30380722E+02 -0.50804016E+02 + -0.19044098E+02 -0.49842196E+01 -0.29108648E+01 -0.74697680E+01 + 0.79306431E+01 -0.42882528E+01 0.20778378E+02 0.76332722E+01 + -0.15185137E+01 0.16232573E+02 0.66888428E+01 -0.10187650E+02 + 0.54846725E+01 -0.28345733E+01 -0.53408060E+01 0.10432415E+01 + 0.18286180E+01 -0.16316251E+01 -0.18638296E+01 0.42999359E+02 + 0.40907440E+02 0.17649246E+02 -0.67038953E+00 0.99691086E+01 + 0.10768867E+02 0.18582962E+02 0.55952597E+01 0.21914597E+01 + 0.12064838E+01 0.24707308E+01 -0.28870993E+01 0.12680759E+01 + 0.10030657E+00 0.17061023E+01 0.14686527E+01 0.67665517E-01 + 0.21641413E-01 0.18892784E-01 0.10023634E-01 -0.12924849E-01 + -0.28599402E-01 -0.64662802E-02 0.11706680E-01 -0.93984343E-02 + 0.17487409E-01 -0.23059969E+00 -0.14013823E+01 0.18092794E+01 + -0.91769516E-01 0.27110618E-01 0.17508436E-02 -0.26233229E-02 + 0.22305543E-01 0.89679919E-02 0.32947335E-01 0.14318242E-01 + 0.24811622E-01 -0.15941350E-02 -0.90277523E+00 0.23125534E+01 + 0.16092967E+01 -0.14453238E+00 -0.20665839E+00 0.51915783E+00 + 0.49450493E+00 -0.19916792E+00 0.18426664E+00 0.25234297E-01 + 0.38722821E-01 -0.42649657E-02 -0.26182026E-01 -0.56744325E+00 + 0.44611597E+00 0.11730175E+01 -0.47925121E+00 0.65121371E+00 + -0.45957804E-01 0.45501199E+00 0.25943023E+00 0.15283298E+00 + 0.99556029E-01 -0.21310529E-01 0.37541655E+00 -0.42286009E-01 + 0.20739956E+01 0.21575239E+02 0.34665108E+01 -0.20396402E+01 + 0.26834297E+01 0.28675489E-01 0.42604321E+00 0.28829843E+00 + 0.78976136E+00 0.17124642E-01 -0.31698339E-01 0.52003264E+00 + -0.44703302E+00 -0.10670328E+00 -0.74782786E+01 0.15177947E+02 + 0.26179514E+01 0.20770683E+01 -0.10762348E+01 -0.44632077E+00 + 0.60240370E+00 -0.58553094E+00 -0.10602016E+01 -0.88225491E-01 + -0.11664104E+01 -0.34999728E+00 0.25958815E+02 -0.27454483E+02 + -0.54103336E+01 0.15304747E+01 0.93126850E+01 -0.87061577E+01 + -0.62785416E+01 0.45617943E+01 -0.37337401E+01 -0.49913472E+00 + 0.41627297E+00 -0.20554547E+00 0.59320409E-01 0.14931066E+02 + -0.24322109E+02 -0.18978456E+02 0.66896200E+01 -0.11191241E+02 + 0.25101948E+01 -0.91349792E+01 -0.48819113E+01 -0.36994448E+01 + 0.46167007E+00 0.15925082E+01 -0.77618060E+01 -0.19510707E+01 + -0.18649813E+02 -0.15214693E+03 0.53326965E+02 0.57327814E+01 + -0.26576281E+02 -0.19274545E+00 0.15754473E+00 0.28831234E+01 + -0.84430447E+01 -0.36592317E+00 0.27528572E+01 -0.42047195E+01 + 0.30515223E+01 0.14867091E+02 -0.28944748E+02 -0.87118652E+02 + -0.89018812E+01 -0.27807983E+02 0.10147782E+02 0.44683981E+01 + -0.29643440E+01 0.63139424E+01 0.88454924E+01 -0.19191800E+01 + 0.97981710E+01 0.39162436E+01 -0.15608711E+03 0.10050726E+03 + 0.31733870E+02 0.67168102E+01 -0.41432083E+02 0.47361160E+02 + 0.28008730E+02 -0.28612595E+02 0.24360201E+02 0.73379183E+01 + -0.59432826E+01 0.31006489E+01 0.61421555E+00 -0.10763946E+03 + 0.12835527E+03 0.69382751E+02 -0.43361359E+02 0.56389217E+02 + -0.13272401E+02 0.51118820E+02 0.27908691E+02 0.29593458E+02 + -0.90813322E+01 -0.13741107E+02 0.45609161E+02 0.17076019E+02 + 0.49405960E+02 0.36311185E+03 -0.26420923E+03 0.41176748E+01 + 0.81804565E+02 -0.21720428E+01 -0.76053786E+01 -0.19046158E+02 + 0.28341923E+02 0.31033659E+01 -0.15050347E+02 0.12041607E+02 + -0.86199579E+01 -0.58249126E+02 0.21876076E+03 0.15515247E+03 + 0.21008593E+02 0.99964432E+02 -0.32595764E+02 -0.15503604E+02 + 0.48927860E+01 -0.20159592E+02 -0.26689789E+02 0.95943127E+01 + -0.29238539E+02 -0.13632692E+02 0.39192969E+03 -0.18186565E+03 + -0.12129234E+03 -0.57435070E+02 0.56430359E+02 -0.11213168E+03 + -0.54315079E+02 0.70347794E+02 -0.67493713E+02 -0.30095579E+02 + 0.18334641E+02 -0.94074984E+01 -0.31521273E+01 0.27239185E+03 + -0.28597070E+03 -0.12101059E+03 0.12336749E+03 -0.12470566E+03 + 0.26024109E+02 -0.12104428E+03 -0.59888287E+02 -0.85995743E+02 + 0.29719173E+02 0.37946320E+02 -0.11199421E+03 -0.46891850E+02 + -0.50657455E+02 -0.37947949E+03 0.38515723E+03 -0.23199800E+02 + -0.10095909E+03 0.50711761E+01 0.14311046E+02 0.33573044E+02 + -0.37079788E+02 -0.60635834E+01 0.25830381E+02 -0.14170277E+02 + 0.10315927E+02 0.79237274E+02 -0.35955151E+03 -0.10834154E+03 + -0.33607834E+02 -0.13744238E+03 0.42688854E+02 0.22823517E+02 + -0.24746647E+01 0.25041639E+02 0.33539780E+02 -0.14638426E+02 + 0.35408264E+02 0.18950533E+02 -0.44368753E+03 0.16978250E+03 + 0.19025841E+03 0.10587994E+03 -0.16499313E+02 0.12066158E+03 + 0.45466450E+02 -0.74402390E+02 0.81906021E+02 0.44979855E+02 + -0.21132381E+02 0.10045573E+02 0.49591427E+01 -0.27212524E+03 + 0.29296631E+03 0.10778041E+03 -0.14709779E+03 0.12872285E+03 + -0.21798767E+02 0.12947227E+03 0.51874660E+02 0.10150548E+03 + -0.36791386E+02 -0.41881744E+02 0.12185918E+03 0.52135880E+02 + 0.17340685E+02 0.14838106E+03 -0.17882974E+03 0.15429539E+02 + 0.43413681E+02 -0.26469879E+01 -0.74090319E+01 -0.18376602E+02 + 0.16659882E+02 0.33483200E+01 -0.13998299E+02 0.58607693E+01 + -0.43770046E+01 -0.36554958E+02 0.17909184E+03 0.23982544E+02 + 0.19982361E+02 0.63960342E+02 -0.19503311E+02 -0.11998042E+02 + -0.21119621E+00 -0.10841630E+02 -0.14879584E+02 0.71827703E+01 + -0.14873816E+02 -0.91093121E+01 0.18463350E+03 -0.63689987E+02 + -0.10000370E+03 -0.59487553E+02 -0.83337975E+01 -0.48281860E+02 + -0.12824591E+02 0.28396820E+02 -0.35691711E+02 -0.22169373E+02 + 0.81618071E+01 -0.34571950E+01 -0.25228517E+01 0.91842926E+02 + -0.11355025E+03 -0.39262447E+02 0.60758072E+02 -0.51565228E+02 + 0.64481277E+01 -0.51903687E+02 -0.14617392E+02 -0.41567413E+02 + 0.15849867E+02 0.16073256E+02 -0.48541443E+02 -0.20367508E+02 + 0.33230793E-01 -0.53760558E-02 -0.43271579E-01 -0.82253766E+00 + 0.10927147E+00 -0.62830341E-02 0.32827888E-01 0.20675361E-02 + 0.11074953E-01 0.14030250E-01 -0.93817338E-02 0.58153607E-02 + -0.90415105E-02 -0.72160554E-02 0.44827167E-01 0.94339013E-01 + -0.15674746E+00 -0.88599294E+00 0.21040725E-01 0.11656060E-01 + -0.43813027E-02 0.28248453E-02 0.18651810E-01 0.15717313E-01 + 0.10290854E-01 -0.74585453E-02 0.32696807E+00 0.55384904E+00 + -0.20601004E+00 0.22753012E+00 -0.38133556E+00 0.28293085E+00 + -0.22165217E+00 -0.19600344E+00 -0.30326170E+00 -0.53036105E-01 + -0.64323902E-01 -0.25258502E-01 0.27758271E-01 0.84868366E+00 + 0.71870285E+00 0.10409750E+00 -0.34669641E+00 0.68305485E-01 + 0.17950527E+00 0.17103159E+00 -0.16034061E+00 0.11909677E+00 + -0.90939045E-01 0.77516763E-02 0.50704512E-02 -0.44594161E-01 + 0.19773264E+01 -0.63938504E+00 0.54355240E+00 0.34600694E+01 + 0.14479407E+01 -0.65015870E+00 -0.12161551E+01 0.79876208E+00 + -0.60558915E+00 0.30918711E+00 0.64186800E+00 0.23445682E+00 + 0.25567997E+00 -0.23858166E+00 -0.21537187E+01 -0.21538348E+00 + 0.19827142E+00 0.62378964E+01 -0.14610815E+01 -0.79967242E+00 + 0.97321606E+00 0.28241432E+00 -0.71557987E+00 -0.40822547E-01 + -0.35631901E+00 -0.30096269E+00 0.27642244E+00 -0.35841660E+01 + 0.20953629E+01 0.21262350E+01 0.82936811E+01 -0.25825262E+01 + 0.12673424E+01 0.22965708E+01 0.32046335E+01 0.59451181E+00 + 0.29327148E+00 0.60926776E-01 -0.18911137E+00 -0.77316456E+01 + -0.86913090E+01 0.70329517E+00 0.29154104E+00 0.37658501E+01 + -0.15267448E+01 -0.19037495E+01 0.18705777E+01 -0.38128948E+00 + 0.16374692E+01 0.94264507E-01 -0.12111473E+01 0.54479063E+00 + -0.11841910E+02 0.12982109E+02 -0.46878176E+01 0.11409553E+02 + 0.11456190E+02 0.28962116E+01 0.70374966E+01 -0.53894968E+01 + 0.32251692E+01 -0.26807203E+01 -0.33563080E+01 -0.14099931E+01 + -0.16444159E+01 0.45781116E+01 0.22667101E+02 0.25675013E+01 + -0.19983488E+02 -0.88170254E+00 0.60731277E+01 0.46235952E+01 + -0.60956392E+01 -0.36376827E+01 0.50197077E+01 0.35221523E+00 + 0.22886686E+01 0.17762288E+01 -0.40170135E+01 0.62177038E+01 + -0.81950226E+01 -0.85565052E+01 -0.26114576E+02 0.52662058E+01 + -0.33671968E+01 -0.57750206E+01 -0.89394627E+01 -0.96039099E+00 + -0.44176665E+00 -0.38639605E+00 0.38240880E+00 0.16040436E+02 + 0.22648804E+02 -0.38160076E+01 0.32987604E+01 -0.11050161E+02 + 0.41704865E+01 0.42172184E+01 -0.41252756E+01 0.30131924E+00 + -0.52030263E+01 -0.83111125E+00 0.49567080E+01 -0.11959333E+01 + 0.23355225E+02 -0.34282349E+02 0.11538242E+02 -0.49848267E+02 + -0.40598740E+02 -0.39050007E+01 -0.14526565E+02 0.10634095E+02 + -0.49407692E+01 0.58253703E+01 0.57160435E+01 0.24022808E+01 + 0.39250431E+01 -0.89171886E+01 -0.57658356E+02 -0.79275866E+01 + 0.56511951E+02 -0.33630768E+02 -0.73403583E+01 -0.97860651E+01 + 0.12670937E+02 0.95948782E+01 -0.10938619E+02 -0.13207884E+01 + -0.39759085E+01 -0.31204891E+01 0.31317451E+01 -0.26248662E+01 + 0.75624285E+01 0.10054381E+02 0.23560148E+02 -0.29456441E+01 + 0.29910412E+01 0.40049524E+01 0.69776058E+01 0.23051453E+00 + 0.35383257E+00 0.45363480E+00 -0.17931674E+00 -0.85573311E+01 + -0.16594070E+02 0.34918072E+01 -0.66410446E+01 0.96621037E+01 + -0.31863918E+01 -0.24729843E+01 0.26573007E+01 0.11516501E+00 + 0.40185375E+01 0.10184889E+01 -0.46337080E+01 0.70501119E+00 + -0.15520617E+02 0.24251537E+02 -0.78417478E+01 0.39622375E+02 + 0.31915634E+02 0.84966397E+00 0.10047779E+02 -0.63451672E+01 + 0.19262160E+01 -0.35821593E+01 -0.31948893E+01 -0.13733149E+01 + -0.27612696E+01 0.26133039E+01 0.42539505E+02 0.70027022E+01 + -0.41647888E+02 0.34347591E+02 0.24487429E+01 0.63871117E+01 + -0.86457167E+01 -0.66765866E+01 0.73050594E+01 0.12362032E+01 + 0.21852674E+01 0.16885307E+01 -0.16071808E+00 0.14123529E-01 + -0.13230795E+00 0.34138903E-01 0.59729517E-01 -0.50168329E+00 + -0.57280517E+00 0.43802690E-01 -0.13694670E-01 0.17453469E-01 + 0.33055807E-02 0.23122185E-02 0.62880963E-02 0.53357899E-01 + -0.19458124E-01 0.69014668E-01 0.63686967E-02 0.54668400E-01 + 0.58147484E+00 -0.50669259E+00 -0.12543347E-01 0.45777820E-01 + -0.29289942E-01 -0.17757392E-01 -0.45786143E-03 -0.10528304E-01 + -0.54030935E-02 0.18703188E+00 -0.11604701E+00 -0.90121031E-01 + -0.24077912E+00 -0.58423525E+00 -0.78927040E-01 -0.25518278E-01 + 0.17570584E+00 0.64967513E-01 -0.28771311E-01 0.21496506E-01 + 0.58259081E-01 -0.21440379E+00 0.46478160E-01 0.59997041E-01 + -0.10545157E+00 0.87879360E-01 0.31408739E+00 -0.76883554E+00 + -0.22707506E+00 0.97065151E-01 -0.84792078E-01 -0.42242594E-02 + -0.36972158E-01 0.13577212E-01 0.13984450E+01 0.21562596E+00 + 0.81785202E+00 0.42129420E-01 -0.45740336E+00 0.19257107E+01 + 0.10962820E+01 -0.13253962E+00 0.64441621E-01 -0.76614618E-01 + 0.80381989E-01 0.60075343E-01 -0.42204820E-02 -0.88858902E+00 + 0.68705350E+00 -0.11165399E+00 -0.39081052E-02 -0.11788683E+01 + -0.96058542E+00 0.22603960E+01 0.79304039E-01 -0.20290291E+00 + 0.10524018E+00 0.22646756E+00 0.12000297E-01 0.20639112E-02 + -0.38604550E-01 -0.64558333E+00 0.15047131E+00 0.23604786E+00 + 0.51776189E+00 0.65631807E+00 -0.64743757E-01 0.23293778E+00 + -0.31635427E+00 -0.24677654E+00 0.73522210E-01 -0.12383265E+00 + -0.23125414E-01 0.63801259E+00 -0.17993660E+00 0.41443497E-01 + -0.30626380E+00 0.13222782E+00 -0.38505167E+00 0.11026430E+01 + 0.38552052E+00 -0.14338493E+00 0.16477841E+00 0.44638623E-01 + -0.27766572E-01 -0.14409492E-01 -0.16779747E+01 0.35500044E+00 + -0.75000978E+00 0.44501577E-01 0.16619509E+00 -0.29565685E+01 + -0.11524153E+01 0.10906345E+00 0.63353598E-01 0.74749351E-01 + -0.98273456E-01 -0.23684593E+00 0.99928252E-01 0.12862396E+01 + -0.10268888E+01 -0.34922292E-03 0.42514104E+00 0.18869686E+01 + 0.92553735E+00 -0.33864343E+01 -0.96434176E-01 0.88395417E-01 + -0.27669013E-01 -0.47842044E+00 -0.87917507E-01 -0.50919611E-01 + 0.67794323E-01 0.43764465E-01 -0.85234791E-02 0.55448759E-01 + -0.75007230E-02 0.26949579E-02 0.40005319E-01 0.17787796E+00 + -0.21966220E+00 0.13119746E-01 0.17033216E-01 0.48258598E-02 + 0.93731321E-02 0.41226272E-01 -0.45745872E-01 -0.44874884E-02 + -0.56989055E-01 0.66878623E-03 0.49436130E-02 -0.93553104E-02 + 0.20852254E+00 0.17780302E+00 -0.10008898E-01 0.40826781E-03 + -0.44579692E-02 -0.96555203E-02 0.32994185E-01 -0.50840318E-01 + -0.82209945E-01 -0.16789144E+00 -0.35853390E-01 -0.74349880E-01 + 0.36870696E-01 -0.67959309E-01 -0.23842363E+00 -0.75435221E-01 + 0.58410536E-01 0.19143851E-01 0.72812736E-01 -0.35581663E-01 + -0.75313270E-01 -0.37497941E-02 -0.53745732E-02 0.86594522E-01 + -0.85272789E-01 -0.75303733E-01 0.15578286E+00 -0.57227295E-01 + -0.19145610E-01 0.38526919E-01 -0.33226523E-02 -0.25027826E-01 + -0.24258217E-01 0.56879047E-01 -0.87987781E-01 -0.18437514E-01 + -0.26629930E-02 0.94258226E-02 0.11299052E-01 -0.10933794E-01 + 0.11623717E-02 0.17373119E+00 0.16964650E+00 -0.10166548E-01 + -0.62725316E-02 0.30380951E-01 -0.23155002E-01 -0.33405375E-01 + -0.44372205E-01 0.21909753E-01 -0.50504357E-02 -0.34750249E-01 + 0.32919925E-02 -0.52613996E-01 -0.17605484E+00 0.17251746E+00 + 0.14515134E-01 0.11617799E-01 0.42745028E-01 -0.67311865E-02 + -0.12199853E-01 -0.23588117E-01 0.42618997E-01 0.23207843E-01 + 0.16206969E-01 -0.71131135E-02 -0.15745319E-01 0.93277022E-02 + 0.54416270E-03 -0.92576861E-01 0.75096667E-01 -0.57170995E-01 + -0.11325012E-01 -0.45626003E-01 -0.51696181E-01 -0.54596663E-02 + 0.18047408E-02 -0.57304047E-01 0.28688207E-01 -0.29154113E-02 + -0.48920624E-02 -0.11745230E-02 -0.72187781E-01 -0.10533947E+00 + -0.46112321E-01 -0.93352422E-02 -0.77548146E-01 0.10806181E-01 + 0.16295979E-01 -0.91340803E-02 -0.37854970E-01 0.59323609E-02 + -0.70786555E-02 0.43499954E-02 -0.12444423E-01 -0.23848298E-02 + 0.11797853E-01 -0.69076233E-02 -0.14922633E-01 -0.16607359E-01 + -0.28959990E-01 0.37629217E-01 0.27335903E-02 -0.21362375E-01 + 0.14246407E-01 0.54619014E-02 0.60001425E-02 0.29482828E-01 + -0.15042796E-01 -0.14008234E-01 -0.39528869E-02 0.18516524E-02 + -0.39649025E-01 0.28208222E-01 -0.11501376E-01 -0.40830545E-01 + 0.14463946E-01 0.18475296E-02 -0.75901337E-02 0.18725945E-01 + 0.10570665E-01 -0.12890499E-04 0.23008054E-01 -0.51339734E-01 + 0.28110504E-01 -0.61789118E-02 0.81891306E-02 -0.29036775E-01 + 0.28971056E-01 0.64823441E-02 0.76583959E-02 0.27483685E-02 + -0.17355926E-01 0.15277425E-01 0.51793228E-02 -0.15141429E-01 + 0.88938065E+01 -0.15078265E-01 -0.25140064E-01 0.22020804E-01 + 0.25030831E-02 -0.20642309E-01 -0.30851012E-01 0.35875998E-02 + -0.87216613E-03 0.24480883E-01 0.15102468E-01 -0.19631796E-01 + 0.20391542E-01 0.61357880E+00 0.13776004E+00 -0.57032764E+00 + -0.28906604E-01 -0.35331151E+00 -0.21978436E+00 -0.14012581E+00 + 0.54715615E-01 0.14554125E+00 -0.24320902E-02 -0.52757952E-01 + -0.18868657E-01 -0.78913510E-01 0.26584976E+02 -0.91476983E+00 + -0.10767021E+01 0.83116639E+00 0.18041840E+01 -0.63989371E+00 + 0.51932621E+00 0.50343698E+00 -0.63642454E+00 -0.97818613E+00 + -0.29772168E+00 0.35066119E+00 -0.68079126E+00 0.31529951E+01 + -0.22581005E+01 0.95738220E+01 0.81222594E+00 0.97320185E+01 + 0.23350554E+01 0.16431693E+01 0.61718774E+00 -0.20582497E+01 + -0.12018208E-01 0.19452524E+01 -0.24020819E+00 0.93675071E+00 + -0.12845279E+03 0.76379833E+01 0.81046038E+01 -0.12054642E+02 + -0.15387235E+02 0.68140392E+01 -0.15058469E+01 -0.48598976E+01 + 0.49816790E+01 0.52011757E+01 0.22433045E+01 -0.60794914E+00 + 0.40673323E+01 -0.78451294E+02 -0.14396162E+02 -0.34657211E+02 + -0.25212047E+01 -0.49333847E+02 -0.11871572E+02 -0.53334064E+01 + -0.59590969E+01 0.88634005E+01 0.10821543E+01 -0.11399438E+02 + 0.47652416E+01 -0.32855814E+01 0.21243150E+03 -0.14004525E+02 + -0.17843674E+02 0.43910172E+02 0.43445210E+02 -0.19488859E+02 + 0.13466700E+01 0.12091711E+02 -0.13215184E+02 -0.10340990E+02 + -0.57268867E+01 -0.15506172E+01 -0.88107119E+01 0.24853136E+03 + 0.78768326E+02 0.34186371E+02 0.19544324E+01 0.10425355E+03 + 0.27955257E+02 0.85331831E+01 0.15262190E+02 -0.16240067E+02 + -0.35532908E+01 0.25211716E+02 -0.16891586E+02 0.51664085E+01 + -0.16578397E+03 0.30796995E+01 0.14645019E+02 -0.58538589E+02 + -0.48412689E+02 0.21371473E+02 -0.61169744E+00 -0.10880287E+02 + 0.14118614E+02 0.89713211E+01 0.56740236E+01 0.40566044E+01 + 0.80941868E+01 -0.28710034E+03 -0.11082729E+03 0.47830534E+01 + 0.12881907E+01 -0.99204010E+02 -0.28727613E+02 -0.78436446E+01 + -0.15181052E+02 0.13331136E+02 0.39052055E+01 -0.23992599E+02 + 0.21218475E+02 -0.36269217E+01 0.51397835E+02 0.44691315E+01 + -0.40350657E+01 0.25961411E+02 0.18408005E+02 -0.80434484E+01 + 0.32910937E+00 0.31243172E+01 -0.52550678E+01 -0.28733051E+01 + -0.18864108E+01 -0.22640371E+01 -0.26912498E+01 0.11311130E+03 + 0.48871567E+02 -0.13456261E+02 -0.14472980E+01 0.34871857E+02 + 0.10456634E+02 0.32485311E+01 0.52217913E+01 -0.40892696E+01 + -0.13860579E+01 0.83094473E+01 -0.88487806E+01 0.87602514E+00 + 0.69597125E-01 0.16769733E+01 0.15545816E+01 -0.55449344E-02 + 0.69705725E-01 0.23653561E-01 0.12845128E-01 0.86718909E-02 + -0.45932859E-01 0.31570096E-01 0.45554500E-01 -0.21642284E-01 + 0.12889817E-01 -0.21921284E+00 -0.16087894E+01 0.17624187E+01 + -0.13460630E+00 -0.59290789E-02 -0.83502904E-02 -0.34621306E-01 + 0.11610981E-01 -0.14968857E-01 -0.25111863E-01 0.17095665E-01 + -0.55068284E-02 -0.23103977E-01 -0.48869604E+00 0.17512939E+01 + 0.14671191E+01 -0.29812479E+00 0.43485564E+00 0.74070942E+00 + 0.47886825E+00 -0.15530139E-01 0.28587043E+00 -0.90406001E-01 + 0.12089236E+00 -0.10466528E+00 -0.22864468E+00 0.26475126E+00 + -0.10255442E+01 0.12023135E+01 -0.79612106E+00 -0.14503479E+00 + 0.48347481E-01 0.24352115E+00 0.33930928E+00 0.17734116E+00 + -0.29564551E+00 -0.23605781E-01 0.26259267E+00 -0.14518070E+00 + 0.32442265E+01 0.19304138E+02 -0.17855986E+02 0.15392789E+01 + 0.12891808E+01 -0.13034649E+01 0.78133225E-01 -0.28128737E+00 + 0.13791045E+01 -0.29651862E+00 -0.13774165E+01 0.90447134E+00 + -0.48520064E+00 -0.38545475E+01 0.17391617E+02 0.15856245E+02 + 0.32506828E+01 0.17471524E+01 0.54408711E+00 -0.87338269E-01 + 0.11546888E+01 -0.39241767E+00 0.82400143E-01 -0.41304436E+00 + -0.31734008E+00 -0.47280583E+00 0.15891955E+02 -0.71328111E+01 + -0.82937183E+01 -0.10363102E+01 -0.37894361E+01 -0.13196980E+02 + -0.97192097E+01 0.57880574E+00 -0.50687680E+01 0.15093237E+00 + -0.15454119E+01 0.22428341E+01 0.37367296E+01 -0.37251844E+01 + 0.30780756E+00 -0.38300512E+01 0.13541659E+02 -0.41292338E+01 + 0.24990661E+01 -0.36101904E+01 -0.68872385E+01 -0.33844929E+01 + 0.48587589E+01 0.16653652E+01 -0.54408011E+01 -0.14610329E+01 + -0.35525452E+02 -0.55185825E+02 0.18234506E+03 -0.17191864E+02 + -0.18231384E+02 0.10715060E+02 0.41820860E+00 0.49597664E+01 + -0.10105695E+02 0.44890794E+00 0.11448022E+02 -0.59232826E+01 + 0.21196375E+01 0.48971527E+02 -0.17984662E+03 -0.10086093E+02 + -0.28173094E+02 -0.18571411E+02 -0.34781046E+01 0.46446905E+00 + -0.91365309E+01 0.32334211E+01 0.29283720E+00 0.53791580E+01 + 0.33645313E+01 0.52979574E+01 -0.98831818E+02 0.35010025E+02 + 0.81809647E+02 0.42378189E+02 0.32127884E+02 0.71276749E+02 + 0.47292526E+02 -0.79754682E+01 0.26064089E+02 0.57404060E+01 + 0.62453079E+01 -0.13935454E+02 -0.23157148E+02 0.37681503E+02 + -0.22015532E+02 0.41568680E+02 -0.89377487E+02 0.34201309E+02 + -0.14441485E+02 0.12126778E+02 0.37069687E+02 0.21612261E+02 + -0.29737091E+02 -0.11194305E+02 0.31738434E+02 0.18420135E+02 + 0.11772128E+03 -0.16025236E+02 -0.54052002E+03 0.52717880E+02 + 0.66749588E+02 -0.31852322E+02 -0.27905672E+01 -0.18864182E+02 + 0.26960798E+02 0.23407800E+00 -0.36213848E+02 0.12973186E+02 + -0.41116314E+01 -0.15707159E+03 0.53367798E+03 -0.18824307E+03 + 0.96771606E+02 0.59688568E+02 0.96216154E+01 0.33605175E+01 + 0.27191832E+02 -0.63597374E+01 -0.57947135E+00 -0.20041166E+02 + -0.10695271E+02 -0.15405687E+02 0.25402480E+03 -0.12169589E+03 + -0.29696802E+03 -0.17765755E+03 -0.10246048E+03 -0.16805844E+03 + -0.91728355E+02 0.29707184E+02 -0.58331955E+02 -0.25739077E+02 + -0.14582020E+02 0.34748569E+02 0.59372269E+02 -0.14180336E+03 + 0.90961334E+02 -0.17497099E+03 0.24299307E+03 -0.93683578E+02 + 0.25937103E+02 -0.10940236E+02 -0.83610352E+02 -0.59765331E+02 + 0.78051529E+02 0.30359772E+02 -0.77565636E+02 -0.57330204E+02 + -0.15175063E+03 0.14136122E+03 0.67243634E+03 -0.63942413E+02 + -0.95142914E+02 0.37566513E+02 0.25746934E+01 0.25226885E+02 + -0.30201874E+02 0.11459293E+01 0.47971268E+02 -0.10312353E+02 + 0.43723440E+01 0.18913742E+03 -0.64964209E+03 0.40084793E+03 + -0.13516269E+03 -0.75677643E+02 -0.12140693E+02 -0.98627491E+01 + -0.34648930E+02 0.30085962E+01 -0.86283255E+00 0.28143951E+02 + 0.13283780E+02 0.17091980E+02 -0.29154053E+03 0.17865942E+03 + 0.44016385E+03 0.25832788E+03 0.12581498E+03 0.18186658E+03 + 0.75668427E+02 -0.42528137E+02 0.58712418E+02 0.38270676E+02 + 0.19351196E+02 -0.37923859E+02 -0.65868088E+02 0.21195496E+03 + -0.14264766E+03 0.25605197E+03 -0.27863403E+03 0.10939056E+03 + -0.14928992E+02 -0.43717604E+01 0.85104996E+02 0.72570892E+02 + -0.90291138E+02 -0.36729889E+02 0.84085495E+02 0.70076569E+02 + 0.67721512E+02 -0.90769203E+02 -0.30035889E+03 0.26721813E+02 + 0.47102432E+02 -0.15028220E+02 -0.20477100E+00 -0.11208222E+02 + 0.12107579E+02 -0.20266438E+01 -0.22364059E+02 0.21444893E+01 + -0.19921618E+01 -0.77146408E+02 0.27997412E+03 -0.22317944E+03 + 0.64471100E+02 0.32618530E+02 0.58598595E+01 0.59874973E+01 + 0.15801618E+02 0.81914449E+00 0.12750367E+01 -0.13325418E+02 + -0.56135445E+01 -0.63814483E+01 0.12182439E+03 -0.87194756E+02 + -0.22319072E+03 -0.12528762E+03 -0.51943050E+02 -0.73651093E+02 + -0.21513718E+02 0.20706057E+02 -0.21602539E+02 -0.18770325E+02 + -0.10114023E+02 0.15116210E+02 0.26225405E+02 -0.10590907E+03 + 0.75341293E+02 -0.12101202E+03 0.11209222E+03 -0.47404510E+02 + 0.42671257E+00 0.63914061E+01 -0.32075298E+02 -0.31445267E+02 + 0.37990162E+02 0.16272751E+02 -0.33418060E+02 -0.29758163E+02 + 0.24743641E-01 -0.24780037E+00 0.32477383E-01 -0.70758224E+00 + 0.77269542E+00 0.21704480E-01 0.73262006E-02 -0.54433793E-02 + -0.36484736E-02 0.15552453E-01 0.11511405E-01 0.95175020E-02 + -0.77193901E-02 -0.48369352E-01 -0.53220801E-01 0.27144585E-01 + -0.81413311E+00 -0.71973479E+00 -0.70226764E-04 -0.60768463E-02 + 0.16783386E-01 -0.50986302E-02 -0.15607438E-01 0.57154219E-02 + 0.16545273E-01 -0.27624261E-01 0.42223510E+00 -0.98611236E-01 + 0.50277317E+00 -0.16155949E+01 0.44995165E+00 0.60947478E+00 + -0.26007742E+00 -0.34951413E+00 -0.61507735E-01 -0.29398155E+00 + -0.57447206E-01 -0.17995073E-01 -0.72372675E-01 0.12762966E+01 + 0.26164579E+00 0.47269124E+00 -0.10257168E+01 -0.19976234E+01 + 0.18526942E+00 0.29332149E+00 -0.20163959E+00 0.15762202E+00 + -0.21016262E+00 -0.20759078E-01 0.75109005E-01 -0.30883992E+00 + 0.23981123E+01 0.29899120E+01 0.38449600E+01 -0.60386229E+01 + 0.53788691E+01 -0.93953526E+00 -0.15277853E+01 0.59264237E+00 + 0.45906553E+00 0.24649298E+00 -0.10305214E+00 0.32214963E+00 + 0.46169204E+00 0.16696634E+01 0.25706762E+00 0.28278368E+01 + -0.46109810E+01 -0.72205906E+01 0.34772471E+00 -0.62179738E+00 + -0.14041897E-01 0.11932107E+01 0.11926311E+00 0.61168361E-01 + -0.12217854E+00 0.74488103E-01 -0.42425365E+01 0.35861957E+00 + -0.69054890E+01 0.77307911E+01 0.14447308E+01 -0.51289425E+01 + 0.42940632E+00 0.37216489E+01 0.11370012E+01 0.24206257E+01 + -0.55311292E-01 0.61113585E-01 0.43589982E+00 -0.11186956E+02 + 0.14551839E+01 -0.46096087E+01 0.70924864E+01 0.82799072E+01 + 0.54562348E+00 -0.19091223E+01 0.63213462E+00 -0.97554809E+00 + 0.27594106E+01 0.64862490E-01 -0.13592871E+01 0.23405161E+01 + -0.17754061E+02 -0.32034550E+01 -0.41930237E+02 0.41079239E+02 + -0.18051514E+02 0.25384109E+01 0.90485382E+01 -0.25573387E+01 + -0.52479219E+01 -0.22733593E+01 0.16716584E+01 -0.19437447E+01 + -0.34734039E+01 -0.11303489E+02 0.17556185E+02 -0.22370165E+02 + 0.15778043E+02 0.52471004E+02 -0.31812954E+01 0.27775533E+01 + -0.23356986E+00 -0.10081250E+02 0.12472677E+01 -0.56565034E+00 + 0.53981125E-01 0.12582926E+00 0.12362516E+02 -0.29632864E+01 + 0.15124091E+02 -0.18801893E+02 -0.13831274E+02 0.12536343E+02 + 0.10004864E+01 -0.93945026E+01 -0.36175585E+01 -0.51194935E+01 + 0.14203262E+01 -0.24957808E-01 -0.76139683E+00 0.25606962E+02 + -0.82127504E+01 0.11993702E+02 -0.10493735E+02 -0.15479229E+02 + -0.24436884E+01 0.37523031E+01 0.70967054E+00 0.28187838E+01 + -0.75910473E+01 0.22493187E-01 0.46240826E+01 -0.53346510E+01 + 0.38124294E+02 -0.81857128E+01 0.10164819E+03 -0.78550079E+02 + 0.12163009E+02 0.46451297E-01 -0.17560549E+02 0.37782581E+01 + 0.13861210E+02 0.52900157E+01 -0.42033958E+01 0.37402475E+01 + 0.76729031E+01 0.27311661E+02 -0.54518936E+02 0.45628464E+02 + -0.14268176E+02 -0.10502531E+03 0.78711662E+01 -0.59193978E+01 + 0.21227322E+01 0.23136658E+02 -0.59244928E+01 0.94676512E+00 + 0.14095345E+01 0.77875793E-01 -0.12606328E+02 0.52987642E+01 + -0.10864912E+02 0.19476120E+02 0.18500380E+02 -0.88927746E+01 + -0.17200900E+01 0.67320638E+01 0.26062744E+01 0.29826610E+01 + -0.15832289E+01 -0.24634516E+00 0.30302536E+00 -0.16824036E+02 + 0.83268948E+01 -0.88709040E+01 0.17254645E+00 0.14521972E+02 + 0.19288082E+01 -0.16344374E+01 -0.16025695E+01 -0.28889387E+01 + 0.53860931E+01 0.74160635E-01 -0.41329079E+01 0.36643448E+01 + -0.25644224E+02 0.11694124E+02 -0.68230270E+02 0.47731461E+02 + 0.49299583E+01 -0.33478413E+01 0.10701688E+02 -0.15946397E+01 + -0.10438580E+02 -0.35907743E+01 0.26091223E+01 -0.24007339E+01 + -0.50249081E+01 -0.22422714E+02 0.41399734E+02 -0.25003632E+02 + 0.22523797E+00 0.66093277E+02 -0.54813418E+01 0.45410833E+01 + -0.25613079E+01 -0.15686406E+02 0.53152466E+01 -0.38827556E+00 + -0.17855605E+01 -0.56493258E+00 -0.25739521E+00 -0.51444802E-01 + -0.39007924E-01 0.43471344E-01 0.74577093E-01 -0.69018120E+00 + -0.77091730E+00 0.18789889E-01 -0.30679218E-01 0.34278046E-01 + 0.70777461E-02 0.17007650E-02 0.12116459E-01 0.30931160E-01 + 0.82304358E-01 0.23780584E-01 -0.61587133E-02 0.14854145E+00 + 0.73189169E+00 -0.68215251E+00 0.67674113E-02 0.98737925E-02 + -0.13763633E-01 -0.28919922E-01 -0.11603952E-02 0.28128896E-01 + 0.15583676E+00 -0.97631477E-02 -0.42719722E-01 0.55609424E-01 + -0.76401174E-01 -0.72838414E+00 -0.35610980E+00 0.81875384E-01 + 0.17080718E+00 -0.30333633E-01 -0.31908482E-01 0.57391774E-01 + 0.27769839E-01 -0.52173842E-01 0.24948266E+00 0.12350981E+00 + -0.15202741E+00 0.21870522E+00 0.53911513E+00 -0.62828910E+00 + -0.21726985E+00 -0.81490837E-02 -0.29228793E-01 -0.10110051E-01 + -0.15235766E-01 0.31288318E-01 0.17942055E+01 -0.47697359E+00 + -0.24683045E-01 -0.73759902E+00 -0.31411223E-01 0.23973179E+01 + 0.15254402E+01 0.46166000E+00 -0.19089139E+00 -0.40453416E+00 + 0.24325489E+00 0.47338761E-01 -0.12414199E+00 -0.10261517E+01 + 0.34687656E+00 -0.13719416E+00 -0.56109309E+00 -0.19106921E+01 + -0.12889605E+01 0.28899508E+01 0.31973648E+00 0.39896643E+00 + 0.91862559E-01 0.74149251E-01 0.17311738E+00 -0.22030468E+00 + 0.19139688E+00 -0.29637605E+00 -0.89744151E-01 0.34440777E-03 + 0.12633979E+00 0.17837121E+00 0.34260511E+00 -0.52784592E-01 + -0.35431856E+00 0.11950551E+00 0.18184207E+00 -0.15287530E+00 + -0.12142629E-02 0.38059655E+00 -0.70801198E+00 -0.47004503E+00 + 0.36706585E-01 -0.10262800E+00 -0.90509474E+00 -0.71891248E-01 + 0.41418591E+00 0.51909387E-02 0.73546290E-01 0.61649166E-01 + -0.10198504E+00 -0.11583489E+00 -0.30275669E+01 0.20220096E+01 + 0.34253961E+00 0.11947128E+01 -0.63510936E+00 -0.44640865E+01 + -0.18234404E+01 -0.84736711E+00 0.57081997E+00 0.75149286E+00 + -0.48013154E+00 -0.24022443E-01 0.20686176E+00 0.15877695E+01 + -0.71108866E+00 0.99898326E+00 0.13696938E+01 0.26519346E+01 + 0.18384991E+01 -0.53081532E+01 -0.50006747E+00 -0.82502490E+00 + -0.16206495E+00 -0.16357309E+00 -0.40980053E+00 0.16522449E+00 + -0.80586374E-02 0.50992239E-01 -0.46632241E-01 0.57858132E-01 + 0.29589588E-01 -0.29866926E-01 0.44593319E-01 0.20724244E+00 + -0.33956417E+00 0.48757140E-01 0.48252717E-02 0.75157727E-02 + 0.82745329E-02 0.56242995E-01 -0.98413788E-02 -0.85247047E-02 + -0.81652962E-02 0.10179363E-01 -0.32878403E-01 0.63941111E-02 + 0.30926961E+00 0.19301081E+00 0.51544080E-02 -0.95572881E-02 + 0.14922715E-01 -0.64172186E-02 0.19160559E-02 -0.24454542E-02 + -0.16382515E+00 -0.21728694E-01 0.84944487E-01 -0.70919216E-01 + 0.61331503E-01 -0.12808955E+00 -0.38097063E+00 -0.58370434E-01 + 0.67949355E-01 0.16139146E-01 0.56471497E-01 -0.82536153E-02 + -0.59724025E-01 0.79807997E-01 0.33527710E-01 0.72642326E-01 + -0.10801912E+00 -0.34897956E-02 0.36352581E+00 -0.57958066E-01 + -0.35505168E-01 0.12366364E-02 0.40800601E-01 -0.18490655E-01 + -0.46349317E-02 0.14545527E-01 -0.12120492E+00 0.26173398E-01 + 0.17550852E-02 -0.28536871E-01 0.22547290E-01 -0.36351152E-01 + -0.60174358E-02 0.28420085E+00 0.16398446E+00 -0.12288247E-01 + 0.14442493E-01 0.60371332E-01 0.38244717E-01 0.32651134E-01 + -0.77243626E-01 -0.35003494E-01 0.14984455E-01 0.15117689E-01 + -0.19099511E-01 -0.49697436E-01 -0.15599817E+00 0.25729859E+00 + 0.33024964E-02 -0.99182781E-03 0.71319520E-01 -0.75824678E-01 + 0.36760569E-01 -0.49347986E-01 0.15868418E-01 0.38285632E-01 + 0.23324167E-01 -0.39113779E-01 -0.30983375E-01 0.13260115E-01 + 0.37964739E-01 -0.74268162E-01 0.11632289E+00 -0.17346490E-01 + 0.15348020E-01 -0.14875908E-01 -0.52558880E-01 -0.71550250E-01 + -0.61885454E-02 -0.24182135E-01 0.37889171E-02 -0.25238233E-01 + -0.21548858E-02 0.12035027E-01 -0.14105135E+00 -0.92943013E-01 + -0.53878658E-01 -0.32849424E-01 -0.84194541E-01 0.31174354E-01 + -0.46395548E-02 0.12672111E-01 -0.28512161E-01 -0.13265371E-01 + -0.14615446E-01 0.36233847E-02 -0.12471825E-01 0.34783303E-02 + 0.54068267E-02 -0.35035559E-02 0.55042446E-01 0.23584511E-01 + -0.25574237E-01 0.69150329E-02 -0.15520843E-01 0.11701882E-01 + 0.12512359E-01 -0.23976656E-01 0.11502409E-02 0.91396831E-02 + 0.85549615E-02 -0.30781738E-01 0.11815183E-01 0.77101648E-01 + 0.19891473E-01 -0.14418865E-01 -0.48151333E-01 -0.46777278E-01 + 0.32677677E-01 0.10109332E-01 0.22690780E-03 0.29887984E-01 + -0.23127504E-01 0.21396788E-01 0.23422491E-01 -0.10521829E+00 + 0.46248101E-01 -0.85954962E-04 0.24128253E-01 0.10098126E-01 + 0.15944388E-01 0.24146425E-01 0.21453381E-01 0.39750673E-02 + -0.21658877E-01 0.59070811E-02 0.15631013E-01 -0.13315893E-01 + 0.30724745E+01 0.76932688E-02 0.10582104E-01 -0.58678426E-02 + 0.86863562E-02 0.23237041E-02 -0.16314250E-02 0.22063470E-02 + 0.30517471E-02 0.31540650E+00 -0.10881312E-01 0.51532704E-01 + 0.60170829E-01 0.84916502E-02 -0.18651346E-01 -0.24970859E-01 + 0.24080008E-01 -0.41201664E-03 0.70605505E+00 -0.14244080E+00 + -0.29646527E-01 -0.12706629E-01 -0.95824562E-02 -0.33969921E-02 + 0.17386444E-01 -0.78530967E-01 -0.11982952E-01 -0.42120481E+00 + -0.20498922E+00 -0.70140362E-01 -0.13760924E+00 -0.42224448E-01 + 0.85511677E-01 0.73424160E-01 -0.67239933E-01 0.15587627E-01 + -0.89627135E+00 0.41788441E+00 -0.50209496E-01 0.68723977E-01 + 0.28690731E-01 0.34792382E-01 -0.43728631E-01 0.22312868E+00 + 0.29185694E-01 0.65906465E-01 0.19188380E+00 0.25963048E-01 + 0.69747448E-01 0.35327673E-01 -0.73112071E-01 -0.53085875E-01 + 0.43332022E-01 -0.21014431E-01 0.26427591E+00 -0.27628177E+00 + 0.10059512E+00 -0.50584864E-01 -0.29864948E-01 -0.44461355E-01 + 0.33647086E-01 -0.14697210E+00 -0.26645195E-01 0.16860802E-01 + -0.18605262E+00 -0.38714591E+00 -0.19328044E-03 0.40252996E-03 + 0.75271167E-03 0.54476932E-02 0.79560243E-02 0.55059046E-03 + 0.20514991E-01 0.39720565E+00 -0.19083656E+00 -0.12558008E-01 + 0.56398660E-02 -0.12297943E-01 -0.14556027E-01 -0.61569135E-02 + 0.10029856E-01 0.10009073E-01 0.30681634E+00 0.34232044E+00 + 0.98892391E-01 0.69215238E-01 0.82950518E-02 -0.18969622E-01 + 0.55852693E-01 -0.31100797E-01 0.77327038E-02 -0.19496197E+00 + 0.34152463E+00 -0.10556674E+00 -0.18567832E-01 0.55548735E-03 + -0.31484786E-01 0.53078610E-01 0.60641043E-01 -0.30647779E+00 + 0.81640363E+00 0.18649312E+01 -0.98093085E-01 0.15951090E-01 + 0.17376810E-01 -0.39560460E-01 -0.20320363E+00 -0.74637711E-01 + -0.73014015E+00 -0.19144686E+01 0.81253171E+00 0.19620959E+00 + -0.52492671E-01 0.88517666E-01 0.17049301E+00 0.12281353E+00 + -0.20673338E+00 0.48533574E+00 -0.15024738E+01 -0.17705137E+01 + -0.81606110E-03 -0.53666764E+00 -0.37227353E+00 0.75344294E-02 + -0.40956616E+00 0.40251583E+00 0.89858896E+00 0.10686445E+01 + -0.16356421E+01 0.29005784E+00 0.37916356E+00 -0.13871599E-01 + 0.33012235E+00 -0.34580475E+00 -0.33433402E+00 0.10481234E+01 + -0.77934951E+00 -0.19115534E+01 0.12393999E+00 0.55828344E-01 + -0.70680201E-01 0.11313993E+00 0.58049357E+00 0.31924832E+00 + 0.22701540E+01 0.16197052E+01 -0.96915627E+00 -0.33665836E+00 + -0.14552671E+00 -0.21495458E+00 -0.52067465E+00 -0.32353055E+00 + 0.57284433E+00 -0.12134342E+01 0.19404649E+01 0.37635963E+01 + -0.62870938E+00 0.10511742E+01 0.11378069E+01 -0.29707568E-01 + 0.86152846E+00 -0.11126767E+01 -0.29988582E+01 -0.20589962E+01 + 0.24830685E+01 -0.22141758E-01 -0.89734024E+00 0.17300200E+00 + -0.71507877E+00 0.67783278E+00 0.56816953E+00 -0.79848272E+00 + 0.23965521E+00 0.80937093E+00 0.18386710E-01 -0.11181236E+00 + 0.65899372E-01 -0.10855013E+00 -0.42357111E+00 -0.30929345E+00 + -0.19041709E+01 -0.49399413E-01 0.43354791E+00 0.93478858E-01 + 0.24635492E+00 0.13785356E+00 0.41312331E+00 0.21510725E+00 + -0.42922240E+00 0.70117199E+00 -0.47726721E+00 -0.19355592E+01 + 0.54693979E+00 -0.56250000E+00 -0.84684217E+00 0.39356496E-01 + -0.54770637E+00 0.81452745E+00 0.24183493E+01 0.72689992E+00 + -0.10589314E+01 -0.23238602E+00 0.54398221E+00 -0.20291322E+00 + 0.43034214E+00 -0.41715693E+00 -0.29115313E+00 -0.90023018E-02 + -0.35391401E-01 -0.47154613E-02 0.19855537E-01 -0.11723322E+00 + -0.10261105E-01 0.60877353E-02 -0.11590884E-01 -0.67245774E-02 + 0.96493699E-02 -0.22004316E-01 -0.56211911E-02 0.11911504E+00 + 0.25769383E-01 -0.13206675E-01 -0.57847798E-03 -0.63171280E-02 + -0.14825935E-02 0.97160041E-01 0.14064240E+00 0.12654924E+00 + 0.90184137E-02 0.10824889E+00 0.98466850E-03 -0.39058451E-01 + 0.21360934E-01 -0.68189758E-02 -0.69581389E-01 0.23204977E-01 + -0.33772092E-01 -0.23201564E-01 -0.16431103E-01 0.35661332E-01 + -0.24787609E-01 -0.15851654E-01 0.41659132E-01 -0.95431058E-03 + 0.32939357E+00 0.11949617E+00 -0.34582306E-01 -0.11245042E+00 + 0.58247320E-01 0.44278201E-01 0.32697480E-01 0.79446398E-02 + -0.27802205E+00 0.99982262E-01 -0.18884204E+00 0.14989614E+00 + -0.30045878E-01 -0.12822230E-01 0.70558429E-01 0.67012231E-02 + -0.54927103E-01 -0.52163047E+00 -0.76617789E+00 -0.38275307E+00 + 0.93988597E-01 -0.80029541E+00 -0.46852093E-01 0.19828326E+00 + -0.19820786E+00 -0.20384856E-01 0.73622519E+00 0.23355690E+00 + 0.24254851E+00 0.40519953E+00 0.11749785E-01 -0.76143026E-01 + 0.65943301E-01 0.78227103E-01 -0.24041748E+00 -0.48859108E-01 + -0.53506446E+00 -0.33032447E+00 -0.10122341E+00 0.79143226E-01 + -0.14064234E+00 -0.84364593E-01 0.29860293E-02 -0.22253856E-01 + 0.39246804E+00 -0.24812710E+00 0.40944195E+00 -0.17673939E+00 + -0.78235686E-01 0.72178841E-01 -0.16227911E+00 0.10302574E-01 + 0.85755765E-01 0.64045298E+00 0.11233282E+01 0.36713567E+00 + -0.16331939E+00 0.12432957E+01 0.20128110E+00 -0.23927684E+00 + 0.27385575E+00 0.72312951E-01 -0.94199342E+00 -0.33690757E+00 + -0.17330156E+00 -0.81343490E+00 0.69725700E-01 0.41456182E-01 + -0.43618816E-03 -0.84605157E-01 0.24982798E+00 -0.22805035E-01 + -0.59726276E-02 0.38705333E-02 0.30002026E-02 0.19159811E-02 + 0.18420031E-01 -0.37724920E-01 0.35234529E-02 -0.43825810E-02 + -0.67331116E-02 -0.10876592E-01 -0.79003610E-02 -0.13564546E-01 + -0.40359162E-02 0.42511482E-01 0.42690057E-01 0.78176372E-02 + -0.44241245E-02 0.61757568E-01 0.38225949E-01 0.16911129E-01 + -0.45007329E-01 0.18286873E-01 -0.83427310E-01 0.43182421E-01 + 0.80693141E-02 -0.15373635E-02 0.29610461E-01 -0.18918576E-01 + -0.18943192E-01 -0.15242502E-01 -0.12218371E-01 -0.21460388E-01 + -0.98122180E-01 -0.44038400E-03 0.17151916E-01 0.91914497E-02 + -0.88108547E-01 0.29710809E-01 0.37761100E-01 -0.42912245E-01 + -0.14925539E+00 -0.86556077E-01 0.32728361E-02 -0.97887143E-02 + -0.35554547E-01 -0.30815806E-01 -0.29502630E-01 0.11506282E-01 + -0.96649565E-02 0.11226374E+00 -0.22778022E+00 0.95754513E-03 + 0.19735225E-01 -0.19949600E-01 -0.14575392E-01 0.80723651E-02 + 0.10257791E-01 0.98831533E-03 0.21253307E-02 0.44467158E-03 + 0.30331463E-01 -0.68215728E-02 -0.16475894E-01 0.66600144E-02 + -0.96909404E-02 -0.23368846E-02 0.10803204E-01 0.18352592E-03 + 0.94600804E-02 0.34825664E-02 0.29143482E-01 0.68724394E-01 + 0.15268686E-01 -0.34583663E-02 -0.26248896E-01 -0.41180067E-02 + -0.69923671E-02 0.78354776E-02 -0.15067246E-01 -0.50502360E-01 + 0.26632210E-01 -0.38117900E-01 0.12489505E-01 0.38269714E-01 + -0.23778919E-01 -0.45978688E-02 -0.10741331E-01 0.55188525E-01 + -0.19089220E-01 0.50233081E-02 -0.68038441E-02 0.13171526E-01 + -0.79407506E-02 -0.15828493E-02 0.69405888E-02 -0.26731647E-02 + -0.18833795E-02 0.10679698E-01 0.77929986E-02 0.25170865E-01 + -0.12785461E-01 -0.85407831E-02 -0.88489465E-02 0.11496037E-01 + -0.64758724E-03 -0.79743117E-02 -0.92306355E-03 -0.26192795E-03 + 0.58631450E-02 0.11213571E-01 0.88310167E-02 0.19518092E-02 + 0.98038791E-03 -0.22055171E-02 0.15052840E-02 0.49419217E-02 + -0.49593602E-02 -0.28198513E-02 -0.11953373E-01 -0.12248963E-01 + -0.72131343E-02 0.10401812E-01 -0.17990726E-02 -0.28054372E-02 + 0.18662047E-02 0.27312078E+01 -0.36635625E-03 0.16809824E-02 + 0.35598597E-02 0.75279060E-02 0.53007551E-03 0.95740211E-03 + -0.22847110E-02 -0.28182077E-03 0.21439908E+00 0.15668213E-01 + 0.39947953E-01 0.18864460E-01 0.18349141E-01 -0.73838937E-02 + -0.29964810E-01 0.16750785E-01 0.58596502E-02 0.98324704E+00 + -0.38888179E-01 -0.89483634E-02 -0.30634860E-01 -0.57423551E-01 + 0.13029806E-01 0.31853251E-01 -0.39872222E-01 0.66098981E-02 + -0.71482241E-01 -0.26525635E+00 -0.19658716E-01 -0.33415090E-01 + -0.51787484E-01 0.35274655E-01 0.85669100E-01 -0.48909988E-01 + -0.21501373E-01 -0.13290062E+01 0.17191924E+00 -0.47023814E-01 + 0.52566618E-01 0.13115124E+00 -0.12865188E-01 -0.10077954E+00 + 0.11846806E+00 0.88568963E-02 -0.13872872E+00 0.21173362E+00 + -0.49534775E-02 0.75430046E-02 0.31798296E-01 -0.33703379E-01 + -0.59091616E-01 0.35570819E-01 0.11184798E-01 0.40687090E+00 + -0.11250210E+00 0.64376891E-01 -0.24939284E-01 -0.85930586E-01 + -0.26775305E-02 0.72211981E-01 -0.74090540E-01 -0.24171598E-01 + 0.18235698E-01 -0.32615590E+00 -0.29267043E+00 0.70642792E-02 + 0.11300357E-02 -0.19541867E-02 0.65887645E-02 0.25641057E-03 + 0.29901182E-03 0.10992620E-01 0.29850316E+00 -0.32224560E+00 + -0.13626590E-01 -0.15000730E-02 -0.56463708E-02 -0.13415892E-01 + 0.31011614E-02 0.13834986E-01 -0.92273317E-02 0.24425700E+00 + 0.56881361E-01 0.36258154E-03 0.63643634E-01 -0.37808137E-03 + -0.32947320E-01 0.38247399E-01 0.19941088E-01 -0.57335585E-01 + 0.87612152E-01 0.25150669E+00 -0.19707844E-01 -0.44863455E-01 + 0.16167350E-01 -0.10398515E-01 0.50344795E-01 0.68640888E-01 + -0.23492482E+00 0.11852227E+01 0.87067664E+00 -0.62521160E-01 + 0.42712395E-02 0.31809576E-01 0.21999139E-01 -0.92716336E-01 + -0.10461420E+00 -0.57572049E+00 -0.91379118E+00 0.12106152E+01 + 0.14713532E+00 0.49721979E-01 0.31173522E-01 0.14988387E+00 + 0.74236989E-01 -0.24920762E+00 0.37146533E+00 -0.15066242E+01 + -0.33582765E+00 0.13240385E+00 -0.49595785E+00 -0.17519760E+00 + 0.14915366E-01 -0.31701410E+00 -0.11277884E+00 0.11722956E+01 + -0.33704275E+00 -0.16070231E+01 -0.73385954E-01 0.44775620E+00 + -0.89496613E-01 0.11555022E+00 -0.42885175E+00 -0.43839580E+00 + 0.61520100E+00 -0.11530800E+01 0.13902968E+00 0.11537028E+00 + -0.13625572E-01 -0.11211419E+00 -0.90618193E-01 0.34417909E+00 + 0.43181032E+00 0.19090472E+01 -0.30285782E+00 -0.14655379E+01 + -0.29066688E+00 -0.22451898E+00 -0.12008685E+00 -0.50865209E+00 + -0.31707209E+00 0.65367371E+00 -0.86626565E+00 0.25727079E+01 + 0.11919090E+01 -0.25942808E+00 0.98266917E+00 0.50214672E+00 + 0.11235261E+00 0.75492078E+00 0.13290590E+00 -0.35606389E+01 + 0.50929976E+00 0.30332546E+01 0.46690196E+00 -0.93843842E+00 + 0.33491963E+00 -0.23293012E+00 0.92977613E+00 0.81740063E+00 + -0.38443807E+00 0.52484918E+00 -0.42313319E+00 -0.31547219E-01 + -0.23082055E-01 0.98553777E-01 0.48045237E-01 -0.29371864E+00 + -0.38383645E+00 -0.16131201E+01 0.93166280E+00 0.74328411E+00 + 0.15688562E+00 0.21910544E+00 0.11658287E+00 0.44385308E+00 + 0.28195137E+00 -0.46593124E+00 0.43430272E+00 -0.11887656E+01 + -0.43771562E+00 0.14430624E+00 -0.56061119E+00 -0.36049956E+00 + -0.12475538E+00 -0.52396160E+00 -0.43358773E-01 0.28472090E+01 + -0.78438574E+00 -0.16446295E+01 -0.40643525E+00 0.59259111E+00 + -0.32095200E+00 0.95902145E-01 -0.59256899E+00 -0.44462156E+00 + 0.10362735E-02 -0.26521128E-01 0.73475327E-03 0.78305662E-01 + -0.87907068E-01 -0.87850466E-02 0.68914331E-02 -0.58439672E-02 + -0.10781296E-01 0.83343238E-02 -0.22290353E-01 0.50302148E-02 + 0.79541683E-01 0.76331973E-01 -0.69553149E-02 -0.10722161E-02 + -0.23844002E-02 -0.24587917E-03 0.73374867E-01 0.11703366E+00 + 0.75943530E-01 -0.60151588E-01 0.15490431E+00 0.13585862E-01 + -0.18192250E-01 0.11195568E-01 0.70080836E-02 -0.29040044E-01 + 0.32617461E-01 -0.60124032E-01 -0.11059098E+00 -0.43481726E-01 + 0.27728146E-01 0.21420592E-01 -0.26929742E-01 0.35609297E-01 + -0.37986711E-01 0.21261556E+00 0.65299809E-01 -0.47157770E+00 + 0.18923239E+00 0.89936629E-02 0.30793028E-02 0.21662015E-01 + 0.45056511E-01 -0.18105257E+00 0.52625746E-01 -0.21388228E+00 + -0.12751257E+00 -0.44269648E+00 -0.68748951E-01 0.48228782E-01 + 0.46695489E-01 -0.61157335E-01 -0.31314623E+00 -0.65667808E+00 + -0.16174650E+00 0.18607914E+00 -0.82700670E+00 -0.49523894E-01 + 0.11539984E+00 -0.11283566E+00 -0.42533651E-02 0.31864041E+00 + 0.13107453E+00 0.33589387E+00 0.72368962E+00 0.48834570E-01 + -0.47290842E-02 -0.90480983E-01 0.11117184E+00 -0.19858021E+00 + 0.16404297E-01 -0.35947224E+00 -0.23393698E+00 0.24125104E+00 + -0.40167993E+00 -0.59507191E-01 -0.12976586E-01 0.16296891E-02 + -0.64027667E-01 0.21480627E+00 -0.16956282E+00 0.42124185E+00 + 0.31029803E+00 0.24321970E+00 0.14924949E+00 -0.11708121E+00 + -0.62503338E-01 0.91057897E-01 0.29138744E+00 0.99653769E+00 + 0.11597234E+00 -0.23700123E+00 0.11012861E+01 0.13280974E+00 + -0.17497236E+00 0.16628049E+00 -0.11821240E-01 -0.40243316E+00 + -0.14012007E+00 -0.34927449E+00 -0.10288906E+01 -0.43111134E-01 + -0.44211321E-01 0.12559944E+00 -0.10422826E+00 0.19184583E+00 + -0.12884370E-01 -0.28929864E-02 0.62589156E-02 -0.43417551E-02 + 0.16956746E-02 0.30290779E-01 -0.54206152E-01 0.47972496E-02 + -0.54383767E-02 -0.18483960E-02 -0.49267076E-02 -0.35054756E-02 + -0.10494788E-02 -0.31706644E-03 0.53946707E-01 0.46015929E-01 + 0.77006114E-02 -0.74489890E-02 0.28184280E-01 0.48737310E-01 + 0.56083123E-02 -0.11658833E-01 0.10535412E-01 -0.77447712E-01 + 0.14809873E-01 -0.54364097E-02 0.26957260E-02 0.12003126E-01 + -0.48028259E-03 -0.13672523E-01 -0.10574404E-01 -0.94266161E-02 + -0.67775021E-02 -0.85156560E-01 0.66752793E-04 0.83940960E-02 + 0.25840158E-01 -0.82805574E-01 0.31506184E-01 0.41513223E-01 + -0.28803999E-01 -0.18279600E+00 -0.70030391E-01 0.43120943E-02 + -0.44541992E-03 -0.10199835E-01 -0.34188926E-01 -0.19336941E-01 + 0.11237562E-01 -0.19958831E-01 0.87408066E-01 -0.20651507E+00 + -0.62467046E-02 0.28983789E-01 -0.82333684E-02 -0.15517811E-01 + 0.84783211E-02 0.52443543E-03 0.13247509E-02 0.27244105E-02 + 0.20155314E-03 0.27045678E-01 0.32722114E-02 -0.98290928E-02 + 0.24848564E-02 -0.12258628E-01 0.43838951E-02 0.21730985E-02 + 0.14691027E-03 0.10895628E-01 -0.70574176E-02 0.27331525E-01 + 0.34686185E-01 0.11546563E-01 -0.10812424E-01 -0.11996834E-01 + -0.61492622E-02 -0.16286846E-01 0.90343282E-02 -0.16508182E-02 + -0.44392467E-01 0.24883408E-01 -0.41023172E-01 0.30125698E-01 + 0.19361742E-01 -0.84361620E-02 -0.86162388E-02 -0.12216836E-01 + 0.51103357E-01 -0.75027507E-04 0.11774481E-01 -0.37965029E-02 + 0.73318444E-02 -0.37572163E-02 -0.29526060E-02 0.51077679E-02 + -0.20714712E-02 -0.67285742E-02 0.69300090E-02 0.76303929E-02 + 0.18072840E-01 -0.92502236E-02 -0.23002876E-02 -0.76491982E-02 + 0.66094734E-02 0.57324432E-02 -0.36398082E-02 0.18937784E-02 + 0.12494958E-03 0.95274895E-02 0.79445876E-02 0.87751150E-02 + -0.22462979E-02 0.10836435E-02 0.13684510E-02 -0.88894577E-03 + 0.21372179E-02 -0.11187471E-02 -0.17962215E-02 -0.84776208E-02 + -0.32081937E-02 -0.57096705E-02 0.51954128E-02 0.20163734E-02 + -0.19013527E-02 0.13429526E-02 diff --git a/src/main/resources/assets/org/orekit/nequick/ccir13.asc b/src/main/resources/assets/org/orekit/nequick/ccir13.asc new file mode 100644 index 0000000000000000000000000000000000000000..14eb6798812484278fa40de6c6920bef97e930f7 --- /dev/null +++ b/src/main/resources/assets/org/orekit/nequick/ccir13.asc @@ -0,0 +1,715 @@ + 0.65998964E+01 -0.96180737E-01 -0.18148595E-01 0.64034283E-01 + -0.14069435E-01 -0.11540678E-01 0.66070855E-02 0.26406836E-01 + -0.39686033E-03 0.23210552E-01 -0.22450823E-02 -0.10104239E-01 + -0.12631580E-01 -0.42413343E-01 0.80642939E-01 0.27393836E+00 + -0.16345827E+00 -0.16899700E+00 -0.32240999E+00 0.70448697E-01 + -0.77763975E-01 -0.13244357E-01 0.30214986E-01 -0.13424671E+00 + -0.17871726E-01 0.15353709E-01 0.17452026E+02 0.14823141E+01 + -0.10489836E+01 -0.31613785E+00 0.14407471E+01 -0.17907828E+00 + 0.29510629E+00 -0.22444354E-01 0.21991578E+00 -0.10238972E+01 + 0.21552382E+00 0.43258828E+00 0.30413872E-01 -0.42824154E+01 + -0.43370705E+01 0.27843063E+01 0.32597790E+01 0.52011843E+01 + 0.38541880E+01 -0.19715508E+01 0.21992905E+01 0.23029690E+01 + -0.60228556E+00 0.22066259E+01 0.23972336E-01 -0.80908841E+00 + -0.11069538E+03 -0.47234507E+01 0.81807337E+01 -0.57918816E+01 + -0.15985529E+02 0.41825180E+01 0.31950969E+00 -0.15979003E+01 + -0.29805326E+00 0.65984235E+01 -0.15701970E+01 -0.28786163E+01 + -0.55098760E+00 0.53160343E+01 0.72372942E+01 -0.31718048E+02 + -0.84363060E+01 -0.20782211E+02 -0.15876793E+02 0.10275279E+02 + -0.12953022E+02 -0.18293261E+02 0.30118990E+01 -0.10225960E+02 + 0.10002424E+01 0.57159648E+01 0.22316840E+03 0.88046808E+01 + -0.19268265E+02 0.27535292E+02 0.49745651E+02 -0.14210364E+02 + -0.63509388E+01 0.59100389E+01 -0.75693417E+00 -0.15410736E+02 + 0.43323641E+01 0.69434185E+01 0.26285543E+01 0.29579544E+02 + 0.18237549E+02 0.82377548E+02 0.84427810E+00 0.30343168E+02 + 0.29563704E+02 -0.19898544E+02 0.30717590E+02 0.48212418E+02 + -0.59438214E+01 0.19914412E+02 -0.42029829E+01 -0.14977189E+02 + -0.20669724E+03 -0.11006776E+02 0.17986938E+02 -0.39454208E+02 + -0.59185928E+02 0.16635513E+02 0.11510051E+02 -0.69961233E+01 + 0.14310035E+01 0.15335246E+02 -0.50885744E+01 -0.70506630E+01 + -0.39190333E+01 -0.65092926E+02 -0.45056271E+02 -0.80958832E+02 + 0.13474419E+02 -0.17513613E+02 -0.25489258E+02 0.16221634E+02 + -0.31921722E+02 -0.51784847E+02 0.50485597E+01 -0.17261200E+02 + 0.55830841E+01 0.16545364E+02 0.74110519E+02 0.55856390E+01 + -0.58897910E+01 0.18034470E+02 0.23959211E+02 -0.63647890E+01 + -0.57852678E+01 0.26369388E+01 -0.59193826E+00 -0.55258875E+01 + 0.21282358E+01 0.25619020E+01 0.18311788E+01 0.34186600E+02 + 0.23974504E+02 0.27236193E+02 -0.89847784E+01 0.29195013E+01 + 0.82554817E+01 -0.46716986E+01 0.12058103E+02 0.19580338E+02 + -0.15368041E+01 0.54791770E+01 -0.23879938E+01 -0.65005140E+01 + -0.24007400E-01 0.21675978E+01 0.11725760E+01 0.50758086E-01 + 0.13093474E-01 -0.23201449E-01 0.38342893E-01 0.48389513E-01 + 0.63410662E-02 0.44442557E-01 0.19522280E-01 -0.27899284E-01 + -0.14491891E-02 -0.34519996E-01 -0.11496038E+01 0.21471727E+01 + -0.14192484E+00 0.68746626E-01 -0.33114925E-01 -0.61117642E-01 + 0.42638429E-01 0.90309940E-02 -0.28206117E-01 -0.93916431E-02 + -0.10890186E-01 0.86654350E-02 -0.62337194E-01 0.79887128E+00 + 0.91313583E+00 -0.18493378E+00 0.26627880E+00 0.28355408E+00 + 0.51949298E+00 0.11120750E+00 0.27354652E+00 -0.12354255E+00 + -0.27485762E-01 -0.33132059E-02 0.10892821E+00 -0.26281744E+00 + 0.44478521E+00 0.60648137E+00 -0.41248816E+00 0.25587833E+00 + -0.95881879E-01 -0.33539433E-01 0.57145733E+00 0.13682044E+00 + -0.25388563E+00 -0.10539192E+00 0.25895590E+00 -0.85921526E-01 + 0.27832451E+01 0.16864960E+02 0.40619507E+01 -0.20387974E+01 + 0.93537438E+00 0.16030453E+01 0.35865557E+00 -0.70939958E+00 + 0.63179672E+00 -0.16262045E+01 0.22060847E+00 0.10916176E+01 + -0.26890576E+00 -0.38157616E+01 -0.31960354E+01 0.17024628E+02 + 0.35198448E+01 0.14320096E+01 -0.42652923E+00 0.44432792E+00 + -0.12067032E+00 -0.51051909E+00 0.10688667E+01 0.34004807E+00 + 0.25413656E+00 -0.20112851E+00 0.69541912E+01 -0.18067734E+02 + 0.91149321E+01 0.38701576E+00 0.36137352E+01 -0.53189087E+01 + -0.11495462E+02 -0.10826283E+01 -0.27792189E+01 0.27802818E+01 + 0.12037230E+01 -0.14036683E+01 -0.12014112E+01 0.12424924E+02 + -0.22949509E+02 -0.12072405E+02 0.37552617E+01 -0.35413675E+01 + 0.57876978E+01 0.79935122E+00 -0.93507404E+01 -0.10703613E+01 + 0.37773590E+01 0.11066065E+01 -0.40062103E+01 -0.51845574E+00 + -0.17640093E+02 -0.10663565E+03 0.76676781E+02 0.15154501E+02 + -0.11779244E+02 -0.14249014E+02 -0.23536949E+01 0.50884314E+01 + -0.77559648E+01 0.10476252E+02 -0.28326015E+01 -0.80197411E+01 + 0.17742893E+01 0.41513287E+02 -0.97553864E+02 -0.95567101E+02 + -0.19530245E+02 -0.16382980E+02 0.50004244E+01 0.46859521E+00 + 0.59307051E+00 0.33864224E+01 -0.85503206E+01 -0.49351854E+01 + -0.36469865E+00 0.17972651E+01 -0.50485668E+02 0.11387515E+03 + -0.35196548E+02 0.13647219E+02 -0.18866573E+02 0.35348221E+02 + 0.61966625E+02 0.28466082E+01 0.12943145E+02 -0.17173037E+02 + -0.69480548E+01 0.11160711E+02 0.54356537E+01 -0.10127907E+03 + 0.11782327E+03 0.68567123E+02 -0.27491041E+02 0.10630719E+02 + -0.37230164E+02 -0.21067331E+01 0.51232285E+02 0.83989620E+01 + -0.19422346E+02 -0.21974297E+01 0.19062988E+02 0.78485546E+01 + 0.37536377E+02 0.21429556E+03 -0.35160007E+03 -0.42891769E+02 + 0.40961731E+02 0.44047211E+02 0.81962329E+00 -0.13827250E+02 + 0.28208023E+02 -0.26970642E+02 0.91622019E+01 0.21888948E+02 + -0.39068768E+01 -0.13467381E+03 0.43239697E+03 0.16293761E+03 + 0.55668140E+02 0.53183453E+02 -0.12969425E+02 -0.54627333E+01 + -0.22841864E+01 -0.78471823E+01 0.25674971E+02 0.17792437E+02 + -0.14446115E+01 -0.57079682E+01 0.15792363E+03 -0.30741357E+03 + 0.12066244E+02 -0.73300522E+02 0.21158735E+02 -0.10123547E+03 + -0.13733228E+03 0.33357602E-01 -0.29374786E+02 0.42309250E+02 + 0.14585931E+02 -0.30827667E+02 -0.13427902E+02 0.27333496E+03 + -0.24579082E+03 -0.17028870E+03 0.87392258E+02 -0.19682510E+02 + 0.87100418E+02 0.28480637E+01 -0.12049127E+03 -0.31395861E+02 + 0.46579376E+02 -0.16486950E+01 -0.39088516E+02 -0.23570740E+02 + -0.31926086E+02 -0.18912199E+03 0.49377737E+03 0.51254742E+02 + -0.55447201E+02 -0.56824295E+02 0.64984665E+01 0.14788384E+02 + -0.39874294E+02 0.31675291E+02 -0.11539884E+02 -0.25417494E+02 + 0.36541967E+01 0.17872554E+03 -0.60567114E+03 -0.10871115E+03 + -0.77059845E+02 -0.71071350E+02 0.11870969E+02 0.10181161E+02 + 0.38203001E+01 0.61157160E+01 -0.31524569E+02 -0.23383057E+02 + 0.37743139E+01 0.61833124E+01 -0.22133594E+03 0.37228467E+03 + 0.54766739E+02 0.12162727E+03 0.21483109E+01 0.12726327E+03 + 0.13672382E+03 -0.70452433E+01 0.30163025E+02 -0.44665482E+02 + -0.12745264E+02 0.35419662E+02 0.16225983E+02 -0.29494238E+03 + 0.23506216E+03 0.19200449E+03 -0.10832541E+03 0.29829514E+02 + -0.84662720E+02 -0.59570789E+01 0.12735706E+03 0.48301056E+02 + -0.52132954E+02 0.77952442E+01 0.36343369E+02 0.26745316E+02 + 0.91377707E+01 0.66141739E+02 -0.22206754E+03 -0.21895308E+02 + 0.25961348E+02 0.26107529E+02 -0.57225595E+01 -0.50952444E+01 + 0.19250319E+02 -0.14170376E+02 0.50944929E+01 0.10638087E+02 + -0.13205595E+01 -0.84391205E+02 0.27314233E+03 0.24791868E+02 + 0.38730946E+02 0.33692505E+02 -0.33924561E+01 -0.61104660E+01 + -0.23151674E+01 -0.92081571E+00 0.13415735E+02 0.10256060E+02 + -0.23337307E+01 -0.19138917E+01 0.11088846E+03 -0.16574036E+03 + -0.44082214E+02 -0.64954498E+02 -0.86842937E+01 -0.57481567E+02 + -0.51243748E+02 0.55801935E+01 -0.11060499E+02 0.16775253E+02 + 0.39023745E+01 -0.14520376E+02 -0.73669634E+01 0.11177200E+03 + -0.84463303E+02 -0.81101242E+02 0.44699478E+02 -0.19768433E+02 + 0.28911028E+02 0.49595222E+01 -0.49829727E+02 -0.25354980E+02 + 0.21757780E+02 -0.52241926E+01 -0.12592972E+02 -0.10411532E+02 + 0.30574525E-01 -0.31148717E-01 -0.33901516E-01 -0.87049472E+00 + 0.20368209E+00 -0.32607842E-01 -0.16634516E-01 0.27669176E-01 + 0.36947880E-01 0.47631599E-02 0.34091133E-02 -0.23116292E-01 + 0.21287637E-01 0.58895040E-01 0.15586517E-01 0.69088884E-01 + -0.21127129E+00 -0.80712032E+00 -0.14075823E-01 -0.17555032E-01 + -0.16835840E-01 0.10679643E-01 -0.12162153E-01 -0.73469686E-02 + -0.37808849E-02 0.10991143E-02 0.62006795E+00 0.13560390E+00 + 0.16468418E+00 0.99273920E-01 -0.26552624E+00 0.37287199E+00 + -0.35812032E+00 -0.19624997E-01 0.44019241E-01 -0.16461615E+00 + 0.20510986E-01 -0.11776924E+00 0.38004398E-01 0.10694619E+01 + 0.31023818E+00 0.14203928E+00 -0.43358117E-01 0.10166669E+00 + 0.41650143E+00 0.48760930E+00 -0.12005377E+00 0.97967386E-01 + -0.15563516E+00 -0.22586858E+00 0.49013637E-01 -0.20813970E-01 + 0.18206575E+01 -0.41084614E+00 0.27921238E+01 0.24209125E+01 + 0.16685303E+01 -0.28808552E+00 -0.90014279E+00 -0.50827682E+00 + -0.45300132E+00 -0.35001542E-01 0.36338080E-01 0.24220031E+00 + -0.31733364E+00 0.43253842E+00 -0.63174385E+00 0.50231868E+00 + -0.17871256E+01 0.42565956E+01 -0.41577768E+00 -0.12443371E-01 + 0.90635937E+00 -0.81871711E-02 0.12240941E+00 -0.58664852E+00 + 0.16192608E-01 -0.34534615E-01 -0.39647152E+01 0.33445108E+00 + -0.17875118E+01 0.35496013E+01 0.51491532E+01 -0.33950500E+01 + 0.13043871E+01 0.25871402E+00 0.68523347E-01 0.13834658E+01 + 0.79948354E+00 0.91803938E+00 -0.45803875E-01 -0.64467535E+01 + -0.20690763E+01 0.49838591E+00 -0.82725662E+00 0.50504017E+01 + -0.24308872E+01 -0.33799701E+01 0.58349323E+00 -0.12550087E+01 + 0.10462332E+01 0.23345356E+01 -0.70762026E+00 0.51471239E+00 + -0.15008720E+02 0.14641235E+02 -0.20451660E+02 0.19731979E+02 + 0.55634995E+01 0.25407569E+01 0.62443285E+01 0.28349655E+01 + 0.24219618E+01 -0.96738267E+00 -0.41830260E+00 -0.83132803E-01 + 0.83228946E+00 -0.45921926E+01 0.10040653E+02 -0.35055697E+01 + -0.40767612E+01 0.60929508E+01 0.75083411E+00 0.31848952E-01 + -0.46174974E+01 -0.34868580E+00 0.49051601E+00 0.39066937E+01 + 0.55248684E+00 -0.44293055E+00 0.63590775E+01 -0.54019079E+01 + 0.35216532E+01 -0.11525576E+02 -0.16511581E+02 0.75384364E+01 + -0.19127111E+01 -0.46861178E+00 -0.16359043E+01 -0.28776960E+01 + -0.27371662E+01 -0.23561430E+01 -0.15143436E+00 0.10229012E+02 + 0.11192627E+01 -0.24896040E+01 0.21574695E+01 -0.16082792E+02 + 0.50335703E+01 0.60995483E+01 0.46528444E-01 0.44228535E+01 + -0.24760294E+01 -0.58701072E+01 0.17978441E+01 -0.14681014E+01 + 0.34721951E+02 -0.42912167E+02 0.43504807E+02 -0.63420731E+02 + -0.24599470E+02 -0.63787670E+01 -0.11826031E+02 -0.60871477E+01 + -0.45813751E+01 0.32331924E+01 0.11356508E+01 -0.13086147E+01 + -0.20494528E+00 0.13705240E+02 -0.26223618E+02 0.63174248E+01 + 0.21032364E+02 -0.33421906E+02 0.69371122E+00 0.33373719E+00 + 0.82973967E+01 0.57793893E-02 -0.35463054E+01 -0.80484915E+01 + -0.15746632E+01 0.11740103E+01 -0.34624617E+01 0.80138206E+01 + -0.30727043E+01 0.99697714E+01 0.14296802E+02 -0.47378616E+01 + 0.91392750E+00 0.25849402E+00 0.23256731E+01 0.17453269E+01 + 0.22083223E+01 0.17524529E+01 0.13290423E+00 -0.44886570E+01 + 0.27600317E+01 0.26766872E+01 -0.16193962E+01 0.12873305E+02 + -0.35492830E+01 -0.32382326E+01 -0.82338870E+00 -0.40521240E+01 + 0.16536398E+01 0.42015963E+01 -0.11780930E+01 0.11460972E+01 + -0.24425173E+02 0.32594193E+02 -0.26974182E+02 0.44860214E+02 + 0.18794022E+02 0.41103077E+01 0.71137910E+01 0.43121300E+01 + 0.26971643E+01 -0.24290111E+01 -0.88320673E+00 0.13616093E+01 + -0.47190928E+00 -0.12868724E+02 0.17487791E+02 -0.35085895E+01 + -0.16604246E+02 0.24305555E+02 -0.93955791E+00 -0.42676288E+00 + -0.49368086E+01 0.68438691E+00 0.36197155E+01 0.52519341E+01 + 0.11007042E+01 -0.74931693E+00 -0.15135264E+00 -0.28601021E-02 + -0.89310586E-01 -0.33103663E-01 0.79293370E-01 -0.50901484E+00 + -0.82532126E+00 0.27812917E-01 0.20369738E-01 0.24551893E-01 + 0.18150743E-01 -0.15981855E-01 0.17871842E-01 0.47308989E-02 + -0.10820432E+00 0.30828550E-01 0.20033805E-01 0.29000899E-01 + 0.75493073E+00 -0.47701424E+00 0.32587878E-02 0.46372227E-01 + -0.10304346E-01 -0.20734092E-01 0.25965126E-01 -0.58355224E-02 + -0.30175501E-01 0.29149771E+00 -0.15922236E+00 -0.23880070E+00 + -0.31934559E+00 -0.21410790E+00 -0.14080048E+00 -0.13714212E+00 + 0.11907786E+00 0.39285962E-01 0.14231239E+00 0.47506593E-01 + -0.21241788E-01 -0.11470717E+00 0.12420136E+00 -0.40786356E-01 + -0.17982394E+00 0.13026784E+00 0.35654247E+00 -0.31161553E+00 + -0.22107504E+00 0.22054937E-01 -0.22563413E-01 -0.27322272E-01 + 0.78594647E-02 0.29850727E-01 0.91586936E+00 0.45026916E+00 + 0.85786003E+00 0.57185078E+00 -0.34676489E+00 0.13745327E+01 + 0.23583157E+01 -0.16617000E+00 -0.55329833E-01 -0.98012567E-01 + -0.80390751E-01 0.74126601E-01 -0.24377273E-01 -0.41545361E+00 + 0.12106429E+01 -0.93434161E+00 0.17056143E+00 -0.64522797E+00 + -0.23836489E+01 0.16357203E+01 -0.10281749E+00 -0.50418890E+00 + 0.29982608E-01 -0.91422498E-01 -0.29078585E+00 0.26920128E-02 + -0.32012028E+00 -0.33131802E+00 0.44400710E+00 0.35786447E+00 + 0.46332926E+00 0.39637893E+00 0.22233672E+00 0.42943183E+00 + -0.11153209E+00 -0.72281182E-01 -0.15658081E+00 -0.14401633E+00 + 0.95212579E-01 0.34326744E+00 -0.40543489E-01 0.20303135E+00 + -0.67969382E-01 -0.69856882E-01 -0.80425560E+00 0.52323300E+00 + 0.22219920E+00 0.59583046E-01 0.29945871E-01 0.43922313E-01 + -0.15566495E-01 -0.91002509E-02 -0.44131526E+00 -0.30327225E+00 + -0.92330807E+00 -0.77402669E+00 0.13792759E+00 -0.20475719E+01 + -0.27376490E+01 0.10802830E+00 -0.65257788E-01 0.78867793E-01 + 0.10399986E+00 0.14911513E-01 -0.53068720E-01 0.66848314E+00 + -0.16395501E+01 0.17826375E+01 -0.61707687E-01 0.10942956E+01 + 0.34093120E+01 -0.27390242E+01 0.11946614E+00 0.77287662E+00 + 0.62772572E-01 0.15083092E+00 0.45553598E+00 -0.37019581E-01 + 0.21583671E-01 0.64543169E-03 -0.51576737E-03 0.58179986E-01 + 0.27645396E-01 0.17042678E-01 0.23695774E-01 0.30250359E+00 + -0.15979145E+00 0.11132519E-01 0.16834153E-01 -0.14365312E-01 + -0.20031256E-02 0.37123352E-01 0.31039353E-01 -0.32179166E-01 + 0.90723857E-02 -0.57725225E-01 0.15170094E-01 0.13725638E-01 + 0.11982990E+00 0.30412436E+00 0.16133189E-01 0.21785470E-02 + 0.67538656E-02 -0.11140664E-01 -0.14433792E-02 0.11381990E+00 + -0.10765873E+00 -0.10239578E+00 -0.81107616E-01 -0.61356388E-01 + 0.38089097E-01 0.56286901E-01 0.27529797E-01 -0.90354145E-01 + 0.81266291E-01 0.29821135E-03 0.13847735E-01 0.18724556E+00 + 0.95570683E-02 -0.21760222E-01 0.13237506E+00 0.12431902E+00 + -0.66988230E-01 -0.10429621E+00 -0.10871854E-01 -0.82563143E-03 + -0.46499766E-01 -0.35336360E-01 0.74498015E-02 -0.50428431E-02 + -0.87155998E-01 0.10371951E-01 -0.10520716E+00 0.13535340E-01 + -0.12469282E-01 0.89040734E-02 0.31624246E-01 0.37560670E-02 + -0.11854895E-01 0.15747432E+00 0.22601800E+00 -0.16246822E-01 + -0.11745606E-01 0.61789233E-01 0.55235766E-01 -0.75306930E-02 + -0.16015358E-01 -0.22144975E-01 0.42483758E-01 -0.94584078E-02 + -0.29955332E-04 -0.20362385E-01 -0.22954024E+00 0.14123082E+00 + 0.11846970E-01 -0.48866947E-02 0.41830935E-01 -0.25836840E-01 + 0.33995997E-01 -0.30328433E-02 -0.43513551E-02 0.32394242E-01 + 0.24555245E-01 0.15828688E-01 -0.14602710E-01 0.79171918E-02 + -0.24579484E-02 -0.12720142E+00 0.61430715E-01 0.11831303E-01 + 0.48629563E-01 -0.36074687E-01 0.10915473E-01 0.65989308E-02 + 0.81955455E-02 -0.26336169E-01 -0.81899911E-02 -0.11951328E-01 + -0.18219598E-01 -0.14673568E-01 -0.55252790E-01 -0.12856483E+00 + -0.18628046E-01 -0.58445823E-02 -0.82438052E-01 0.24269115E-01 + 0.24777472E-01 -0.10445635E-01 -0.56395717E-02 0.88527240E-02 + -0.72764158E-02 0.19107532E-03 -0.24804154E-01 0.88188238E-02 + 0.33777922E-02 0.22041785E-01 0.75239122E-01 0.32701150E-01 + -0.36235764E-02 0.28052097E-01 0.17236879E-01 0.44026834E-03 + -0.37383430E-01 0.11369156E-02 0.21209640E-02 0.54265261E-02 + 0.13008385E-02 0.85698180E-02 0.10458429E-01 -0.10118044E-02 + -0.77243917E-01 0.30200144E-04 0.16539749E-01 -0.37585136E-02 + 0.45206279E-01 -0.19975778E-01 0.64657144E-02 0.45526288E-02 + -0.13365079E-01 0.17035088E-01 0.60681738E-02 -0.31197893E-01 + 0.27110072E-01 -0.81724226E-02 0.53124391E-01 -0.37347761E-03 + -0.60616839E-02 0.15380550E-01 0.24982354E-01 0.43096021E-02 + -0.35201445E-01 -0.23587817E-01 -0.47319382E-02 0.29201475E-02 + 0.93594637E+01 0.11758082E-01 0.84277689E-01 0.73569536E-01 + 0.11903163E-01 -0.44155391E-02 -0.15138904E-01 0.74017155E-02 + -0.15588633E-01 0.36506955E-01 -0.14251898E-02 -0.65558036E-02 + -0.18775852E-02 0.88674414E+00 0.51994503E-01 0.62100887E-02 + -0.30662936E+00 -0.13489079E+00 -0.16742069E+00 -0.27921742E+00 + -0.73416770E-01 -0.51260430E-01 0.34743931E-01 -0.64074218E-01 + -0.14990612E-01 -0.33514559E-01 0.29466921E+02 -0.10430384E+01 + -0.17538365E+01 0.64629501E+00 0.15527000E+01 -0.81919438E+00 + 0.24933694E+00 0.21972422E+00 0.14215916E+00 -0.14595737E+01 + 0.24961293E+00 0.30417073E+00 -0.55456985E-01 -0.67446027E+01 + 0.40613860E+00 0.46058159E+01 0.29142275E+01 0.43435965E+01 + 0.19936314E+01 0.27405975E+01 0.19893138E+01 0.26587334E+01 + -0.36289036E+00 0.87958097E+00 0.43432504E+00 0.45760855E+00 + -0.14369508E+03 0.82375011E+01 0.86440678E+01 -0.11147150E+02 + -0.15416178E+02 0.78732023E+01 0.98172742E+00 -0.10455227E+01 + 0.79332030E+00 0.88577414E+01 -0.20928278E+01 -0.17485448E+01 + -0.37013817E+00 -0.38804271E+01 -0.24045441E+02 -0.22236849E+02 + -0.39119642E+01 -0.14422158E+02 -0.11314327E+02 -0.11605090E+02 + -0.11023641E+02 -0.19990582E+02 0.18404474E+01 -0.36433990E+01 + -0.19584159E+01 -0.16701307E+01 0.24726463E+03 -0.13912272E+02 + -0.16638885E+02 0.39193115E+02 0.45437637E+02 -0.20975449E+02 + -0.71870813E+01 0.10358953E+01 -0.41288271E+01 -0.20344755E+02 + 0.61743193E+01 0.37249968E+01 0.23654852E+01 0.73438400E+02 + 0.85878952E+02 0.28821285E+02 -0.12087472E+02 0.15061756E+02 + 0.27009081E+02 0.25284409E+02 0.25017273E+02 0.52237438E+02 + -0.39412920E+01 0.60525675E+01 0.32629385E+01 0.20258255E+01 + -0.20673763E+03 0.37566128E+01 0.14237962E+02 -0.50470261E+02 + -0.52279781E+02 0.21282148E+02 0.11163843E+02 0.52002543E+00 + 0.55029087E+01 0.20240616E+02 -0.74278593E+01 -0.33429353E+01 + -0.35941296E+01 -0.11962259E+03 -0.10679832E+03 -0.54719858E+01 + 0.29441711E+02 -0.20143700E+01 -0.27501463E+02 -0.26564102E+02 + -0.25437057E+02 -0.56287430E+02 0.34835873E+01 -0.41210537E+01 + -0.22583301E+01 -0.41311580E+00 0.69616791E+02 0.29591660E+01 + -0.46051245E+01 0.21710464E+02 0.20603971E+02 -0.72812705E+01 + -0.51570253E+01 -0.75040770E+00 -0.23034897E+01 -0.73399339E+01 + 0.31145620E+01 0.10590287E+01 0.16675491E+01 0.55920959E+02 + 0.44685558E+02 -0.57169743E+01 -0.16177475E+02 -0.28279171E+01 + 0.99622288E+01 0.10504270E+02 0.95728416E+01 0.21457169E+02 + -0.10309287E+01 0.88172019E+00 0.53643727E+00 -0.38652465E+00 + -0.91051519E-01 0.16604548E+01 0.15699625E+01 0.76715767E-01 + 0.43537371E-01 -0.13598571E-01 0.49196348E-01 0.54983902E-02 + -0.43234859E-01 0.35610508E-01 0.33476464E-01 -0.23877522E-01 + -0.35067953E-03 0.12912869E+00 -0.15785017E+01 0.15362043E+01 + -0.14700162E+00 0.59193391E-01 -0.35832047E-01 -0.21853300E-01 + 0.66302009E-02 0.16508464E-01 0.10124203E-01 0.11756689E-01 + -0.16161021E-01 -0.59979521E-02 -0.84079021E+00 0.12545851E+01 + -0.53319615E+00 -0.38466424E+00 0.71295905E+00 0.44927460E+00 + 0.46575683E+00 0.96385419E-01 0.24827370E+00 -0.49310956E-01 + -0.60446393E-01 -0.82794249E-01 0.53030346E-01 0.93256640E+00 + -0.20340858E+00 0.24310620E+00 -0.10172791E+00 0.75127989E+00 + 0.97861581E-01 0.30854338E+00 0.39208812E+00 0.25966078E-01 + -0.73293746E-01 -0.10588093E+00 0.91211319E-01 -0.16803260E+00 + 0.31397121E+01 0.17180099E+02 -0.13800440E+02 0.70740998E-01 + 0.46341306E+00 0.14315277E+00 -0.44296425E-01 0.59252042E+00 + 0.15348605E+01 -0.11630144E+01 -0.22830708E+00 0.94050133E+00 + -0.27207708E+00 -0.83226337E+01 0.16027708E+02 0.18227188E+02 + 0.24127636E+01 0.16124907E+01 0.64143932E+00 -0.48962837E+00 + 0.14949484E+01 -0.68322611E+00 -0.83393395E+00 -0.21246541E+00 + 0.36369675E+00 0.15471222E-01 0.25553757E+02 -0.20131187E+01 + 0.26365784E+02 -0.37747600E+01 -0.64699764E+01 -0.78558402E+01 + -0.10889876E+02 -0.23848505E+00 -0.30194919E+01 0.15077209E+01 + 0.17867328E+01 0.61363947E+00 -0.83897746E+00 -0.97228460E+01 + -0.83611345E+01 0.63290434E+01 0.16351891E+01 -0.20032822E+02 + 0.44843369E+01 -0.30204687E+01 -0.67688689E+01 0.79144502E+00 + 0.25467318E+00 0.99470073E+00 -0.17565976E+01 0.14626292E+01 + -0.19355896E+02 -0.47454224E+02 0.12098094E+03 -0.89022665E+01 + -0.42745752E+01 -0.45515871E+01 0.30617991E-01 -0.31281147E+01 + -0.12787306E+02 0.67629743E+01 0.81136113E+00 -0.72240005E+01 + 0.21611481E+01 0.77719879E+02 -0.15284087E+03 -0.28094070E+02 + -0.12935535E+02 -0.18593325E+02 -0.32531595E+01 0.55940328E+01 + -0.11318360E+02 0.32409828E+01 0.75526605E+01 0.48537755E+00 + -0.15223312E+01 0.88688982E+00 -0.16509647E+03 -0.13600341E+02 + -0.14347475E+03 0.67285431E+02 0.29329422E+02 0.45942947E+02 + 0.55822556E+02 -0.64459357E+01 0.13185073E+02 -0.11480048E+02 + -0.14453206E+02 -0.30418861E+00 0.47256918E+01 0.55850414E+02 + 0.47293289E+02 -0.38787140E+02 -0.14584156E+02 0.12430083E+03 + -0.31622999E+02 0.13420869E+02 0.35762142E+02 -0.36125880E+00 + -0.15479679E+01 -0.12744303E+01 0.86030378E+01 -0.44953403E+01 + 0.38700027E+02 -0.28222197E+02 -0.30419238E+03 0.39386948E+02 + 0.15715429E+02 0.20906570E+02 -0.27541666E+01 0.65622759E+01 + 0.40180481E+02 -0.16013824E+02 -0.15492725E+01 0.20418943E+02 + -0.60262117E+01 -0.24083034E+03 0.41435205E+03 -0.13463225E+03 + 0.38008820E+02 0.62823849E+02 0.78923759E+01 -0.17364426E+02 + 0.29752790E+02 -0.36583557E+01 -0.22033188E+02 -0.86091959E+00 + 0.23167665E+01 -0.40712490E+01 0.43789868E+03 0.37758240E+02 + 0.30222437E+03 -0.25211703E+03 -0.68283478E+02 -0.12247943E+03 + -0.11544856E+03 0.29691114E+02 -0.26862549E+02 0.32532578E+02 + 0.40526031E+02 -0.55368466E+01 -0.12097772E+02 -0.16987952E+03 + -0.98175888E+02 0.93504868E+02 0.44424988E+02 -0.31534619E+03 + 0.75678291E+02 -0.27929535E+02 -0.75439178E+02 -0.14984092E+02 + 0.86548948E+01 -0.38562279E+01 -0.19092194E+02 0.82323360E+01 + -0.28264296E+02 0.16086137E+03 0.33062646E+03 -0.60156815E+02 + -0.25561417E+02 -0.33909607E+02 0.69856234E+01 -0.67728310E+01 + -0.52560555E+02 0.17889969E+02 0.16138610E+01 -0.24223925E+02 + 0.70134721E+01 0.30368723E+03 -0.46959616E+03 0.33666504E+03 + -0.55255215E+02 -0.86959839E+02 -0.90647650E+01 0.22722626E+02 + -0.31628494E+02 -0.20313890E+01 0.26141890E+02 0.15387295E+01 + -0.10764122E+01 0.55649920E+01 -0.51269458E+03 -0.24774506E+02 + -0.26924045E+03 0.35456689E+03 0.72959488E+02 0.14845412E+03 + 0.10644101E+03 -0.44661758E+02 0.25646072E+02 -0.38323624E+02 + -0.45829041E+02 0.11802900E+02 0.13949015E+02 0.23760628E+03 + 0.85215302E+02 -0.10850819E+03 -0.47027058E+02 0.35732687E+03 + -0.74357651E+02 0.24879044E+02 0.67221268E+02 0.34626282E+02 + -0.15760850E+02 0.95299788E+01 0.20570358E+02 -0.99656219E+01 + 0.57932053E+01 -0.10340133E+03 -0.13253651E+03 0.30239807E+02 + 0.14212955E+02 0.18223083E+02 -0.44180136E+01 0.29476211E+01 + 0.24200895E+02 -0.79207330E+01 -0.70972711E+00 0.10236231E+02 + -0.29160755E+01 -0.13413786E+03 0.19037308E+03 -0.19506718E+03 + 0.28727465E+02 0.42836151E+02 0.36783915E+01 -0.11200488E+02 + 0.11366664E+02 0.33454435E+01 -0.10977008E+02 -0.10146284E+01 + -0.15341073E+00 -0.23435020E+01 0.21834229E+03 -0.54074174E+00 + 0.81919067E+02 -0.17072714E+03 -0.27865326E+02 -0.65729050E+02 + -0.36894897E+02 0.22338470E+02 -0.91411533E+01 0.15863236E+02 + 0.18038864E+02 -0.67405639E+01 -0.59032984E+01 -0.11627515E+03 + -0.24264629E+02 0.48176727E+02 0.13980582E+02 -0.15089851E+03 + 0.25507414E+02 -0.73551226E+01 -0.20702438E+02 -0.20904860E+02 + 0.87487831E+01 -0.55933890E+01 -0.86189528E+01 0.53419051E+01 + 0.78886330E-01 -0.29637569E+00 -0.60464900E-01 -0.71206862E+00 + 0.59372735E+00 -0.20558242E-01 0.48958015E-01 0.17571803E-01 + 0.42676930E-02 -0.61578047E-02 0.21608405E-01 0.51746960E-03 + -0.57962169E-02 -0.11099775E-01 -0.77226818E-01 -0.35840608E-01 + -0.68324238E+00 -0.71531457E+00 -0.41512378E-01 -0.81707276E-02 + -0.76341666E-02 0.20536050E-01 0.75761302E-04 0.10275764E-01 + -0.93738479E-03 0.10511256E-02 0.13842400E+01 -0.49234234E-01 + 0.12677438E-01 -0.10571032E+01 0.10398120E+00 0.59301776E+00 + -0.14417672E+00 -0.12642121E+00 -0.50918173E-01 -0.13518077E+00 + 0.30521564E-01 -0.12413521E+00 -0.55086076E-01 0.13468283E+01 + 0.45321479E+00 0.33050817E-01 -0.19486004E+00 -0.84212869E+00 + 0.33315790E+00 0.56156081E+00 -0.21251965E+00 0.18369168E+00 + -0.45716692E-01 -0.15525162E+00 -0.21887373E-02 -0.13814416E-01 + 0.13547544E+01 0.35052299E+01 0.39791515E+01 -0.39452152E+01 + 0.91488066E+01 -0.59917301E+00 -0.23404016E+01 0.19902436E+00 + 0.28914595E+00 0.32449687E+00 -0.30973130E+00 -0.13093150E+00 + 0.24543996E+00 0.93270177E+00 0.10100641E+01 0.21535051E+01 + -0.79689913E+01 -0.27236197E+01 0.71202475E+00 -0.46545172E+00 + 0.11434031E+01 -0.18245190E+00 -0.40821990E+00 -0.56782430E+00 + -0.14069527E-01 -0.91296136E-01 -0.10542485E+02 0.11633003E+00 + -0.27338638E+01 0.60308561E+01 0.38688376E+01 -0.47813063E+01 + -0.80322623E-01 0.11000690E+01 0.13760308E+01 0.10471878E+01 + -0.10195703E+00 0.84878850E+00 0.67848611E+00 -0.11052454E+02 + -0.35547702E+01 -0.17437516E+01 -0.14164075E+01 0.29000559E+01 + -0.17477272E+00 -0.31872110E+01 0.15479764E+01 -0.11199074E+01 + 0.35770196E-01 0.15186518E+01 -0.51870155E+00 0.42309418E+00 + -0.12578058E+02 -0.68359618E+01 -0.30894136E+02 0.29231522E+02 + -0.37497787E+02 0.42103472E+01 0.13634277E+02 -0.23105450E+01 + -0.25411384E+01 -0.20200243E+01 0.17991819E+01 0.12031136E+01 + -0.22861774E+01 -0.45937929E+01 0.20954573E+01 -0.12322833E+02 + 0.30053970E+02 0.19175720E+02 -0.63447342E+01 0.20542047E+01 + -0.71390734E+01 -0.82132202E+00 0.34279487E+01 0.34167354E+01 + 0.95250791E+00 -0.24310122E+00 0.24285004E+02 -0.33831911E+01 + 0.87184391E+01 -0.14099851E+02 -0.16883636E+02 0.11646293E+02 + 0.59411901E+00 -0.24929810E+01 -0.56281357E+01 -0.20639105E+01 + 0.36040887E+00 -0.18116416E+01 -0.17643518E+01 0.24702208E+02 + 0.38919735E+01 0.61029816E+01 0.65146122E+01 -0.22756844E+01 + -0.12218447E+01 0.49939818E+01 -0.24445648E+01 0.28680897E+01 + -0.10368447E+00 -0.39225388E+01 0.16193438E+01 -0.12233028E+01 + 0.28191435E+02 0.78694779E+00 0.64988586E+02 -0.59622391E+02 + 0.50546677E+02 -0.93377047E+01 -0.25691008E+02 0.49692049E+01 + 0.66733646E+01 0.38342440E+01 -0.33193254E+01 -0.28077450E+01 + 0.59086132E+01 0.68308530E+01 -0.11145399E+02 0.20142715E+02 + -0.35770203E+02 -0.34637833E+02 0.14650714E+02 -0.28380070E+01 + 0.14030186E+02 0.30224793E+01 -0.93840456E+01 -0.67304082E+01 + -0.30187073E+01 0.13366690E+01 -0.19719055E+02 0.68867254E+01 + -0.97942543E+01 0.12571601E+02 0.16866743E+02 -0.80991716E+01 + -0.60612911E+00 0.14781256E+01 0.55502701E+01 0.12907429E+01 + -0.25038749E+00 0.10915365E+01 0.11269932E+01 -0.16954178E+02 + 0.31211653E+01 -0.45404320E+01 -0.60521488E+01 0.81650001E+00 + 0.11353197E+01 -0.19928207E+01 0.10430183E+01 -0.25809250E+01 + 0.46962976E-01 0.30409877E+01 -0.11915779E+01 0.96175605E+00 + -0.18254305E+02 0.40652580E+01 -0.38976639E+02 0.37998062E+02 + -0.22253876E+02 0.54544687E+01 0.15347374E+02 -0.28659790E+01 + -0.52428360E+01 -0.22536192E+01 0.18733271E+01 0.18808315E+01 + -0.43471785E+01 -0.42598820E+01 0.68740034E+01 -0.86680908E+01 + 0.13091698E+02 0.19776108E+02 -0.94230890E+01 0.93041646E+00 + -0.87512522E+01 -0.19371969E+01 0.73051834E+01 0.41424298E+01 + 0.23743391E+01 -0.12347584E+01 -0.10308002E+00 -0.11345816E+00 + -0.42388607E-01 -0.54478396E-01 0.37894849E-01 -0.71249014E+00 + -0.99690706E+00 0.42135198E-01 -0.17244508E-01 0.18175336E-01 + 0.22615844E-01 0.40037408E-02 -0.35507255E-02 -0.27820380E-01 + -0.77944398E-01 0.14688867E+00 0.16636170E-01 0.53210996E-01 + 0.95628870E+00 -0.70051461E+00 0.17104764E-01 0.31993400E-01 + -0.93262866E-02 -0.18731829E-01 0.20413630E-01 -0.50872727E-03 + 0.29756284E+00 0.12934244E+00 -0.18983012E+00 0.71824849E-01 + -0.41808224E+00 -0.11720638E+00 -0.41143599E+00 -0.28631786E-01 + 0.21437567E+00 0.25426919E-01 0.33951659E-01 0.75097613E-01 + -0.22934020E-01 0.60831446E-01 0.26703393E+00 0.11492735E+00 + -0.14872837E+00 0.15820682E+00 0.73452610E+00 -0.15326774E+00 + -0.20186377E+00 0.79028957E-01 -0.39597563E-02 -0.69052167E-02 + -0.35170142E-02 0.39248485E-01 0.77993286E+00 0.11083746E+01 + 0.43744078E+00 0.59175074E+00 0.27468514E+00 0.27732401E+01 + 0.21687405E+01 -0.25144768E+00 0.20495268E-01 -0.25761267E-01 + 0.13951998E-02 -0.70093565E-01 0.10886872E+00 -0.10175123E+01 + 0.14403580E+01 -0.19194680E+01 0.23482403E-01 -0.27122623E+00 + -0.25169382E+01 0.30849991E+01 -0.93018353E-01 -0.32557720E+00 + -0.32845687E-01 0.71069181E-01 -0.18071032E+00 -0.11195785E+00 + -0.68460888E+00 0.29701370E+00 0.60023886E+00 0.74086189E-01 + 0.98181754E+00 0.17232141E-01 0.71498251E+00 0.15950716E+00 + -0.32126063E+00 -0.25459522E-01 0.10034925E+00 -0.21438284E+00 + 0.80607355E-01 0.29350961E-01 -0.52844387E+00 -0.36183965E+00 + -0.28149527E+00 0.92464566E-01 -0.15573701E+01 -0.51209647E-01 + 0.32866800E+00 -0.38855325E-01 0.12696608E-01 0.45670737E-01 + -0.69922102E-02 -0.22250840E-01 -0.49448672E+00 -0.11309271E+01 + -0.43056560E+00 -0.97913963E+00 -0.75081778E+00 -0.50914221E+01 + -0.24884195E+01 0.29986811E+00 0.74715838E-02 -0.13069282E-01 + -0.12120259E+00 0.20640136E+00 -0.19321388E+00 0.16908380E+01 + -0.17447996E+01 0.30932491E+01 -0.34096673E+00 0.17136320E-01 + 0.35928824E+01 -0.54552412E+01 0.32137137E-01 0.51082975E+00 + 0.19546562E+00 -0.10672492E+00 0.28139514E+00 0.41073266E-01 + -0.29096516E-01 0.21864381E-01 0.12243152E-01 0.32921236E-01 + 0.26921557E-01 -0.18893566E-01 0.16802768E-02 0.28694057E+00 + -0.29211944E+00 0.16393879E-01 0.94393194E-02 -0.60703456E-02 + -0.10121062E-02 0.22870012E-01 0.40416900E-01 0.20207793E-02 + 0.28009051E-01 -0.47511235E-01 0.16151294E-01 0.41487217E-02 + 0.24980807E+00 0.29251510E+00 -0.41429587E-02 0.31435890E-02 + 0.86209811E-02 -0.10191371E-01 -0.31774394E-01 0.34211449E-01 + -0.82030535E-01 0.80120206E-01 0.52378405E-01 -0.12363160E+00 + 0.10513848E+00 0.79557300E-01 -0.65318108E-01 -0.10646765E+00 + 0.76470137E-01 0.25804229E-02 0.20964760E-01 0.12791419E+00 + 0.45520249E-02 0.28757796E-01 0.62985361E-01 0.84955096E-01 + -0.12073988E+00 -0.98188937E-01 0.52158497E-01 0.69911301E-01 + -0.42228647E-01 -0.41942723E-01 -0.53663676E-04 0.20629903E-01 + -0.84972262E-01 0.74791489E-02 -0.72876990E-01 0.54825366E-01 + 0.78998543E-02 0.21651429E-02 0.11295613E-01 -0.22708066E-01 + -0.24967114E-01 0.23709925E+00 0.20721009E+00 -0.75820689E-02 + -0.66711716E-02 0.91338404E-01 0.75325787E-01 -0.11707541E-01 + -0.18225780E-02 -0.68179369E-02 0.26803996E-01 0.29882746E-01 + -0.50773583E-02 -0.38290664E-02 -0.20912650E+00 0.21416287E+00 + -0.53014234E-03 0.60032639E-02 0.42857222E-01 -0.81398368E-01 + -0.70250402E-02 0.28814858E-01 0.10183388E-01 0.45627076E-01 + 0.34210831E-01 -0.13469204E-01 -0.16962208E-01 0.95584542E-02 + 0.76674409E-02 -0.11811173E+00 0.10944933E+00 0.37916858E-01 + 0.34320731E-01 -0.38995236E-01 -0.11582066E-01 0.56862938E-02 + 0.19178797E-01 -0.19646438E-01 -0.19834880E-02 -0.70472513E-02 + -0.87856874E-02 -0.38532328E-02 -0.12558442E+00 -0.99743485E-01 + -0.44582158E-01 -0.84324479E-01 -0.50034773E-01 0.46942957E-01 + 0.46193041E-02 0.71701999E-02 -0.12611548E-01 0.95665874E-03 + -0.12036864E-01 -0.67090063E-04 -0.20105047E-01 0.25720501E-02 + 0.19281612E-02 -0.26651990E-01 0.87436736E-01 0.20321310E-01 + -0.69049001E-01 0.10091057E-02 0.10883667E-01 -0.17108638E-01 + -0.87443851E-02 0.57800971E-02 0.46012322E-02 0.20599570E-01 + -0.53997189E-02 0.58125625E-02 -0.57532750E-02 0.34642287E-01 + 0.31471014E-01 -0.11714597E-01 -0.16319931E-01 -0.50641309E-01 + 0.25461501E-01 0.27247520E-01 0.11968784E-01 0.18001124E-01 + -0.22403056E-01 0.21385523E-01 0.13279281E-01 -0.25084522E-01 + 0.21860246E-01 0.28222948E-02 0.35862550E-01 0.60812443E-01 + 0.43446869E-02 0.19660836E-01 0.30596416E-01 -0.88513829E-02 + -0.24848018E-01 -0.96459314E-02 -0.90757385E-02 -0.20335526E-02 + 0.29977398E+01 -0.81961863E-02 0.18906318E-01 0.31932627E-02 + -0.40838043E-02 -0.23357219E-03 0.76571526E-02 -0.79752170E-02 + 0.34400285E-03 0.20014942E+00 -0.29716199E-01 0.52193098E-01 + 0.37738368E-01 -0.50039212E-02 -0.29981712E-01 -0.13986629E-01 + 0.22926545E-02 -0.21308565E-02 0.13428993E+01 0.44498190E-01 + -0.18523584E+00 -0.17925262E+00 0.45948785E-01 0.47860365E-01 + -0.33176940E-01 0.42967811E-01 0.43051202E-01 -0.47216853E+00 + -0.16368181E+00 -0.10566968E+00 -0.59037436E-01 -0.33112377E-01 + 0.11583865E+00 0.14226821E-01 0.78643629E-04 0.69223386E-02 + -0.23492825E+01 0.67165673E-01 0.47879130E+00 0.52358502E+00 + -0.15943331E+00 -0.14764255E+00 0.48829697E-01 -0.51714528E-01 + -0.10612428E+00 0.24342522E+00 0.16540092E+00 0.64394534E-01 + 0.85904822E-02 0.40568676E-01 -0.88596344E-01 -0.20141602E-02 + -0.10498879E-02 -0.26079479E-02 0.11590290E+01 -0.87880909E-01 + -0.30248934E+00 -0.36426729E+00 0.13489676E+00 0.10174662E+00 + -0.20617874E-01 0.17740108E-01 0.64807892E-01 0.14391306E-01 + -0.21309040E+00 -0.33884132E+00 0.10892763E-01 -0.42811520E-02 + -0.25248926E-02 0.12565411E-01 -0.44771396E-02 0.69199530E-02 + 0.26753717E-02 0.35680091E+00 -0.20014954E+00 -0.98086223E-02 + 0.87794177E-02 -0.34690206E-02 -0.91818944E-02 0.56939311E-02 + 0.10811757E-01 -0.10302395E+00 0.19964647E+00 0.12284160E+00 + 0.62227909E-01 0.39830700E-01 -0.31292230E-01 -0.18277897E-01 + 0.34071937E-01 -0.24559934E-01 0.73183656E-01 -0.31019021E-01 + 0.22225292E+00 -0.79470754E-01 -0.39866906E-01 0.20936767E-01 + -0.13295945E-01 0.57061117E-01 0.55259667E-01 -0.22905076E+00 + 0.90782642E+00 0.16330605E+01 0.19163444E-02 0.35776567E-01 + 0.49570460E-01 -0.11902386E+00 0.45402091E-01 -0.11314363E+00 + -0.39456537E+00 -0.17365063E+01 0.86957514E+00 0.16775034E+00 + -0.85004151E-01 0.42578943E-01 0.72186649E-01 -0.78504860E-01 + -0.12058395E+00 0.13912697E+01 -0.96152514E+00 -0.60672939E+00 + -0.13106681E-01 -0.41902941E+00 0.11963302E+00 0.62974282E-02 + -0.18483324E+00 0.25544435E+00 0.54170632E+00 0.34240025E+00 + -0.99347806E+00 0.24775451E+00 0.47574925E+00 -0.18045484E+00 + 0.13595831E+00 -0.61139071E+00 -0.26010543E+00 0.74438137E+00 + -0.80979353E+00 -0.17164000E+01 -0.35758603E+00 -0.14151997E-01 + -0.13134676E+00 0.27793384E+00 -0.11998469E+00 0.27071470E+00 + 0.13506945E+01 0.16267356E+01 -0.12598553E+01 -0.31339693E+00 + 0.68517029E-01 -0.18701576E+00 -0.86923420E-01 0.14469230E+00 + 0.22702868E+00 -0.34414785E+01 0.10698557E+01 0.14466066E+01 + -0.78836627E-01 0.10688086E+01 -0.78987241E-01 0.20188455E+00 + 0.36264935E+00 -0.72390538E+00 -0.21533566E+01 -0.86708015E+00 + 0.16319656E+01 -0.28797519E+00 -0.10868006E+01 0.50646031E+00 + -0.39900687E+00 0.15120944E+01 0.29860812E+00 -0.48577076E+00 + 0.13015091E+00 0.95722878E+00 0.44391340E+00 -0.32366667E-01 + 0.12413591E+00 -0.17610566E+00 0.96929371E-01 -0.16703933E+00 + -0.11894512E+01 -0.38839000E+00 0.71710134E+00 0.12543809E+00 + 0.23892200E-01 0.17996968E+00 -0.33655792E-01 -0.64367652E-01 + -0.11553252E+00 0.22641020E+01 -0.19882113E-01 -0.99476326E+00 + -0.88516831E-01 -0.73695374E+00 0.47051865E-02 -0.22439906E+00 + -0.23656234E+00 0.55085856E+00 0.17834071E+01 0.62063682E+00 + -0.85358530E+00 0.12144196E+00 0.67288089E+00 -0.39924723E+00 + 0.35274625E+00 -0.10284061E+01 -0.55081528E-01 -0.42461529E-02 + -0.19090572E-01 -0.21750685E-02 0.77972591E-01 -0.10230899E+00 + -0.61414950E-02 -0.60802400E-02 -0.60765664E-02 -0.31842440E-02 + 0.36602344E-02 -0.20476624E-01 0.19559986E-02 0.12126583E+00 + 0.80235839E-01 -0.91823526E-02 -0.76314099E-02 0.35730619E-02 + -0.18788263E-02 0.73799253E-01 0.18658286E+00 0.25844133E-01 + 0.38106725E-01 0.13187512E-01 0.33492073E-01 -0.36260985E-01 + -0.13196411E-01 -0.99324882E-02 0.14192871E-01 -0.25389522E-01 + -0.18034408E-01 0.66986740E-01 0.37657667E-01 0.83836555E-01 + -0.19943714E-01 -0.24610313E-01 0.22301380E-01 -0.17031062E+00 + 0.24293564E+00 -0.47562115E-01 -0.18710291E+00 -0.21173184E+00 + 0.45424968E-01 0.10562469E+00 0.11877581E-01 0.27717492E-01 + -0.23334759E+00 0.18515386E-01 -0.18031676E+00 0.16339771E+00 + -0.16562819E+00 0.22401253E-01 0.12215626E+00 -0.20599376E-01 + -0.22505933E-01 -0.23864312E+00 -0.10410758E+01 0.20875807E+00 + 0.41495822E-02 -0.14400750E+00 -0.13934612E-01 0.98016083E-01 + 0.64151287E-01 -0.90540037E-03 0.43185464E+00 0.47100693E+00 + 0.23188818E+00 -0.12820059E+00 0.30625874E+00 -0.37186649E+00 + 0.27746355E-01 0.18685448E+00 -0.14788830E+00 0.31099784E+00 + -0.51439345E+00 0.33028477E-02 -0.17644372E-01 0.89867830E-01 + -0.63249946E-01 -0.14556962E+00 -0.11969469E-01 -0.39798412E-01 + 0.37246841E+00 -0.99704146E-01 0.28348404E+00 -0.27310556E-01 + -0.17952356E-02 0.30666629E-01 -0.20847888E+00 -0.28230350E-02 + 0.19477865E-01 0.20202784E+00 0.14707640E+01 -0.31790841E+00 + -0.87093830E-01 0.18147080E+00 -0.21470474E-01 -0.88236153E-01 + -0.84560633E-01 0.35590552E-01 -0.68945134E+00 -0.61575747E+00 + -0.83507538E-01 0.61113440E-01 -0.57205105E+00 0.39900196E+00 + 0.70120335E-01 -0.22128370E+00 0.17749646E+00 -0.23316428E-01 + 0.12048602E-01 0.23783315E-02 0.92227734E-03 0.47883238E-02 + 0.22830907E-01 -0.44083364E-01 -0.45512468E-02 0.17387260E-02 + -0.70657879E-02 -0.15885700E-01 -0.40105842E-02 -0.69217123E-02 + -0.58886260E-02 0.35231207E-01 0.42952798E-01 0.33667523E-02 + -0.20392444E-02 0.59208654E-01 0.63783467E-01 0.12437731E-01 + -0.64228058E-01 0.13783633E-01 -0.51416833E-01 0.18383341E-01 + 0.69502769E-02 0.81083290E-02 0.40749948E-01 -0.75332182E-02 + -0.27416047E-01 -0.33444658E-01 -0.19954121E-01 0.60441415E-02 + -0.56821901E-01 0.11292342E-02 0.17509492E-01 -0.67723930E-01 + -0.14539140E+00 -0.30557400E-01 0.45087747E-02 -0.46182219E-01 + -0.15280163E+00 -0.10240619E+00 0.26795983E-01 -0.21112163E-02 + -0.47966205E-01 0.10730193E-01 -0.31358361E-01 0.15586140E-01 + -0.61677694E-02 0.13321459E+00 -0.20194066E+00 0.10347780E-01 + -0.12390454E-01 -0.18478956E-01 -0.15848845E-01 0.85952654E-02 + 0.16202677E-01 0.12485576E-02 -0.19915239E-02 0.31446819E-02 + 0.44241477E-01 -0.30390825E-03 -0.94869845E-02 0.91496035E-02 + -0.60107480E-02 -0.70505962E-02 -0.37957486E-02 0.63174265E-03 + 0.55268030E-02 -0.33853739E-03 0.48207466E-01 0.65101504E-01 + 0.29953867E-01 -0.47032386E-02 -0.26011158E-01 -0.31840345E-02 + 0.30755347E-02 0.13277408E-02 0.22132436E-01 0.82672723E-02 + -0.78570247E-02 -0.45788117E-01 0.51256302E-02 0.33361401E-01 + -0.11823521E-01 -0.16863131E-02 -0.15676618E-01 0.17375017E-01 + 0.15721172E-01 0.64684786E-02 -0.96570849E-02 0.89065656E-02 + -0.50537400E-02 -0.49813055E-02 0.20753630E-02 0.76234303E-02 + -0.90143494E-02 0.38806566E-02 0.70466399E-02 0.23270644E-01 + -0.98308958E-02 -0.23814661E-02 -0.12868521E-02 0.14961662E-01 + 0.29478408E-02 -0.25250821E-02 0.35902052E-02 0.68825744E-02 + 0.69127004E-02 0.12519724E-01 0.12947413E-01 -0.24092742E-02 + 0.11634666E-02 -0.38903586E-02 -0.92853437E-03 0.12939579E-02 + -0.27606012E-02 -0.23899183E-02 -0.13654519E-01 -0.14725208E-02 + 0.18952836E-02 0.95515475E-02 0.27220517E-02 -0.41225250E-02 + 0.64941794E-02 0.26891699E+01 -0.77640079E-02 0.11127226E-01 + 0.56581008E-02 0.55255595E-03 0.19188959E-02 0.38992227E-02 + -0.63712634E-02 -0.10736038E-02 0.89743257E-01 0.20814056E-01 + 0.49664252E-01 0.12002766E-01 0.16872058E-01 -0.14828339E-01 + -0.20098081E-01 -0.71201287E-02 -0.10063168E-01 0.14451989E+01 + 0.18207381E-01 -0.12469007E+00 -0.77557147E-01 0.96017905E-02 + 0.50489227E-02 0.77703628E-02 0.43605082E-01 0.20670583E-01 + -0.10420048E+00 -0.30086064E+00 -0.98388195E-01 -0.17734095E-01 + -0.10223061E+00 0.44458363E-01 0.44485766E-01 0.28927311E-01 + 0.21576229E-01 -0.26058178E+01 0.11795593E+00 0.28667599E+00 + 0.16859519E+00 -0.69919109E-01 -0.51369853E-02 -0.43885093E-01 + -0.75206399E-01 -0.15287776E-01 0.39084069E-02 0.23944090E+00 + 0.64139605E-01 0.46739057E-02 0.91723323E-01 -0.28238663E-01 + -0.27856348E-01 -0.21242142E-01 -0.13344119E-01 0.13095465E+01 + -0.10214919E+00 -0.16770975E+00 -0.98850541E-01 0.73869824E-01 + -0.47578216E-02 0.37430067E-01 0.40278368E-01 -0.92505589E-02 + 0.23524527E-01 -0.34971905E+00 -0.28617579E+00 0.24448624E-02 + 0.10531452E-02 -0.24429683E-02 0.79786703E-02 -0.32044223E-02 + 0.65662451E-02 -0.49985647E-02 0.30120927E+00 -0.33876920E+00 + -0.98431110E-02 -0.94157760E-03 -0.78012803E-04 -0.10437773E-01 + 0.98567717E-02 0.11818309E-01 -0.57822526E-01 0.21672080E+00 + 0.88802397E-01 -0.38946371E-02 0.58250647E-01 -0.24885841E-01 + -0.17417109E-01 0.15775122E-01 -0.64615905E-02 0.32139465E-01 + 0.32517146E-01 0.21158406E+00 -0.15073597E-01 -0.36884345E-01 + 0.46076272E-01 0.17812059E-02 0.35551559E-01 0.46800572E-01 + -0.24651740E+00 0.11098005E+01 0.93898606E+00 0.13167661E+00 + 0.78329667E-02 0.21393836E-01 0.26152806E-01 0.99524148E-02 + -0.16420490E+00 -0.35180089E+00 -0.94679415E+00 0.12385635E+01 + 0.81863344E-01 0.52147958E-01 -0.94125010E-02 0.86879611E-01 + -0.13224542E+00 -0.17574912E+00 0.77992594E+00 -0.13512276E+01 + -0.66809845E+00 0.17822577E-01 -0.50182986E+00 0.64230561E-01 + -0.65235972E-01 -0.17756592E+00 0.55901706E-01 0.60895658E+00 + -0.39232604E-01 -0.12162886E+01 -0.19391635E-01 0.24424779E+00 + -0.32840198E+00 0.16300701E-01 -0.27074844E+00 -0.22464836E+00 + 0.55456519E+00 -0.69234842E+00 -0.40266696E+00 -0.63226157E+00 + 0.10810312E-01 -0.15206471E-01 -0.15813009E+00 0.76063037E-01 + 0.54846871E+00 0.12965288E+01 -0.14871562E+00 -0.16574057E+01 + -0.77499509E-01 -0.24706510E+00 -0.49161386E-01 -0.18116426E+00 + 0.29508817E+00 0.42510372E+00 -0.19151392E+01 0.23017206E+01 + 0.19343644E+01 0.18132132E+00 0.97290933E+00 -0.32005329E-01 + 0.30257875E+00 0.47717172E+00 -0.22451323E+00 -0.23164320E+01 + -0.23464796E-02 0.23696499E+01 0.11396230E+00 -0.30829370E+00 + 0.81678474E+00 -0.14368922E+00 0.57714278E+00 0.30708337E+00 + -0.28491080E+00 0.36383953E-01 0.31162423E+00 0.57425320E+00 + -0.42527661E-01 0.73678861E-02 0.16507232E+00 -0.12021208E+00 + -0.42351905E+00 -0.11174612E+01 0.66397589E+00 0.92702854E+00 + -0.17574133E-01 0.21021616E+00 0.75819194E-01 0.74323654E-01 + -0.16377258E+00 -0.30484438E+00 0.11824274E+01 -0.11248283E+01 + -0.14524230E+01 -0.21500514E+00 -0.54644215E+00 -0.13700273E-01 + -0.25452745E+00 -0.35112607E+00 0.19990943E+00 0.20050182E+01 + 0.13328120E-01 -0.14572992E+01 -0.51557053E-01 0.12367893E+00 + -0.57814133E+00 0.17719764E+00 -0.37120977E+00 -0.99483013E-01 + -0.84307924E-03 -0.17258720E-01 -0.53407182E-02 0.81290662E-01 + -0.76485693E-01 -0.47752857E-02 0.17251113E-02 -0.37566551E-02 + -0.43733157E-02 0.26733198E-02 -0.18344464E-01 0.50127059E-02 + 0.71141422E-01 0.87314069E-01 -0.61744680E-02 -0.70299730E-02 + 0.26243478E-02 -0.23496000E-02 0.28444365E-01 0.11505324E+00 + -0.33933113E-02 0.28973152E-02 0.92887580E-01 0.31396374E-01 + -0.23507848E-01 -0.87130778E-02 -0.41673444E-02 0.46873268E-01 + 0.13442471E-01 -0.25793346E-01 -0.76117992E-01 0.18148191E-01 + 0.74972928E-01 0.14298555E-01 -0.31826302E-01 0.11931221E-01 + -0.10709220E+00 0.17803705E+00 0.89736991E-02 -0.42456064E+00 + 0.21876010E+00 -0.10819509E-01 0.28348541E-01 -0.17255737E-01 + 0.18319871E-01 -0.19474296E+00 0.41860357E-01 -0.13339257E+00 + -0.18719764E+00 -0.42420572E+00 -0.77197962E-02 0.99332154E-01 + -0.31550217E-01 -0.35813104E-01 0.40004592E-01 -0.68339717E+00 + 0.27681798E+00 -0.17132305E-01 -0.32585520E+00 0.31075010E-02 + 0.79180360E-01 0.84248841E-01 -0.97170286E-02 0.93430877E-01 + 0.14520723E+00 0.17805336E+00 0.36324471E+00 0.13691723E+00 + -0.32484740E+00 -0.81565976E-01 0.24830070E+00 -0.83268046E-01 + 0.17182922E+00 -0.39017051E+00 -0.75088441E-01 0.10350132E+00 + -0.59314132E+00 0.26216136E-01 -0.36645234E-01 0.51128767E-01 + -0.23116680E-01 0.29115206E+00 -0.16628718E+00 0.17287152E+00 + 0.57455140E+00 0.10316521E+00 0.24566704E-01 -0.18611246E+00 + 0.36977731E-01 0.51306792E-01 -0.20561790E+00 0.10611658E+01 + -0.37965369E+00 0.59568025E-02 0.27356154E+00 -0.27140493E-01 + -0.93819201E-01 -0.12059696E+00 0.53143971E-01 -0.24612650E+00 + -0.89114845E-01 -0.68045080E-01 -0.36101604E+00 -0.25655359E+00 + 0.38696355E+00 0.15423262E+00 -0.32276905E+00 0.91858685E-01 + -0.19476928E-01 0.73561030E-02 0.17873570E-02 -0.35678833E-02 + -0.33237983E-02 0.33766452E-01 -0.63296556E-01 -0.19452671E-02 + -0.13239881E-02 -0.42364784E-02 -0.10886640E-01 0.13287687E-02 + 0.24953787E-03 -0.21379865E-02 0.55756997E-01 0.50980333E-01 + 0.43777418E-02 -0.78862309E-02 0.35293180E-01 0.57927500E-01 + 0.91379695E-02 -0.24990181E-01 0.15874527E-01 -0.32756235E-01 + -0.91940798E-02 0.63448362E-02 0.59108059E-02 0.20577457E-01 + 0.78460500E-02 -0.80252253E-02 -0.28437277E-01 -0.12757894E-01 + 0.18312814E-01 -0.39697696E-01 -0.13474633E-02 0.13109336E-01 + -0.83176978E-02 -0.11117947E+00 -0.57078409E-03 0.10578159E-01 + -0.20841744E-01 -0.17377388E+00 -0.81262529E-01 0.16026542E-01 + 0.58632642E-02 -0.14602412E-01 -0.52710972E-03 -0.37079420E-01 + 0.15373140E-01 0.46844824E-03 0.11484051E+00 -0.20478857E+00 + -0.60416013E-02 0.15950162E-01 -0.92366859E-02 -0.13327929E-01 + 0.76846969E-02 0.44647716E-02 0.99554379E-03 -0.25372533E-02 + 0.11280878E-02 0.34911960E-01 0.61604748E-02 -0.65696426E-02 + 0.27554485E-02 -0.89025460E-02 -0.58459700E-03 -0.36023045E-02 + 0.17695032E-02 0.71463883E-02 -0.67619309E-02 0.35612646E-01 + 0.37786972E-01 0.27549386E-01 -0.10036920E-01 -0.17617412E-01 + -0.51135980E-02 -0.85136071E-02 0.82170218E-02 0.34347039E-01 + 0.35131625E-02 0.34137517E-02 -0.39485250E-01 0.19134531E-01 + 0.13404503E-01 -0.16808830E-01 -0.10705445E-01 -0.19780356E-01 + 0.15510092E-01 0.21839622E-01 0.12911428E-01 -0.73543191E-02 + 0.50285608E-02 0.59204106E-03 -0.34981018E-02 0.37478309E-02 + 0.20511297E-02 -0.60793981E-02 0.34043845E-02 0.10783732E-01 + 0.17769098E-01 -0.77495468E-02 0.85491623E-03 -0.31315386E-02 + 0.84124953E-02 0.57312618E-02 0.12188158E-02 0.74360073E-02 + 0.63715726E-02 0.54682344E-02 0.96778497E-02 0.52643046E-02 + -0.51632933E-02 0.32400470E-02 -0.58748294E-03 -0.52953465E-03 + 0.25913932E-02 0.41622822E-02 -0.12601026E-02 -0.82769878E-02 + 0.12908092E-02 -0.11074101E-02 0.28636474E-02 0.26873224E-02 + -0.14917086E-02 0.50641405E-02 diff --git a/src/main/resources/assets/org/orekit/nequick/ccir14.asc b/src/main/resources/assets/org/orekit/nequick/ccir14.asc new file mode 100644 index 0000000000000000000000000000000000000000..67760b1797b5b36e1da9496a6c12b9ef7052f6c3 --- /dev/null +++ b/src/main/resources/assets/org/orekit/nequick/ccir14.asc @@ -0,0 +1,715 @@ + 0.64934902E+01 -0.60000788E-01 0.15284568E+00 0.42398740E-01 + 0.80449134E-02 -0.12943847E-02 -0.18471057E-01 0.14364938E-01 + -0.27232723E-01 0.34205064E-02 0.44790655E-03 0.49032946E-03 + -0.11499409E-01 -0.88309318E+00 -0.13880616E+00 0.72883040E+00 + -0.23786406E+00 0.56492411E-01 -0.44968978E+00 0.27552202E-01 + -0.10558826E+00 -0.26403385E+00 -0.71968925E-02 -0.76252699E-01 + -0.75245738E-01 0.36521424E-01 0.10725157E+02 0.11520149E+01 + -0.29717493E+01 0.77741122E+00 0.10456991E+01 -0.56724101E+00 + 0.10612049E+01 -0.19255698E-01 0.20865388E+00 0.83688870E-02 + 0.17841756E+00 0.38568933E-01 -0.13791543E+00 0.65042410E+01 + -0.35215242E+01 -0.41706262E+01 0.52065020E+01 0.25852561E+00 + 0.73438554E+01 -0.40593761E+00 0.99215269E+00 0.34198158E+01 + 0.59768510E+00 0.13837194E+01 0.21450300E+01 -0.30246961E+00 + -0.73952774E+02 -0.10371048E+02 0.20006668E+02 -0.58430324E+01 + -0.17244535E+02 0.25785177E+01 -0.66231852E+01 -0.10432463E+01 + 0.73055929E+00 0.10648136E+01 -0.16124161E+01 0.77939093E-01 + 0.78449035E+00 0.16648845E+00 0.12172330E+02 -0.27850800E+01 + -0.25546801E+02 0.91742992E+01 -0.32795715E+02 0.28933215E+00 + -0.56761966E+01 -0.18448345E+02 -0.33526461E+01 -0.67829113E+01 + -0.12907631E+02 -0.90398949E+00 0.15081432E+03 0.33412430E+02 + -0.50513577E+02 0.15113484E+02 0.58774567E+02 -0.36906853E+01 + 0.14214766E+02 0.30996857E+01 -0.45489941E+01 -0.52512522E+01 + 0.42320633E+01 -0.65626699E+00 -0.12561435E+01 -0.37230698E+02 + -0.76325498E+01 0.37164612E+02 0.49207066E+02 -0.43934429E+02 + 0.60087311E+02 0.41347008E+01 0.15909639E+02 0.43547516E+02 + 0.70065866E+01 0.12691342E+02 0.29472048E+02 0.48083038E+01 + -0.14633238E+03 -0.42288406E+02 0.54256516E+02 -0.17434313E+02 + -0.73183670E+02 0.16437654E+01 -0.12896774E+02 -0.25577698E+01 + 0.64732409E+01 0.78860898E+01 -0.44402704E+01 0.10190878E+01 + 0.83452725E+00 0.52198566E+02 -0.78648906E+01 -0.54521667E+02 + -0.41549358E+02 0.62281204E+02 -0.48637405E+02 -0.83191109E+01 + -0.19453854E+02 -0.45155910E+02 -0.66038690E+01 -0.10019680E+02 + -0.28811020E+02 -0.57783604E+01 0.55789322E+02 0.18161957E+02 + -0.20868530E+02 0.74471412E+01 0.30560638E+02 0.63638091E-01 + 0.42821302E+01 0.46981829E+00 -0.28367577E+01 -0.37410164E+01 + 0.16539935E+01 -0.48298734E+00 -0.21111564E+00 -0.20312286E+02 + 0.70529175E+01 0.23697172E+02 0.12980739E+02 -0.27796112E+02 + 0.14427420E+02 0.43019180E+01 0.83882170E+01 0.16908129E+02 + 0.23868091E+01 0.27971561E+01 0.10196642E+02 0.21167965E+01 + -0.23634212E+00 0.20315304E+01 0.14751930E+01 0.51506601E-01 + -0.41991580E-01 -0.66530518E-02 0.60239170E-01 0.42047124E-01 + 0.14694091E-01 0.14501675E-01 0.22909958E-01 0.50704996E-02 + -0.13813756E-01 0.24778871E-01 -0.13336086E+01 0.20401323E+01 + -0.29250428E-01 0.11255962E+00 -0.27715957E-01 -0.61806727E-01 + 0.33551301E-02 0.49672596E-01 -0.88648424E-02 0.15672090E-01 + -0.17772950E-01 0.25840359E-01 -0.94002926E+00 0.96187341E+00 + -0.48695213E+00 -0.14855824E-01 0.85204065E-01 0.68687499E-01 + 0.59923762E+00 -0.17397808E+00 0.52780789E+00 -0.97602300E-01 + -0.50955068E-01 0.97110152E-01 0.78837097E-01 -0.15056741E+00 + 0.25372839E+00 0.77975589E+00 0.44844516E-01 0.66648591E+00 + 0.29808592E-01 -0.28804496E-01 0.27313727E+00 0.57353723E+00 + -0.14783476E+00 -0.54335695E-01 0.18213356E+00 -0.17622779E+00 + 0.44821749E+01 0.12306819E+02 0.71697431E+01 -0.92180443E+00 + 0.17149887E+01 0.12936373E+01 -0.14673869E+00 -0.16734647E+01 + -0.90978974E+00 -0.64830923E+00 -0.10648319E+01 0.25684690E+00 + -0.10137749E+00 0.85512936E-01 -0.10835257E+02 0.85481062E+01 + 0.11747246E+01 0.18459187E+01 0.27393371E+00 0.21028149E+01 + -0.48073649E+00 -0.68387586E+00 0.73008960E+00 -0.79940557E-01 + 0.11825161E+01 -0.94839275E+00 0.13821822E+02 -0.18135984E+02 + 0.25114822E+02 0.74971113E+01 0.18632154E+01 0.13507413E+01 + -0.10556159E+02 0.19317436E+01 -0.81330175E+01 0.36078360E+01 + 0.21540526E+00 -0.27909286E+01 -0.10886441E+01 0.62252502E+01 + -0.13018351E+02 -0.10101440E+02 -0.10007334E+01 -0.14628851E+02 + 0.11357670E+01 0.36046579E+01 -0.42910976E+01 -0.89776678E+01 + -0.89598782E-02 -0.42933545E+00 -0.15849819E+01 0.34161615E+01 + -0.17371536E+02 -0.66748367E+02 0.62607895E+02 0.20953901E+02 + -0.16884048E+02 -0.15206277E+02 -0.11621352E+01 0.13002543E+02 + 0.13039216E+02 0.52742462E+01 0.93021603E+01 -0.34476852E+01 + 0.56655067E+00 -0.56244600E+00 -0.33539307E+02 -0.27122938E+02 + -0.17939257E+02 -0.18481977E+02 -0.38500452E+00 -0.14842595E+02 + -0.31616001E+01 0.47638435E+01 -0.45677814E+01 -0.55476630E+00 + -0.94443140E+01 0.57917881E+01 -0.74925003E+02 0.14071362E+03 + -0.14038927E+03 -0.58120228E+02 0.71764202E+01 -0.49531412E+01 + 0.62205994E+02 -0.40746994E+01 0.32049103E+02 -0.27928362E+02 + 0.17490292E+01 0.17929642E+02 0.32690542E+01 -0.65806335E+02 + 0.54215317E+02 0.98710693E+02 -0.88018885E+01 0.75170929E+02 + -0.11637874E+02 -0.30119812E+02 0.31769405E+02 0.47102097E+02 + 0.81819420E+01 0.76862321E+01 0.71875305E+01 -0.20791471E+02 + 0.89678278E+01 0.10135834E+03 -0.35098581E+03 -0.86679382E+02 + 0.51673244E+02 0.53351055E+02 0.76851797E+00 -0.36545685E+02 + -0.47825405E+02 -0.15288160E+02 -0.24478300E+02 0.11542590E+02 + 0.20585670E+01 0.16705963E+02 0.25283752E+03 -0.40345551E+02 + 0.73295853E+02 0.65839951E+02 0.55188236E+01 0.37025745E+02 + 0.24288328E+02 -0.10951291E+02 0.91241064E+01 0.23609194E+00 + 0.27590467E+02 -0.15265543E+02 0.19687543E+03 -0.38724146E+03 + 0.30177783E+03 0.15378909E+03 -0.65229538E+02 -0.34766834E+01 + -0.15835889E+03 0.39712992E+01 -0.47045303E+02 0.82022125E+02 + -0.10522799E+02 -0.45835918E+02 -0.15153828E+01 0.19607631E+03 + -0.66795013E+02 -0.28728564E+03 0.45004833E+02 -0.16881577E+03 + 0.29734268E+02 0.87140701E+02 -0.93818207E+02 -0.11390156E+03 + -0.33501694E+02 -0.25811827E+02 -0.17500469E+02 0.51393459E+02 + 0.36721817E+02 -0.58378582E+02 0.52954004E+03 0.12650403E+03 + -0.61309464E+02 -0.72215317E+02 0.55067844E+01 0.43052780E+02 + 0.65146362E+02 0.18467985E+02 0.23828384E+02 -0.14804020E+02 + -0.66496487E+01 -0.41053898E+02 -0.39513181E+03 0.14958511E+03 + -0.11126385E+03 -0.10337822E+03 -0.17559296E+02 -0.34940395E+02 + -0.43032944E+02 0.85262613E+01 -0.69466352E+01 0.36357472E+01 + -0.34809723E+02 0.18168348E+02 -0.24683015E+03 0.44674805E+03 + -0.29277637E+03 -0.16985976E+03 0.11071173E+03 0.20931091E+02 + 0.18121008E+03 -0.38683252E+01 0.23711790E+02 -0.10216880E+03 + 0.16843338E+02 0.51287094E+02 -0.42596769E+01 -0.21369887E+03 + 0.15854465E+02 0.32373215E+03 -0.56573437E+02 0.18293462E+03 + -0.24894987E+02 -0.10696294E+03 0.11558175E+03 0.12890712E+03 + 0.48120483E+02 0.32083450E+02 0.20970276E+02 -0.55741138E+02 + -0.36825500E+02 0.12671241E+02 -0.24902856E+03 -0.60534363E+02 + 0.24415833E+02 0.33357071E+02 -0.56761298E+01 -0.18138474E+02 + -0.29999865E+02 -0.79703002E+01 -0.73311758E+01 0.64502964E+01 + 0.43373957E+01 0.26744598E+02 0.18625591E+03 -0.93930145E+02 + 0.56447620E+02 0.58127300E+02 0.13249874E+02 0.98932362E+01 + 0.23001038E+02 -0.14396305E+01 0.16029671E+01 -0.36048810E+01 + 0.15927849E+02 -0.79116158E+01 0.11669274E+03 -0.18738850E+03 + 0.10586761E+03 0.65915176E+02 -0.55447582E+02 -0.14503894E+02 + -0.76371857E+02 0.23939581E+01 -0.49679351E+00 0.45396576E+02 + -0.83436613E+01 -0.20962418E+02 0.35527294E+01 0.76042999E+02 + 0.11706136E+02 -0.12662367E+03 0.20020096E+02 -0.78973938E+02 + 0.45572462E+01 0.47576385E+02 -0.49966721E+02 -0.54524887E+02 + -0.23131269E+02 -0.13527062E+02 -0.95180092E+01 0.22111982E+02 + 0.19034376E-01 0.98584294E-01 0.10540416E-01 -0.10316916E+01 + -0.50497759E-01 -0.28466880E-02 0.14425300E-01 0.89508248E-03 + 0.40291805E-01 -0.58668959E-02 -0.37617795E-02 0.81910542E-03 + 0.14230343E-01 0.55068705E-01 -0.61659031E-02 0.25711080E-01 + 0.34259059E-01 -0.75383472E+00 0.40433593E-02 -0.13901707E-01 + -0.40712301E-01 -0.29276971E-01 -0.10735628E-01 -0.72969962E-03 + -0.98825954E-02 -0.17654423E-02 0.12820826E+00 0.71660626E+00 + 0.71653312E+00 0.37673324E+00 -0.52130514E+00 0.26109612E+00 + -0.33626252E+00 0.12658983E+00 0.23496895E+00 0.45112647E-01 + 0.10876165E-01 -0.79171479E-01 -0.49059771E-01 0.84820718E+00 + 0.11983800E+00 0.93958414E+00 0.63321990E+00 0.95848078E+00 + 0.16888374E+00 0.38933191E+00 -0.13174997E+00 -0.13978601E+00 + -0.28500170E+00 -0.16895264E+00 0.28273299E-01 -0.13272935E+00 + 0.10719461E+01 -0.10473357E+01 0.16151114E+01 0.88533993E+01 + 0.29226627E+01 -0.44834805E+00 -0.18926812E+01 -0.10330507E+01 + 0.70661664E-01 0.34604049E+00 0.24440202E+00 -0.55603737E+00 + -0.15387839E+00 0.15618076E+01 0.14701883E+00 -0.74968100E-01 + -0.39555376E+01 0.69049401E+01 -0.19420260E+00 0.57892245E+00 + -0.79809880E+00 0.60062045E+00 0.22479728E-01 -0.32704270E+00 + 0.23038144E+00 0.36810511E+00 -0.29060514E+01 -0.35181141E+01 + -0.57364321E+01 0.55235319E+01 0.45822948E+00 -0.15032139E+01 + 0.21021149E+01 -0.25328857E+00 -0.18473366E+01 -0.84338069E-01 + 0.39706537E+00 0.18311097E+00 0.12498159E+01 -0.99295187E+01 + -0.10716363E+01 -0.49983826E+01 -0.20832243E+01 0.18830384E+01 + 0.86717826E+00 -0.15240573E+01 0.21804466E+01 0.58699912E+00 + 0.14913263E+01 0.91169506E+00 0.18899290E+00 0.18160113E+01 + -0.94457226E+01 0.17658323E+02 -0.11660739E+02 -0.68379431E+01 + -0.55005393E+01 0.43817205E+01 0.11818675E+02 0.47689600E+01 + 0.28519672E+00 -0.19000348E+01 -0.25939710E+01 0.37662928E+01 + 0.75847077E+00 -0.56515369E+01 0.91205730E+01 -0.19686935E+01 + 0.13128128E+02 -0.68311536E+00 0.99185145E+00 -0.16249561E+01 + 0.51543722E+01 -0.11013594E+01 -0.84779024E-01 0.18501140E+01 + -0.38142788E+00 -0.30122881E+01 0.75019464E+01 0.35646598E+01 + 0.11501076E+02 -0.18637678E+02 -0.69856590E+00 0.35613029E+01 + -0.47264385E+01 -0.46824560E+00 0.42374134E+01 -0.10472507E+00 + -0.11728554E+01 -0.23341642E+00 -0.39178734E+01 0.26873823E+02 + -0.89032382E+00 0.74988828E+01 0.33407247E+01 -0.96325502E+01 + -0.34091043E+01 0.21045971E+01 -0.56645594E+01 0.19026136E+00 + -0.22414274E+01 -0.13311146E+01 -0.59583026E+00 -0.46499023E+01 + 0.21163467E+02 -0.48009995E+02 0.25364655E+02 -0.28718992E+02 + 0.28193629E+00 -0.14275018E+02 -0.20585052E+02 -0.64663582E+01 + -0.17794695E+01 0.29850130E+01 0.60325069E+01 -0.71860552E+01 + -0.16418027E+01 0.39766912E+01 -0.27315859E+02 0.82747126E+01 + -0.15480449E+02 -0.37333546E+02 -0.14049911E+01 -0.78134067E-01 + -0.88510962E+01 -0.22243376E+01 0.97602409E+00 -0.25714509E+01 + -0.92084914E+00 0.73255782E+01 -0.59779358E+01 0.12392722E+01 + -0.78840609E+01 0.12213485E+02 -0.45400095E+00 -0.31542864E+01 + 0.34382265E+01 0.87975073E+00 -0.27262013E+01 0.43419164E+00 + 0.68464506E+00 0.22095340E+00 0.30523138E+01 -0.20467281E+02 + 0.39570873E+01 -0.23940723E+01 0.22183470E+00 0.45692406E+01 + 0.23968153E+01 -0.16324166E+01 0.37603848E+01 -0.13567247E+01 + 0.12711171E+01 0.64020485E+00 0.41453236E+00 0.32386904E+01 + -0.14195784E+02 0.34288696E+02 -0.15830329E+02 0.32217911E+02 + 0.34044676E+01 0.12452764E+02 0.10785024E+02 0.26360891E+01 + 0.13603802E+01 -0.15146807E+01 -0.39355421E+01 0.41184168E+01 + 0.11697750E+01 0.83907938E+00 0.17864227E+02 -0.90199423E+01 + 0.53105707E+01 0.36594131E+02 0.70343792E+00 0.17940168E+01 + 0.47861300E+01 0.37236946E+01 -0.12472181E+01 0.73165965E+00 + 0.12939290E+01 -0.52513409E+01 -0.64028978E-01 0.89368582E-01 + -0.10483639E+00 -0.41617226E-01 0.42851824E-01 -0.37522113E+00 + -0.74830669E+00 -0.35888157E-02 0.50473485E-01 0.39554738E-01 + 0.17244505E-01 -0.62780869E-02 0.40925257E-02 0.47223814E-01 + -0.15007500E+00 -0.77078819E-01 0.23586081E-01 -0.40981133E-01 + 0.73113239E+00 -0.37994540E+00 -0.29909760E-01 0.14559224E-01 + 0.11881359E-01 -0.21748170E-01 0.17178882E-01 0.25832307E-01 + -0.12422318E+00 0.75573784E+00 0.11975992E+00 -0.26279080E+00 + -0.63855439E+00 -0.10346420E+00 -0.24757488E+00 0.83832867E-01 + -0.37987664E-01 0.47420461E-01 0.51827621E-01 -0.82543485E-01 + -0.48918199E-01 -0.25143119E-01 -0.32514679E+00 -0.23532417E+00 + -0.13309411E-01 -0.85015297E-01 0.38035685E+00 0.60264967E-01 + -0.13409160E-01 -0.31570800E-01 -0.10386515E+00 -0.10889218E-01 + 0.21442086E-01 -0.58925855E-02 0.51993853E+00 -0.57693455E-01 + 0.28187776E+00 -0.73442996E-01 -0.19520199E+00 -0.11351214E-01 + 0.58080941E+00 -0.54905403E+00 0.22085562E+00 -0.66554368E-01 + -0.17385942E+00 0.18870948E-03 -0.11992918E+00 -0.21958470E+00 + 0.21047790E+01 -0.20394138E+00 -0.57054359E+00 0.54538924E-01 + -0.12259455E+01 0.53822301E-01 -0.47958690E+00 -0.65027052E+00 + -0.24385015E-01 0.14002997E+00 -0.22192314E+00 -0.13525110E+00 + -0.54393631E+00 -0.13514566E+01 0.26100159E+00 0.43233761E+00 + 0.97404122E+00 0.40088600E+00 0.80763835E+00 -0.98028898E-01 + 0.11027521E+00 -0.10748786E+00 -0.36647193E-01 0.19190548E+00 + 0.88344038E-01 -0.25658113E+00 0.72416735E+00 0.57697695E+00 + -0.34691739E+00 0.32392943E+00 -0.13627892E+01 0.11442542E+00 + -0.10774225E+00 0.10521625E+00 0.98740995E-01 0.29976498E-01 + 0.26290990E-01 -0.56078196E-01 0.27019137E+00 0.45024633E+00 + -0.17958546E+00 0.12233192E+00 0.51881069E+00 0.42524201E+00 + 0.30084956E+00 0.94178414E+00 -0.65111023E+00 -0.27122756E-01 + 0.76508403E-01 -0.85360545E-04 0.12641454E+00 0.79744749E-01 + -0.28821568E+01 0.73260629E+00 0.53177392E+00 0.33241987E+00 + 0.14034442E+01 0.37998933E+00 0.94033831E+00 0.12633944E+01 + -0.60186643E-01 -0.11780189E+00 0.26741916E+00 0.93822658E-01 + -0.40619414E-01 0.80723651E-02 -0.33849481E-01 0.31438515E-01 + 0.26720108E-01 0.34434192E-01 0.15387810E-01 0.30153817E+00 + -0.68199992E-01 0.15819103E-01 0.84541179E-02 -0.12130376E-01 + -0.27178496E-02 0.10475044E+00 0.49542673E-02 0.35022680E-01 + 0.87533653E-01 -0.61479896E-01 -0.14135311E-01 -0.12770660E-01 + 0.36308039E-01 0.26710707E+00 0.10513935E-01 -0.55483915E-02 + 0.76266038E-02 -0.12753191E-01 -0.21390149E-02 0.58438718E-01 + -0.11032433E+00 0.12841827E+00 -0.22302933E+00 -0.96188486E-01 + 0.17974999E-01 0.29908019E+00 0.44135422E+00 -0.46303540E-01 + 0.41154433E-01 -0.14057259E-01 0.87432861E-02 0.30396742E+00 + 0.75595438E-01 -0.15522313E+00 -0.17690331E-02 0.20859616E+00 + -0.87131821E-02 -0.10404949E+00 -0.36777055E+00 0.11611283E+00 + -0.29208448E-02 -0.80868125E-01 0.16911153E-01 0.13700172E-01 + -0.13175464E+00 -0.61796587E-01 -0.48755106E-01 -0.12370612E-01 + -0.54931860E-01 -0.18966548E-01 0.25214598E-01 0.38970198E-01 + -0.42744718E-01 0.83304524E-01 0.22285061E+00 -0.54338342E-03 + 0.11550711E-02 0.12497650E-01 0.33643264E-01 -0.49855206E-01 + 0.77534854E-01 -0.20823942E-01 0.56232177E-02 -0.27867476E-01 + 0.31055158E-01 0.45609649E-01 -0.22880864E+00 0.88289440E-01 + 0.14045585E-01 -0.77454448E-02 -0.15834920E-01 -0.47239352E-01 + 0.55206645E-01 -0.21747218E-01 0.19386901E-01 0.35340980E-01 + 0.19234708E-01 0.55831406E-01 0.12493883E-01 -0.18281758E-01 + -0.14992006E-01 -0.12327415E+00 0.10836016E-01 0.29655596E-01 + 0.94482973E-02 -0.85593499E-02 0.62130173E-02 0.62354229E-01 + 0.73285471E-02 -0.53194743E-01 -0.14881391E-01 0.54990910E-02 + -0.13634078E-01 -0.12771357E-01 0.14701583E-02 -0.12577879E+00 + 0.20759542E-01 0.37858861E-02 -0.38624063E-01 0.25079563E-01 + 0.28830523E-01 0.14798064E-01 0.11077591E-01 0.17425487E-01 + 0.35621811E-01 -0.25656393E-01 -0.24061343E-01 0.10520254E-01 + 0.45533031E-02 0.66021502E-01 -0.21064222E-01 -0.72724116E-02 + 0.14031812E-01 0.59114881E-01 0.15700981E-01 0.68930606E-02 + -0.33762053E-01 -0.16519625E-01 -0.90381280E-02 -0.59326994E-02 + 0.11942730E-01 0.13869076E-01 0.63189805E-01 0.68125665E-01 + -0.60883962E-01 -0.21250362E-01 -0.66251676E-02 -0.73823370E-02 + 0.39793648E-01 -0.44493157E-01 0.10462926E-01 -0.12947633E-01 + -0.25500299E-02 -0.15238016E-01 0.15929744E-01 -0.17856486E-01 + -0.52744091E-01 -0.53626947E-01 0.39534133E-01 0.30350424E-01 + 0.46890299E-02 -0.20292008E-02 0.65144040E-02 0.41108795E-01 + -0.98453537E-02 -0.10881118E-01 0.51510613E-03 0.14489322E-01 + 0.97736454E+01 0.14032149E+00 0.20471638E+00 0.45970183E-01 + 0.19347200E-01 0.34263048E-02 -0.56153458E-01 0.16434990E-01 + -0.13611991E-01 0.26763937E-01 0.57403482E-02 0.63922629E-02 + -0.11557202E-01 0.21873844E+00 -0.40463656E-02 0.25696558E+00 + -0.28938836E+00 0.35062745E+00 0.15157066E+00 -0.29073572E+00 + 0.10218960E+00 -0.17300346E+00 -0.40608421E-01 -0.18231004E-01 + -0.10038074E-01 0.41188151E-01 0.30748093E+02 -0.22748404E+01 + -0.31234465E+01 0.27615955E+01 0.15846490E+01 -0.34613085E+00 + 0.56108177E+00 0.11689794E+00 0.14760590E+00 -0.10534286E+01 + -0.31982249E+00 0.22981022E+00 -0.44722270E-01 -0.14903675E+02 + 0.10495949E+00 0.34792297E+01 0.47500277E+01 -0.45592585E+01 + -0.62566572E+00 0.40229530E+01 -0.11005297E+01 0.26008978E+01 + -0.20069686E+00 0.20519114E+00 0.83855027E+00 -0.12517659E+00 + -0.15924529E+03 0.13519260E+02 0.10932476E+02 -0.29060255E+02 + -0.17306379E+02 0.23026781E+01 -0.11505022E+01 0.89456850E+00 + 0.19126707E+00 0.56772122E+01 0.24429233E+01 -0.23409443E+01 + 0.10148535E+01 0.11584834E+03 -0.17900436E+02 -0.13041323E+02 + -0.16672867E+02 0.35105484E+02 -0.30701971E+01 -0.21194824E+02 + 0.64325066E+01 -0.15774624E+02 0.32018070E+01 0.94925410E+00 + -0.46957254E+01 -0.13125658E+01 0.29437546E+03 -0.25372299E+02 + -0.15352103E+02 0.91963020E+02 0.53816132E+02 -0.39363289E+01 + -0.11707983E+01 -0.62234497E+01 -0.21492355E+01 -0.11163956E+02 + -0.70858798E+01 0.70973525E+01 -0.29095373E+01 -0.29224634E+03 + 0.61603146E+02 -0.42039785E+01 0.19493484E+02 -0.98674660E+02 + 0.13333192E+02 0.47858608E+02 -0.16327667E+02 0.39196564E+02 + -0.93861618E+01 -0.60532713E+01 0.96561794E+01 0.45459681E+01 + -0.26182544E+03 0.17990250E+02 0.11552253E+02 -0.11288570E+03 + -0.65355698E+02 0.19973888E+01 0.40330248E+01 0.10058838E+02 + 0.31824427E+01 0.93387594E+01 0.84235001E+01 -0.84775352E+01 + 0.29146051E+01 0.29994775E+03 -0.74359123E+02 0.36368927E+02 + -0.57280788E+01 0.11249139E+03 -0.15975359E+02 -0.48075104E+02 + 0.17203217E+02 -0.41371586E+02 0.10335050E+02 0.90007267E+01 + -0.86931515E+01 -0.47164726E+01 0.91385612E+02 -0.41139164E+01 + -0.41653347E+01 0.47360001E+02 0.27213379E+02 -0.10529798E-02 + -0.22038870E+01 -0.48923016E+01 -0.13381233E+01 -0.28368788E+01 + -0.34559803E+01 0.34892290E+01 -0.93806016E+00 -0.10869085E+03 + 0.30786818E+02 -0.22838776E+02 -0.15038880E+01 -0.44714828E+02 + 0.61636324E+01 0.17758163E+02 -0.62771397E+01 0.15508571E+02 + -0.38858967E+01 -0.40972462E+01 0.29156959E+01 0.15558701E+01 + -0.13369411E+00 0.17268353E+01 0.14351931E+01 0.76106489E-01 + -0.28437421E-01 -0.11006787E-01 0.26756639E-01 0.27960544E-01 + 0.89221098E-03 0.14117886E-01 0.26185047E-01 -0.14624753E-02 + -0.14191493E-01 0.24574745E+00 -0.14273099E+01 0.15711823E+01 + -0.83912969E-01 0.46123274E-01 -0.25364887E-01 -0.29690675E-01 + -0.29524008E-01 0.19983063E-01 -0.17720956E-01 0.16691633E-01 + -0.70638615E-02 -0.72944127E-02 0.39862120E+00 -0.13170791E+00 + -0.64909154E+00 -0.32600099E+00 0.21109907E+00 -0.12451130E+00 + 0.43011889E+00 -0.18416306E+00 0.24612100E+00 -0.10645312E+00 + 0.16143292E+00 -0.21634486E-01 0.63935578E-01 0.92620963E+00 + -0.49406093E+00 0.64722395E+00 -0.72104096E-01 0.28068078E+00 + 0.60120350E+00 0.27893120E+00 0.30756903E+00 0.17852146E-01 + -0.17372718E+00 -0.12843072E-01 0.60005605E-01 -0.44218379E+00 + 0.10201951E+01 0.13495907E+02 -0.10630936E+02 -0.10683584E+01 + 0.58663213E+00 -0.10076990E+01 -0.52236598E-01 -0.47220087E+00 + 0.46965638E+00 -0.10257159E+01 -0.77649903E+00 0.21886134E+00 + -0.13192790E-01 -0.63123817E+01 0.98021412E+01 0.17635956E+02 + 0.41804466E+01 0.17669467E+01 0.96404302E+00 -0.45744419E-01 + 0.97980118E+00 -0.73717678E+00 -0.27884775E+00 -0.14686048E+00 + 0.75753582E+00 0.43112880E+00 -0.29365110E+01 -0.14322777E+01 + 0.14004352E+02 0.79823327E+00 -0.58754282E+01 0.25628233E+01 + -0.86770878E+01 0.29869022E+01 -0.79320562E+00 0.71983647E+00 + -0.20778570E+01 0.96054983E+00 -0.10125141E+01 -0.14787667E+02 + 0.89715195E+01 -0.16094650E+02 0.62427349E+01 -0.78737435E+01 + -0.20880356E+01 -0.53182232E+00 -0.72572398E+01 0.20186644E+01 + -0.28493702E+00 -0.16519641E+01 -0.56926078E+00 0.75286026E+01 + 0.38437169E+01 0.23742905E+01 0.10843651E+03 0.32352238E+01 + 0.29753845E+01 0.82216110E+01 -0.24196386E+01 0.54554968E+01 + -0.16184169E+00 0.67759500E+01 0.53559599E+01 -0.44717273E+00 + -0.89659041E+00 0.51551998E+02 -0.11602978E+03 -0.19592438E+02 + -0.36331177E+02 -0.12795038E+02 -0.63453693E+01 0.43711376E+01 + -0.10106876E+02 0.51247439E+01 0.35840931E+01 0.18366956E+01 + -0.68241382E+01 -0.46224632E+01 -0.85184898E+01 0.16360107E+02 + -0.82426071E+02 0.12709790E+02 0.42946472E+02 -0.15440465E+02 + 0.50130875E+02 -0.12952685E+02 -0.69280119E+01 -0.39795117E+01 + 0.73542223E+01 -0.55133829E+01 0.81558447E+01 0.96722000E+02 + -0.39015034E+02 0.11213722E+03 -0.45417725E+02 0.37435165E+02 + -0.13082532E+01 -0.10213684E+02 0.49293098E+02 -0.15153332E+02 + 0.73512321E+01 0.14430302E+02 0.19037808E+01 -0.38897949E+02 + -0.43353897E+02 -0.20246556E+03 -0.28853784E+03 0.21355970E+01 + -0.19108793E+02 -0.21631132E+02 0.12639036E+02 -0.18742432E+02 + -0.96571703E+01 -0.16555695E+02 -0.14417871E+02 0.12324685E+00 + 0.51283340E+01 -0.14933171E+03 0.32959497E+03 -0.18182323E+03 + 0.11664076E+03 0.33371811E+02 0.17004456E+02 -0.19989792E+02 + 0.32714706E+02 -0.11863820E+02 -0.12437938E+02 -0.82264690E+01 + 0.19701036E+02 0.14783766E+02 0.80268509E+02 -0.52966339E+02 + 0.19053438E+03 -0.56769222E+02 -0.11784625E+03 0.38850357E+02 + -0.12247974E+03 0.22450394E+02 0.35795441E+02 0.12220045E+02 + -0.89107666E+01 0.82319517E+01 -0.27355560E+02 -0.27648267E+03 + 0.89760971E+02 -0.27464084E+03 0.11196627E+03 -0.69628693E+02 + 0.97918758E+01 0.44225204E+02 -0.12664154E+03 0.35483719E+02 + -0.18650513E+02 -0.41325409E+02 -0.23082571E+01 0.85997482E+02 + 0.88594849E+02 0.39292139E+03 0.33457983E+03 -0.12988246E+02 + 0.27334517E+02 0.24206512E+02 -0.20228148E+02 0.24981491E+02 + 0.22630323E+02 0.17233309E+02 0.16416183E+02 -0.32048082E+00 + -0.83845119E+01 0.18617632E+03 -0.39346265E+03 0.42378687E+03 + -0.15928719E+03 -0.40951447E+02 -0.20998566E+02 0.32289703E+02 + -0.42694336E+02 0.11828459E+02 0.17220367E+02 0.13173158E+02 + -0.22972109E+02 -0.18645218E+02 -0.14528056E+03 0.72072128E+02 + -0.21711533E+03 0.77514603E+02 0.13667310E+03 -0.45385799E+02 + 0.13474229E+03 -0.16270966E+02 -0.53262211E+02 -0.17100185E+02 + 0.23942337E+01 -0.10488987E+01 0.37738708E+02 0.35145361E+03 + -0.85622955E+02 0.26572534E+03 -0.10509779E+03 0.58970486E+02 + -0.46502333E+01 -0.66478333E+02 0.13732690E+03 -0.33438583E+02 + 0.15821193E+02 0.48546875E+02 0.14652004E+01 -0.85408585E+02 + -0.52937943E+02 -0.20882059E+03 -0.14351865E+03 0.98669796E+01 + -0.11305204E+02 -0.10061108E+02 0.10184311E+02 -0.11492324E+02 + -0.13785836E+02 -0.64393110E+01 -0.66763268E+01 0.56769723E+00 + 0.43437328E+01 -0.82705460E+02 0.16970370E+03 -0.24499573E+03 + 0.77111313E+02 0.21147842E+02 0.97495165E+01 -0.17787201E+02 + 0.19586733E+02 -0.44074764E+01 -0.82658710E+01 -0.68889666E+01 + 0.94197063E+01 0.82319374E+01 0.79956360E+02 -0.38184708E+02 + 0.95916229E+02 -0.35911255E+02 -0.56887787E+02 0.20183624E+02 + -0.54853703E+02 0.38453093E+01 0.25204601E+02 0.86927290E+01 + 0.11558257E+01 -0.29337673E+01 -0.18029600E+02 -0.15973773E+03 + 0.28304304E+02 -0.87137711E+02 0.30577972E+02 -0.21899443E+02 + -0.35690377E+01 0.34283482E+02 -0.53517757E+02 0.10929289E+02 + -0.38510756E+01 -0.20168243E+02 -0.64146167E+00 0.31352385E+02 + 0.29265391E-01 -0.24591346E+00 0.14553225E+00 -0.84675032E+00 + 0.61966658E+00 -0.31919140E-01 0.56226421E-01 0.23503462E-01 + 0.53592059E-02 -0.20415215E-01 0.15285025E-01 -0.63779615E-02 + 0.55775279E-03 0.90108335E-01 -0.20454387E+00 -0.73520787E-01 + -0.64477378E+00 -0.82056803E+00 -0.32559566E-01 -0.23924757E-01 + -0.15155605E-01 -0.23472777E-01 -0.29544419E-01 0.71342289E-02 + -0.47043152E-02 -0.47027953E-02 0.52882087E+00 0.75878024E+00 + 0.37392047E+00 0.52214783E+00 -0.73013431E+00 0.44710666E+00 + 0.54939020E-01 0.22959816E+00 0.20311102E+00 -0.81182413E-01 + -0.88519573E-01 -0.12205945E+00 -0.90271056E-01 0.76053393E+00 + 0.47488004E+00 0.52843851E+00 0.69257706E+00 0.27872598E+00 + 0.68038344E-01 0.28850752E+00 -0.78320973E-01 0.16159260E+00 + -0.23097008E+00 -0.32177996E-01 0.43377083E-01 -0.46754383E-01 + 0.45139915E+00 0.33630769E+01 -0.12169753E+01 -0.37143755E+01 + 0.72003303E+01 -0.30781597E+00 -0.21212358E+01 -0.96283770E+00 + 0.84034169E+00 0.23972344E+00 -0.28099906E+00 0.56343921E-01 + -0.53734171E+00 -0.14882059E+01 0.13920954E+01 0.12130709E+01 + -0.79513631E+01 -0.25826595E+01 -0.42678672E+00 0.51285851E+00 + 0.19756992E+00 0.12423239E+01 0.54061139E+00 -0.37421107E-01 + 0.29954505E+00 0.11390960E+00 -0.56358538E+01 -0.57385159E+01 + -0.52712650E+01 -0.10486718E+01 0.53347263E+01 -0.35143900E+01 + -0.12000904E+01 -0.28657036E+01 -0.12631083E+01 0.94290608E+00 + 0.92692262E+00 0.13676528E+01 0.12747040E+01 -0.10084607E+02 + -0.83411741E+00 -0.68800192E+01 -0.56028543E+01 -0.31238854E+00 + 0.13777542E+01 -0.14698858E+01 0.52827829E+00 -0.40625009E+00 + 0.18055103E+01 -0.78214061E+00 -0.69355130E-01 0.65176880E+00 + 0.11241798E+01 -0.65113230E+01 -0.21158094E+01 0.29776367E+02 + -0.24963104E+02 0.54256268E+01 0.11766754E+02 0.49691448E+01 + -0.47331409E+01 0.25715870E+00 0.14093018E+01 -0.11038085E+01 + 0.35657842E+01 0.14730918E+02 -0.30367286E+01 -0.11354827E+02 + 0.30109863E+02 0.22487961E+02 0.39788237E+01 -0.24708538E+01 + -0.19585207E+01 -0.73399401E+01 -0.29647701E+01 0.20387474E+00 + -0.30212841E+01 -0.14654016E+01 0.14754129E+02 0.11049474E+02 + 0.13400967E+02 0.58017559E+01 -0.10485389E+02 0.91833000E+01 + 0.26157825E+01 0.80078144E+01 0.25257502E+01 -0.23380880E+01 + -0.18219414E+01 -0.34472320E+01 -0.37856760E+01 0.27359421E+02 + -0.55443001E+01 0.20240784E+02 0.79822860E+01 0.63297043E+01 + -0.35024121E+01 0.38299048E+01 0.60368818E+00 0.41653626E-02 + -0.47033873E+01 0.24803982E+01 -0.54888368E+00 -0.18400832E+01 + -0.71220398E+01 -0.11084242E+01 0.93044796E+01 -0.59619064E+02 + 0.21860550E+02 -0.16687057E+02 -0.19368773E+02 -0.89723339E+01 + 0.81729593E+01 -0.26830547E+01 -0.22497015E+01 0.32522850E+01 + -0.77899036E+01 -0.42522598E+02 0.84326611E+01 0.25657211E+02 + -0.35328537E+02 -0.45498714E+02 -0.12340077E+02 0.45494366E+01 + 0.38336656E+01 0.14014010E+02 0.50293474E+01 -0.80758739E+00 + 0.73919759E+01 0.33322277E+01 -0.14168421E+02 -0.38411448E+01 + -0.11940655E+02 -0.86237659E+01 0.33731954E+01 -0.65763731E+01 + -0.14734648E+01 -0.60773025E+01 -0.16627016E+01 0.18981389E+01 + 0.91158038E+00 0.23963673E+01 0.29741066E+01 -0.22353622E+02 + 0.11713837E+02 -0.14435800E+02 0.11054907E+01 -0.10635337E+02 + 0.18735408E+01 -0.32202845E+01 -0.17535981E+01 0.22505578E+00 + 0.38518553E+01 -0.17070560E+01 0.92721134E+00 0.15198689E+01 + 0.53186111E+01 0.61862020E+01 -0.31186657E+01 0.37600204E+02 + -0.35645133E+00 0.12633383E+02 0.96007862E+01 0.52255840E+01 + -0.41970530E+01 0.22828407E+01 0.11919298E+01 -0.24510040E+01 + 0.52333198E+01 0.34840073E+02 -0.12539687E+02 -0.16330978E+02 + 0.10885726E+02 0.29065948E+02 0.10912359E+02 -0.25189369E+01 + -0.15795354E+01 -0.82213926E+01 -0.28210602E+01 0.71790761E+00 + -0.55111475E+01 -0.20255136E+01 -0.19228468E-01 -0.13114969E+00 + 0.15714891E-01 -0.59424613E-01 0.61318099E-01 -0.58697617E+00 + -0.10644102E+01 0.20145897E-01 -0.13622614E-01 -0.18642440E-01 + 0.22151217E-01 0.47150515E-02 0.11869197E-02 0.58520351E-01 + -0.16852538E+00 -0.50097305E-01 0.11990507E-01 -0.65762768E-02 + 0.10272388E+01 -0.58508110E+00 0.10597579E-01 0.35774235E-01 + -0.15361955E-02 -0.45238875E-01 -0.18923515E-01 -0.59281816E-02 + 0.25976366E+00 0.61606842E+00 0.13208784E-01 0.22894324E+00 + -0.39829195E+00 0.10561228E+00 -0.10849887E+00 0.61109383E-01 + 0.13916729E+00 0.60511831E-01 0.12184702E-01 0.34330257E-02 + 0.49652584E-01 0.33294815E+00 0.93975179E-02 -0.15443995E-01 + 0.12950848E-01 -0.53923000E-01 0.16462354E+00 0.16396616E+00 + -0.73470592E-01 0.80365360E-01 -0.35155836E-01 -0.88913918E-01 + -0.47349852E-01 0.39145380E-01 0.11885967E+01 0.70961654E+00 + 0.16401082E+00 0.73770243E+00 -0.50291091E+00 0.21559591E+01 + 0.16197529E+01 -0.89583582E+00 0.20669129E+00 0.29641485E+00 + 0.17593938E+00 0.21165987E-01 -0.99231154E-02 -0.12865351E+01 + 0.23329020E+01 -0.46353474E+00 -0.75524986E-01 0.23183055E+00 + -0.19695919E+01 0.19060564E+01 -0.13436995E+00 -0.10136843E+01 + 0.37376542E-01 0.39470100E+00 0.21998766E+00 -0.11666384E-01 + -0.71975422E+00 -0.56198859E+00 0.62459815E-01 -0.95555365E-01 + 0.97378629E+00 0.58153582E+00 0.55926204E+00 -0.48008882E-01 + -0.39891303E+00 -0.46037633E-01 0.33642609E-01 0.59914339E-01 + -0.43716528E-01 -0.10643940E+01 -0.18275888E+00 -0.33081704E+00 + -0.55505341E+00 0.37782079E+00 -0.80053771E+00 0.45424262E+00 + -0.85584484E-02 -0.85956872E-01 0.12678234E+00 0.19393580E+00 + 0.18442684E+00 -0.24153914E-01 -0.15753583E+01 -0.46785456E+00 + -0.12589588E+01 -0.16451540E+01 0.12443190E+01 -0.42283182E+01 + -0.14672079E+01 0.14503812E+01 -0.24458456E+00 -0.60518193E+00 + -0.42549506E+00 -0.76019049E-01 -0.11163372E+00 0.21944077E+01 + -0.25643044E+01 0.99713415E+00 -0.11333126E+00 -0.71992117E+00 + 0.24609306E+01 -0.36890421E+01 0.18535006E+00 0.17068615E+01 + -0.43102510E-01 -0.49058509E+00 -0.35204017E+00 -0.33120696E-01 + -0.58546931E-01 -0.61199516E-02 0.13920870E-01 -0.22593589E-01 + 0.60600404E-01 -0.26639463E-01 -0.16022459E-01 0.32998067E+00 + -0.22570471E+00 0.51776581E-02 0.17488200E-01 -0.34345095E-02 + -0.48399717E-02 0.23667345E-01 0.10178505E+00 -0.29486220E-01 + 0.57037495E-01 -0.34963217E-01 0.11159873E-01 -0.30660912E-01 + 0.19712470E+00 0.30310649E+00 -0.16301766E-01 0.55935443E-03 + -0.90922392E-03 0.42374507E-02 -0.16880973E+00 0.95758557E-01 + -0.14629465E+00 0.12069291E+00 0.56210212E-01 -0.12945680E+00 + 0.17435408E+00 0.96609123E-01 0.45201021E+00 -0.36387533E-01 + -0.25372000E-01 0.18637779E-02 -0.35717620E-02 0.18735176E+00 + -0.15473641E-01 0.31935621E-01 0.47426187E-02 0.11311482E+00 + -0.13744950E+00 -0.12981302E+00 -0.40770859E+00 0.16419124E-01 + 0.27462887E-03 -0.82576871E-01 -0.18355068E-01 -0.51394594E-02 + -0.22159742E-01 -0.74835721E-03 -0.36677279E-01 0.25976231E-01 + 0.33930014E-02 0.16898615E-01 0.23251481E-02 0.38304761E-01 + -0.42265587E-01 0.20900027E+00 0.22713178E+00 -0.21249074E-02 + -0.10710888E-01 0.22197489E-01 0.83272219E-01 -0.76565206E-01 + 0.21317841E-02 -0.13129897E-01 0.16477928E-01 0.48060704E-01 + 0.35126519E-02 0.52965075E-01 -0.20686191E+00 0.17197242E+00 + -0.42362544E-02 -0.16804583E-01 0.21828219E-01 -0.31586766E-01 + 0.81997097E-01 0.30568486E-01 0.17527277E-01 0.51112950E-01 + -0.15168884E-02 0.15925396E-02 -0.10897528E-01 -0.70789973E-02 + 0.73832721E-02 -0.12407726E+00 0.85962117E-01 0.66300750E-01 + 0.51962443E-01 -0.13351659E-01 -0.23629975E-01 0.20142781E-01 + 0.38463738E-01 -0.13412733E-01 -0.93066990E-02 -0.41893609E-02 + 0.41461214E-02 -0.17357357E-01 -0.11255020E+00 -0.12668882E+00 + -0.59766680E-01 -0.32285359E-01 -0.46988074E-01 0.39100412E-01 + 0.98173134E-02 0.30527685E-01 -0.36675993E-01 -0.82789995E-02 + 0.30238912E-01 -0.19059832E-02 -0.11280149E-01 -0.14733354E-01 + -0.83649457E-02 0.45781229E-01 0.46038054E-01 0.41310016E-01 + -0.11225827E+00 -0.28089361E-01 0.13309367E-01 -0.41037355E-01 + -0.30710906E-01 -0.95726699E-02 -0.23963353E-01 0.16758919E-01 + 0.11331436E-01 0.23001432E-01 0.68212305E-02 0.87390661E-01 + 0.28464919E-01 -0.32604266E-01 -0.19913837E-01 -0.69480479E-01 + -0.14800049E-01 0.22902381E-01 0.37979655E-01 0.20491345E-01 + -0.21194533E-01 -0.35256981E-02 -0.19661651E-02 -0.39640930E-01 + 0.19599622E-01 -0.60924828E-01 -0.32056216E-01 0.47802251E-01 + 0.17946444E-01 -0.80087408E-02 0.32511208E-01 -0.46744160E-02 + 0.21583994E-02 -0.19618925E-01 -0.14446046E-01 -0.65722279E-02 + 0.30586901E+01 -0.16637225E-01 0.11471305E-01 0.27490903E-02 + 0.25678016E-02 0.37677907E-02 0.98502189E-02 -0.31296548E-02 + -0.10140380E-02 -0.13978875E+00 0.40312845E-01 0.71543939E-01 + 0.19734308E-01 -0.78674182E-02 -0.28102145E-01 -0.14239721E-01 + -0.12600210E-01 0.16756020E-01 0.90984887E+00 0.30035329E+00 + -0.44702735E-01 -0.11969292E+00 -0.10557235E+00 -0.41341107E-01 + -0.80306888E-01 0.44076689E-01 0.34757946E-01 0.86042881E-01 + -0.43596476E+00 -0.28588772E+00 -0.25438230E-01 0.25069172E-01 + 0.82588375E-01 0.67566931E-01 0.33206835E-01 -0.41824643E-01 + -0.12932892E+01 -0.72340822E+00 0.77358042E-02 0.28751051E+00 + 0.31436360E+00 0.10259445E+00 0.24149394E+00 -0.12717050E+00 + -0.11702043E+00 -0.22331178E-01 0.38658845E+00 0.28259498E+00 + 0.19711517E-02 -0.24714001E-01 -0.56775015E-01 -0.61311476E-01 + -0.21844219E-01 0.23831610E-01 0.39463905E+00 0.47750133E+00 + 0.76429836E-01 -0.16718167E+00 -0.21960318E+00 -0.68737447E-01 + -0.17916366E+00 0.90928324E-01 0.88356256E-01 0.15348784E-01 + -0.19566035E+00 -0.33543330E+00 0.15999720E-01 -0.25417623E-02 + 0.83187260E-02 0.10059297E-01 -0.18240045E-02 -0.25734284E-02 + 0.16147815E-01 0.36533713E+00 -0.16898608E+00 -0.20461163E-01 + 0.10633610E-01 -0.42438929E-03 -0.20938260E-01 -0.21641953E-02 + 0.55525005E-02 -0.45814317E-01 0.26786933E-01 0.10879261E+00 + 0.84931552E-01 0.15261322E-01 -0.21805950E-01 -0.14455589E-01 + 0.77350582E-02 0.63701212E-01 0.53684931E-01 0.14995108E-01 + -0.27922710E-01 -0.33047087E-01 0.29755291E-01 -0.18964428E-01 + -0.24144309E-01 0.18880598E-01 0.58857311E-01 -0.22821715E+00 + 0.75741506E+00 0.14800968E+01 0.46163443E-01 -0.14732170E+00 + -0.15568149E+00 -0.56558043E-01 0.70298553E-01 0.11026068E+00 + -0.79187077E+00 -0.15295104E+01 0.65210593E+00 0.17441596E+00 + 0.41551359E-01 -0.66639602E-01 0.12556064E+00 -0.61385304E-01 + 0.27926460E-01 0.87673563E+00 -0.39955688E+00 -0.11206913E+01 + -0.28584504E+00 -0.59748329E-02 0.23729973E+00 -0.19509707E+00 + 0.81449509E-01 -0.73962659E+00 0.28284615E+00 0.89057446E+00 + 0.18807463E+00 -0.24254572E+00 -0.17398730E-01 0.79301968E-02 + 0.20122550E+00 0.40711228E-01 -0.34922600E+00 0.67434174E+00 + -0.67298323E+00 -0.74801010E+00 -0.38288945E+00 0.36076793E+00 + 0.47676268E+00 0.13727283E+00 -0.16624431E+00 -0.43988281E+00 + 0.26705711E+01 0.34237185E+00 -0.97559363E+00 -0.27165592E+00 + -0.16340864E+00 0.21915102E+00 -0.12436141E+00 0.95994294E-01 + -0.12902556E+00 -0.24572020E+01 0.30924755E+00 0.28079758E+01 + 0.50721401E+00 -0.17149810E+00 -0.52098668E+00 0.85138261E+00 + -0.28973019E+00 0.17749032E+01 -0.11304550E+01 -0.23089056E+01 + -0.42302924E+00 0.84942168E+00 0.32151359E+00 0.73436797E-01 + -0.39552432E+00 -0.25851828E+00 0.62756401E+00 -0.39601427E+00 + 0.25266504E+00 -0.31376165E+00 0.29245359E+00 -0.21280552E+00 + -0.37739211E+00 -0.73750854E-01 0.96640050E-01 0.40330353E+00 + -0.21711264E+01 0.10492506E+01 0.67013448E+00 0.88845730E-01 + 0.71819246E-01 -0.15133917E+00 -0.11708714E-01 -0.57785511E-02 + 0.95103085E-01 0.18162584E+01 0.38207388E+00 -0.23117476E+01 + -0.38997960E+00 0.19229440E+00 0.28452802E+00 -0.74004078E+00 + 0.22057386E+00 -0.11552706E+01 0.10284768E+01 0.18343010E+01 + 0.33841425E+00 -0.62726456E+00 -0.48800993E+00 -0.87205529E-01 + 0.21157786E+00 0.21693029E+00 -0.32993799E+00 -0.18698255E-01 + -0.71124732E-02 -0.16465350E-02 0.46282001E-01 -0.15294395E+00 + -0.13111427E-03 -0.99337585E-02 -0.43608658E-02 -0.90814829E-02 + 0.45116879E-02 -0.97028874E-02 0.12505713E-01 0.16136163E+00 + 0.81213892E-01 -0.58312336E-03 -0.18872095E-01 -0.72849249E-02 + 0.14784368E-02 0.11196059E+00 0.20533665E+00 0.13476495E+00 + 0.33945632E+00 -0.11701983E+00 0.27578950E-01 -0.47568358E-01 + 0.25997529E-01 0.16754407E-01 -0.93069017E-01 0.18283078E-01 + 0.31589806E-01 0.22644910E+00 0.42842603E+00 0.72851181E-01 + 0.11030860E-01 0.23866531E-02 0.14397725E-01 0.61859142E-01 + 0.55517517E-01 -0.38489588E-01 -0.42788506E-01 -0.22592752E+00 + -0.99609435E-01 0.99531174E-01 0.29087326E-01 0.16361938E+00 + -0.23381136E+00 0.14897207E-01 -0.29369402E+00 0.21109746E+00 + -0.18685365E+00 -0.38392194E-01 0.10634160E+00 -0.28300032E-02 + 0.66435995E-03 -0.47440806E+00 -0.11250496E+01 -0.27856827E+00 + -0.13569554E+01 0.21064770E+00 -0.44342969E-01 0.76229990E-01 + -0.24290405E-01 -0.11261434E+00 0.10018148E+01 0.22767542E+00 + -0.75611055E-01 -0.59486091E+00 -0.14215126E+01 -0.24381904E+00 + -0.25383967E+00 0.49857941E-01 -0.13947743E+00 -0.18549798E+00 + -0.21002913E+00 -0.15347000E-01 -0.16834819E+00 0.21803892E+00 + 0.20929642E+00 -0.10061080E+00 -0.31904507E-01 -0.28207505E+00 + 0.25608516E+00 -0.18180054E+00 0.42851415E+00 -0.17312264E+00 + -0.17903682E-01 0.86439610E-01 -0.80150060E-01 0.17098185E-01 + -0.30419683E-01 0.51279235E+00 0.15700253E+01 0.14896683E+00 + 0.12490702E+01 -0.17830938E+00 0.75656474E-01 -0.44224095E-01 + -0.61300099E-01 0.12280393E+00 -0.14596167E+01 -0.35159820E+00 + 0.27934027E+00 0.59198815E+00 0.11541491E+01 0.17868274E+00 + 0.44150433E+00 -0.87764323E-01 0.17973500E+00 -0.24559207E-01 + 0.12929834E-01 0.68207048E-02 -0.12768010E-01 -0.38065603E-02 + 0.26851540E-01 -0.10830906E-01 0.77535986E-03 -0.17365512E-02 + -0.15774000E-01 -0.33989731E-01 -0.11249689E-01 0.58662519E-02 + -0.10439690E-01 0.19332499E-02 0.34207720E-01 -0.10329138E-01 + -0.22380955E-02 0.55513062E-01 0.53344566E-01 0.27011270E-01 + -0.84630370E-01 0.11442304E-01 0.11869610E-01 0.18336914E-01 + 0.21410545E-02 0.52863397E-02 0.21707222E-01 -0.38661319E-02 + -0.25270687E-01 -0.34020606E-01 -0.14334359E-02 -0.38540119E-02 + 0.28737670E-01 0.37115016E-02 -0.18286736E-02 -0.17681255E-02 + -0.14221156E+00 -0.59075002E-01 0.19836433E-01 -0.76047634E-02 + -0.12995809E+00 -0.11560405E+00 -0.16809881E-01 0.35188206E-01 + 0.23344198E-01 0.10418749E+00 -0.43988552E-01 -0.21166107E-01 + -0.33218439E-02 0.14282972E+00 -0.15798102E+00 0.98103173E-02 + 0.10149174E-01 -0.20782378E-01 -0.12256940E-01 0.90859644E-02 + 0.14533855E-01 -0.24522969E-02 0.11254709E-01 0.13583390E-02 + 0.43356489E-01 0.26643330E-02 -0.14128674E-01 0.47900598E-02 + -0.10882851E-01 -0.47548078E-02 -0.53821984E-02 0.31365617E-02 + 0.12613773E-01 -0.60953349E-02 0.45044255E-01 0.63900828E-01 + -0.59823166E-02 0.71507203E-02 -0.16160239E-01 -0.33681545E-01 + -0.40392955E-02 0.60944888E-02 0.60271841E-01 0.34214549E-01 + 0.23164378E-01 -0.68351328E-01 0.12046548E-01 0.31958293E-01 + 0.36123709E-02 -0.11482013E-01 -0.12627609E-01 -0.46289045E-01 + 0.64354002E-01 0.10392379E-02 -0.16863159E-02 0.73957364E-02 + -0.10698939E-02 -0.64807981E-02 0.99908598E-02 0.22006980E-02 + -0.50359704E-02 -0.14203114E-02 0.12199912E-01 0.20179288E-01 + -0.62138620E-02 0.78815632E-02 -0.74640582E-02 0.73885922E-02 + 0.22004370E-02 0.85453279E-02 0.76826178E-02 0.31520715E-02 + -0.12767009E-02 0.30879313E-02 0.64275493E-02 -0.43601133E-02 + 0.98584704E-02 0.17043861E-02 0.84848665E-02 0.36111211E-02 + -0.43704286E-02 -0.78293349E-03 -0.17360970E-01 -0.11529317E-02 + 0.11252891E-01 -0.21595629E-02 -0.14455176E-02 0.98986871E-04 + 0.87585188E-02 0.26772802E+01 -0.86198859E-02 0.94552226E-02 + 0.55961572E-02 0.43859929E-02 0.41296370E-02 0.46669282E-02 + -0.20577968E-02 -0.24387248E-03 -0.65158486E-01 0.74515760E-01 + 0.72828352E-01 0.12489908E-01 0.58226585E-02 -0.11427455E-01 + -0.15949465E-01 -0.65154098E-02 0.17882378E-02 0.12957152E+01 + 0.13960779E+00 -0.44050533E-01 -0.51063329E-01 -0.63741863E-01 + -0.59596479E-01 -0.53228300E-01 0.46188690E-01 0.11657927E-01 + -0.15501004E+00 -0.51885808E+00 -0.24664450E+00 -0.34158926E-01 + -0.38116846E-01 0.12921121E-01 0.49244046E-01 0.17124632E-01 + -0.53521991E-02 -0.20537577E+01 -0.26769561E+00 0.49208440E-02 + 0.11124681E+00 0.16032118E+00 0.16892999E+00 0.16521209E+00 + -0.12701941E+00 -0.60623229E-01 0.17818429E+00 0.42037153E+00 + 0.23076218E+00 0.26306635E-01 0.27854430E-01 -0.14802126E-02 + -0.40314917E-01 -0.73871394E-02 0.24690886E-02 0.82360959E+00 + 0.18576212E+00 0.74848413E-01 -0.66371381E-01 -0.10588891E+00 + -0.11814052E+00 -0.11794991E+00 0.87646544E-01 0.56451134E-01 + 0.19192191E-01 -0.34562641E+00 -0.26493758E+00 0.78390092E-02 + -0.45823753E-02 0.45295572E-03 0.74164458E-02 -0.11921157E-02 + 0.17643603E-02 0.59155165E-04 0.28991437E+00 -0.32774389E+00 + -0.21361131E-01 0.55374275E-02 0.53592431E-02 -0.18224832E-01 + -0.22406343E-02 0.48251487E-02 0.43235645E-02 0.13838613E+00 + 0.46312857E-01 0.21590928E-01 0.16815718E-01 -0.19970588E-01 + 0.64824097E-04 -0.19745342E-03 0.47364239E-01 0.35681468E-01 + 0.49083740E-01 0.10480714E+00 0.58407630E-02 0.63248575E-02 + 0.33869774E-02 -0.22746570E-01 0.86412355E-02 0.40659290E-01 + -0.36743331E+00 0.11957970E+01 0.91784447E+00 0.13865000E+00 + -0.27913701E-01 -0.31462729E-01 -0.16293772E-01 0.48463605E-01 + -0.73108386E-03 -0.61130714E+00 -0.93153489E+00 0.12322998E+01 + 0.17962565E+00 0.92122070E-02 -0.88324785E-01 0.12294370E+00 + -0.67933202E-01 -0.18161766E-01 0.24850304E+00 -0.11966048E+01 + -0.56054062E+00 -0.38083974E-01 -0.12794179E+00 0.15602165E+00 + -0.32316101E+00 0.64251304E-01 -0.52134228E+00 0.38644767E+00 + 0.52516818E+00 -0.71278834E+00 -0.22031006E+00 0.48846070E-01 + -0.63622057E-01 0.20911931E+00 0.87847173E-01 -0.20944718E+00 + 0.10246782E+01 -0.12937897E+01 -0.40522784E+00 -0.58681500E+00 + 0.13400626E+00 0.13890813E+00 0.50930057E-01 -0.12004628E-01 + -0.18637219E-01 0.22995975E+01 -0.29405493E+00 -0.19752225E+01 + -0.36606321E+00 -0.36992472E-01 0.18337315E+00 -0.16064256E+00 + 0.12423855E+00 0.50655343E-02 -0.79235858E+00 0.22702663E+01 + 0.19082404E+01 0.38968597E-01 0.33631071E-01 -0.34791511E+00 + 0.11422634E+01 -0.18621103E+00 0.13048162E+01 -0.16866663E+01 + -0.17086962E+01 0.15004873E+01 0.64295954E+00 0.89812338E-01 + 0.19795392E+00 -0.47849473E+00 -0.32040602E+00 0.35970521E+00 + -0.68489265E+00 0.76091522E+00 0.12355459E+00 0.44687080E+00 + -0.14212960E+00 -0.13827264E+00 -0.91967396E-02 -0.65421760E-01 + 0.32495584E-01 -0.19574795E+01 0.92517078E+00 0.13603249E+01 + 0.23316287E+00 -0.27497090E-01 -0.11032373E+00 0.18738518E-01 + -0.33233728E-01 -0.10697253E-01 0.59273267E+00 -0.12416373E+01 + -0.19759160E+01 0.18526610E-01 0.10760015E+00 0.19402064E+00 + -0.95974118E+00 0.11718221E+00 -0.88802701E+00 0.15903206E+01 + 0.16918584E+01 -0.10219688E+01 -0.45557451E+00 -0.17555869E+00 + -0.13787276E+00 0.30494553E+00 0.23491567E+00 -0.17701098E+00 + -0.17107017E-01 -0.11062064E-01 0.93461685E-02 0.72881281E-01 + -0.11495991E+00 -0.24580231E-02 -0.34615423E-02 -0.27623498E-02 + -0.68666786E-02 -0.95973685E-02 -0.17075190E-01 0.91627240E-02 + 0.10242629E+00 0.92916191E-01 0.24848133E-02 -0.11218094E-01 + -0.55938447E-02 0.10607604E-03 0.10907738E+00 0.13264811E+00 + 0.73107123E-01 0.13814706E+00 0.24720402E-01 0.25445610E-01 + -0.19353468E-01 -0.68268133E-03 0.79990216E-02 0.44637099E-02 + 0.49218759E-01 -0.18194417E-01 0.33405840E-01 0.20319276E+00 + 0.36236916E-01 0.17274112E-01 -0.63722837E-02 0.33721287E-01 + 0.25666660E-01 0.92364073E-01 -0.91084361E-01 -0.36218083E+00 + 0.19792330E+00 -0.52057374E-01 0.40467951E-01 -0.31956334E-01 + 0.12260312E+00 -0.15529650E+00 0.11941779E+00 -0.13577777E+00 + -0.17587662E+00 -0.45683962E+00 -0.65770686E-01 0.69410920E-01 + -0.18389065E-01 0.85385442E-02 -0.37895924E+00 -0.73540914E+00 + -0.56422461E-01 -0.47111732E+00 -0.20011032E+00 -0.17941421E-01 + 0.27807336E-01 0.76329648E-01 -0.42905848E-01 0.33812633E+00 + -0.11257857E+00 0.52691780E-01 0.99168271E-02 -0.50797993E+00 + -0.69310427E-01 -0.12250752E+00 0.10490370E+00 -0.24429388E+00 + -0.96905589E-01 -0.29989797E+00 0.95130742E-01 0.83204031E-01 + -0.46254903E+00 0.10771060E+00 -0.16102757E-01 0.71079552E-01 + -0.19646353E+00 0.21520536E+00 -0.41078597E+00 0.15975517E+00 + 0.48532066E+00 0.16240960E+00 0.74154317E-01 -0.57246845E-01 + 0.45167182E-01 -0.30693918E-01 0.27020484E+00 0.10784187E+01 + -0.53013720E-01 0.46552581E+00 0.92620194E-01 0.51729452E-01 + -0.36019333E-01 -0.14987499E+00 0.62644899E-01 -0.55153668E+00 + 0.28454649E+00 0.94641261E-01 0.93170047E-01 0.38448083E+00 + 0.47209587E-01 0.20970257E+00 -0.13942526E+00 0.29898924E+00 + -0.25534304E-01 0.54413597E-02 0.14065276E-01 -0.76298034E-02 + -0.10420345E-01 0.29778400E-01 -0.41098721E-01 -0.40198043E-02 + -0.51609315E-02 -0.10902796E-01 -0.23414368E-01 -0.62101185E-02 + 0.97503476E-02 -0.91798007E-02 0.33085525E-01 0.36749899E-01 + -0.47427081E-02 -0.77581662E-02 0.33572678E-01 0.60052574E-01 + 0.14006684E-01 -0.36195543E-01 0.13402760E-01 0.33575904E-01 + 0.35400661E-02 -0.38376541E-02 0.42043738E-02 0.25882047E-01 + 0.10295447E-01 -0.20480629E-02 -0.22618543E-01 -0.37360494E-02 + 0.12422180E-02 0.29957971E-01 0.19331203E-02 0.71227252E-02 + 0.44606976E-01 -0.10304904E+00 -0.50200403E-01 -0.11642319E-02 + 0.27468763E-02 -0.13490731E+00 -0.85447609E-01 -0.19251920E-02 + 0.38483709E-01 0.11273086E-01 0.55817258E-01 -0.40558748E-01 + -0.12057238E-02 0.39492734E-02 0.10076773E+00 -0.14639936E+00 + -0.27176535E-02 0.11188756E-01 -0.19127030E-01 -0.16049713E-01 + 0.92721246E-02 0.23639500E-02 -0.56997477E-03 0.52273949E-02 + 0.54570334E-03 0.32571722E-01 0.92297159E-02 -0.76535936E-02 + 0.41365661E-02 -0.10613390E-01 0.34963775E-02 -0.13046856E-02 + 0.11616312E-02 0.74619646E-02 -0.10147393E-01 0.32333367E-01 + 0.38845401E-01 0.55554290E-02 -0.41929297E-02 -0.15542837E-01 + -0.18608434E-01 -0.68834014E-02 0.12991249E-01 0.47244687E-01 + 0.51083587E-01 0.33533402E-01 -0.61769702E-01 0.22310423E-01 + 0.10246638E-01 -0.62199384E-02 -0.11598878E-01 -0.16985394E-01 + -0.50428759E-01 0.41603893E-01 0.17688369E-02 -0.36227440E-02 + 0.84820502E-02 0.28933494E-02 -0.58887936E-02 0.68608033E-02 + 0.30614503E-03 -0.15316578E-02 -0.24033545E-02 0.92781484E-02 + 0.14051887E-01 -0.10239174E-01 0.53211115E-02 -0.21397618E-02 + 0.44980948E-02 0.54727197E-02 0.70043909E-02 0.11711870E-01 + 0.68015754E-02 0.21883962E-02 0.35151723E-02 0.67476854E-02 + -0.67525278E-02 0.54354896E-02 0.19866447E-02 0.76344423E-02 + 0.59919464E-02 -0.26257581E-02 -0.48037633E-04 -0.10798142E-01 + 0.56925323E-03 0.80262758E-02 -0.51455799E-03 -0.93577243E-03 + -0.71163801E-03 0.78903772E-02 diff --git a/src/main/resources/assets/org/orekit/nequick/ccir15.asc b/src/main/resources/assets/org/orekit/nequick/ccir15.asc new file mode 100644 index 0000000000000000000000000000000000000000..d3109608fba3b59155b4cb3e4882016c5ae71405 --- /dev/null +++ b/src/main/resources/assets/org/orekit/nequick/ccir15.asc @@ -0,0 +1,715 @@ + 0.56421361E+01 -0.81572413E-01 0.20138618E+00 0.42779677E-01 + 0.44377021E-01 0.38025156E-02 -0.87150792E-03 0.21708569E-01 + -0.23025222E-01 -0.33594198E-02 0.21446485E-03 -0.18263943E-02 + -0.12104561E-01 -0.10026588E+01 -0.77602589E+00 0.80115181E+00 + -0.27182055E+00 0.54614949E+00 -0.18997934E+00 0.82413137E-01 + -0.38998052E-01 -0.97885430E-01 0.13837355E+00 0.10652161E+00 + -0.15692274E+00 0.99289834E-01 0.80236692E+01 0.19602766E+01 + -0.35586729E+01 0.28472131E+00 -0.56597888E+00 -0.44183964E+00 + 0.13710302E+00 0.35544120E-01 0.41852087E+00 0.63865769E+00 + -0.19955041E+00 0.11715311E+00 0.86535454E-01 0.14375470E+02 + 0.64524765E+01 -0.62800093E+01 0.55624418E+01 -0.81383457E+01 + 0.28389120E+01 -0.18190528E+01 0.17703342E+00 0.13019990E+01 + -0.19010274E+01 -0.25744610E+01 0.22809553E+01 -0.81978834E+00 + -0.53995441E+02 -0.20322050E+02 0.18375992E+02 -0.74895930E+00 + -0.51071939E+01 0.81174737E+00 -0.39087519E+00 -0.14415855E+01 + -0.10194235E+01 -0.38520763E+01 0.11969795E+01 -0.14105281E+01 + -0.62901044E+00 -0.18940157E+02 -0.23667873E+02 0.88806610E+01 + -0.27459183E+02 0.41921677E+02 -0.13132247E+02 0.69411263E+01 + -0.15238304E+01 -0.77653646E+01 0.84578733E+01 0.15979067E+02 + -0.12099966E+02 0.12503767E+01 0.11738895E+03 0.68091232E+02 + -0.39820190E+02 -0.16654691E+01 0.25928144E+02 0.13787631E+01 + -0.43914908E+00 0.40016642E+01 0.47450107E+00 0.83207245E+01 + -0.34342327E+01 0.43038511E+01 0.21257401E+01 -0.37460907E+02 + 0.41022411E+02 0.10812600E+02 0.51976318E+02 -0.94334892E+02 + 0.25150225E+02 -0.89467859E+01 0.58774261E+01 0.20332352E+02 + -0.17085920E+02 -0.38310883E+02 0.27109831E+02 0.87873179E+00 + -0.12372594E+03 -0.87597069E+02 0.38698395E+02 0.42182999E+01 + -0.37059372E+02 -0.34062233E+01 0.15188284E+01 -0.37199287E+01 + 0.36815089E+00 -0.74235353E+01 0.42371931E+01 -0.49250050E+01 + -0.28798952E+01 0.87714096E+02 -0.30394651E+02 -0.28824888E+02 + -0.42016953E+02 0.95767807E+02 -0.21253893E+02 0.34847982E+01 + -0.83288565E+01 -0.22973537E+02 0.15845952E+02 0.39268753E+02 + -0.26755201E+02 -0.26882515E+01 0.49962566E+02 0.37968536E+02 + -0.13776734E+02 -0.21174345E+01 0.16793776E+02 0.16195391E+01 + -0.80588609E+00 0.10947104E+01 -0.22045150E+00 0.22938366E+01 + -0.17940501E+01 0.19093056E+01 0.13130226E+01 -0.43963943E+02 + 0.73540721E+01 0.14685715E+02 0.12209098E+02 -0.35778717E+02 + 0.65739965E+01 0.25819159E+00 0.38785124E+01 0.92260513E+01 + -0.54415436E+01 -0.14486172E+02 0.96487923E+01 0.12716560E+01 + -0.21124797E+00 0.17043124E+01 0.20464392E+01 0.56599011E-02 + -0.10268539E+00 0.23923583E-01 0.46511523E-01 0.47292676E-01 + -0.43041888E-02 -0.13252717E-01 0.11830020E-02 0.10728047E-01 + -0.11813323E-01 0.11713130E+00 -0.18258562E+01 0.17008827E+01 + -0.15215687E-01 0.11784351E+00 -0.43866597E-02 -0.22057733E-01 + -0.63331686E-02 0.49470384E-01 -0.17963709E-01 -0.59963912E-02 + -0.16910572E-01 0.36876623E-01 -0.67201304E+00 0.13338751E+00 + -0.21074171E+01 0.51338410E+00 -0.38658464E+00 0.81445098E-01 + -0.95247179E-02 -0.41881126E+00 0.26037967E+00 0.10410905E+00 + 0.31723064E+00 0.19097520E+00 0.45013998E-01 -0.20128696E+00 + 0.15844086E+01 -0.83317602E+00 0.54410458E-01 0.24460573E+00 + -0.36854926E-01 -0.48869911E+00 0.82281888E-01 0.58834499E+00 + 0.92693090E-01 0.62349547E-01 0.23411548E+00 0.29134643E+00 + 0.55470834E+01 0.96163158E+01 0.50997686E+01 0.68665922E+00 + 0.65423727E-01 -0.24311846E+00 -0.12406636E+01 -0.11371593E+01 + 0.11067601E+01 -0.51531065E-01 -0.74737406E+00 0.54248173E-01 + 0.63131154E-01 -0.68635058E+00 -0.12532815E+02 0.31381702E+01 + 0.58695197E+00 -0.89948475E-01 -0.52485317E+00 0.11644163E+01 + -0.24193648E+00 0.99850374E+00 0.73659611E+00 0.30205196E+00 + 0.79808694E+00 -0.56268388E+00 0.84152431E+01 -0.18351839E+01 + 0.22851473E+02 -0.62919540E+01 0.38386995E+00 -0.11887341E+01 + -0.32209759E+01 0.62786980E+01 -0.32539845E+01 0.33874825E-01 + -0.68638248E+01 -0.39917045E+01 0.50753254E+00 0.54675989E+01 + -0.14342615E+02 0.20977674E+02 -0.40119495E-01 -0.43394470E+01 + 0.13764828E+01 0.10244991E+02 0.31333178E+00 -0.92915659E+01 + -0.30012243E+01 -0.67161626E+00 -0.32468977E+01 -0.40313520E+01 + -0.35370174E+02 -0.69950531E+02 0.26502394E+02 0.31762893E+01 + -0.11033850E+01 -0.33225193E+01 0.66381388E+01 0.81779928E+01 + -0.61022072E+01 -0.22130616E+00 0.75198298E+01 0.25410479E+00 + 0.76021153E+00 -0.13441772E+01 0.27343550E+02 0.47622557E+01 + -0.13991564E+02 0.15639170E+01 0.82513838E+01 -0.82063274E+01 + -0.34090369E+01 -0.11663890E+02 -0.46683292E+01 -0.29037731E+01 + -0.57367353E+01 0.13532742E+01 -0.48274445E+02 0.83131851E+02 + -0.96901001E+02 0.27448698E+02 0.21074265E+02 0.43562355E+01 + 0.23491089E+02 -0.30603300E+02 0.98027277E+01 -0.17388163E+01 + 0.41459396E+02 0.21956772E+02 -0.74577127E+01 -0.57677418E+02 + 0.61015915E+02 -0.67599213E+02 -0.76322889E+01 0.15360656E+02 + -0.13954190E+02 -0.63971973E+02 -0.57594645E+00 0.46648544E+02 + 0.18534498E+02 -0.11813202E+01 0.14227716E+02 0.16818100E+02 + 0.80797073E+02 0.17325121E+03 -0.21808232E+03 -0.25066269E+02 + 0.77090273E+01 0.19229858E+02 -0.16147858E+02 -0.21793213E+02 + 0.11739251E+02 0.27427473E+01 -0.23950104E+02 -0.14955988E+01 + -0.43279028E+01 0.23412643E+02 0.63171875E+02 -0.99681198E+02 + 0.62766193E+02 -0.79878149E+01 -0.30435438E+02 0.21497587E+02 + 0.20054749E+02 0.38359371E+02 0.92688770E+01 0.10108423E+02 + 0.14417061E+02 -0.20493574E+01 0.14545422E+03 -0.31993137E+03 + 0.20626822E+03 -0.59260864E+02 -0.98615196E+02 -0.91029177E+01 + -0.61238266E+02 0.69641464E+02 -0.53348751E+01 0.55038424E+01 + -0.10444603E+03 -0.51997681E+02 0.24604843E+02 0.17732973E+03 + -0.14906340E+03 0.97182144E+02 0.28640444E+02 -0.17308901E+02 + 0.45831375E+02 0.16195528E+03 -0.62566643E+01 -0.10428041E+03 + -0.45196335E+02 0.11912195E+02 -0.28687086E+02 -0.28267487E+02 + -0.71918915E+02 -0.20264278E+03 0.37785229E+03 0.43567062E+02 + -0.15192982E+02 -0.31795990E+02 0.19159103E+02 0.24578566E+02 + -0.10395301E+02 -0.54584179E+01 0.29443466E+02 0.18643064E+01 + 0.73603711E+01 -0.46939163E+02 -0.19401112E+03 0.19549149E+03 + -0.98742599E+02 0.65470681E+01 0.41411484E+02 -0.23003342E+02 + -0.32262772E+02 -0.48849609E+02 -0.63948107E+01 -0.14122623E+02 + -0.15711076E+02 0.33360176E+01 -0.20310934E+03 0.43382687E+03 + -0.22873074E+03 0.61049896E+02 0.15113927E+03 0.12178139E+02 + 0.69404495E+02 -0.76307922E+02 -0.99914227E+01 -0.87610989E+01 + 0.11714095E+03 0.56842529E+02 -0.31153521E+02 -0.20313606E+03 + 0.19473549E+03 -0.81566391E+02 -0.31190519E+02 0.46536427E+01 + -0.60174667E+02 -0.17905360E+03 0.15700249E+02 0.10812028E+03 + 0.48076645E+02 -0.19411180E+02 0.28377899E+02 0.18879486E+02 + 0.18400131E+02 0.92124527E+02 -0.19595229E+03 -0.22818571E+02 + 0.91224928E+01 0.16459473E+02 -0.86445189E+01 -0.10113223E+02 + 0.36470232E+01 0.31096523E+01 -0.12310072E+02 -0.65811318E+00 + -0.39445655E+01 0.27785625E+02 0.12070576E+03 -0.10845207E+03 + 0.50968777E+02 0.20172386E+01 -0.18991880E+02 0.84511404E+01 + 0.16190018E+02 0.21269348E+02 0.98832005E+00 0.67662487E+01 + 0.63501005E+01 -0.22222321E+01 0.10348282E+03 -0.20003770E+03 + 0.10056244E+03 -0.24191299E+02 -0.75550995E+02 -0.66165800E+01 + -0.28941284E+02 0.32210007E+02 0.89458332E+01 0.52425108E+01 + -0.48151108E+02 -0.23473757E+02 0.13704450E+02 0.76933624E+02 + -0.97199905E+02 0.34218754E+02 0.94315853E+01 -0.39759985E+00 + 0.27437757E+02 0.72066147E+02 -0.95865564E+01 -0.42264877E+02 + -0.18651276E+02 0.93191538E+01 -0.11183517E+02 -0.35364711E+01 + 0.97871006E-01 0.20281778E+00 0.90489745E-01 -0.95290929E+00 + -0.27933317E+00 0.52461397E-01 0.72199441E-02 0.15705127E-01 + 0.41039664E-01 -0.36827065E-01 -0.15596762E-01 -0.21006119E-01 + -0.74302871E-03 0.18413860E+00 -0.22145296E-01 -0.21845268E-01 + 0.28004026E+00 -0.71528935E+00 -0.12112074E-01 -0.43858774E-02 + -0.32223654E-02 -0.29513296E-02 -0.20680975E-01 -0.50281626E-02 + -0.97669251E-02 0.16754761E-01 -0.50228141E-01 0.86401850E+00 + 0.37329835E+00 -0.43455347E-01 -0.37337756E+00 0.31667173E-01 + -0.33294797E+00 0.19361351E+00 -0.14481425E+00 0.17382687E+00 + -0.27535016E-01 -0.52372944E-01 0.51665079E-01 0.77041346E+00 + -0.10802412E+00 0.78209734E+00 0.82496119E+00 -0.11585003E+00 + -0.95668077E-01 0.54860026E-01 0.16625005E+00 -0.91622949E-01 + -0.65615296E-01 0.60415338E-03 0.15374319E+00 0.46706025E-01 + 0.54401726E+00 -0.93265295E+00 -0.56378663E+00 0.10645507E+02 + 0.57229429E+00 -0.12630768E+01 -0.64789844E+00 -0.60353720E+00 + -0.18424869E+00 0.13993631E+00 0.48576195E-01 0.22784837E+00 + -0.42130151E+00 0.27307934E+00 0.10153093E+01 0.11288967E+01 + -0.25885277E+01 0.76768193E+01 0.73958021E+00 0.39947239E+00 + -0.11303549E+01 0.74285984E+00 0.42960650E+00 -0.46359380E-02 + 0.57497424E+00 -0.24941254E+00 -0.27576047E+00 -0.49189272E+01 + -0.30248425E+01 0.82247725E+01 -0.40766191E+01 0.37377691E+00 + 0.15920105E+01 -0.10867130E+01 0.17805320E+01 -0.15497741E+01 + 0.73062027E+00 0.45829795E-01 0.16331393E+00 -0.90494804E+01 + -0.15745068E+00 -0.52452645E+01 -0.91057485E+00 0.86765213E+01 + 0.23413999E+01 -0.92353117E+00 -0.28763181E+00 0.22783265E-01 + -0.82801867E+00 -0.28931600E+00 -0.10174732E+01 0.16624612E+00 + -0.10378918E+02 0.58001833E+01 -0.22736099E+00 -0.23410551E+02 + 0.69524846E+01 0.71683698E+01 0.60270033E+01 0.22774773E+01 + 0.14830399E+01 0.16389122E+01 -0.30775643E-02 -0.78709882E+00 + 0.30579996E+01 -0.15465742E-02 -0.94203407E+00 -0.70205545E+01 + 0.62845592E+01 -0.72446785E+01 -0.44833164E+01 -0.13172770E+01 + 0.54477391E+01 -0.26917973E+01 -0.22063322E+01 0.88429081E+00 + -0.25067616E+01 0.70779270E+00 -0.41653013E+00 0.77432489E+01 + 0.44009705E+01 -0.26288897E+02 0.11670719E+02 -0.90083337E+00 + -0.26713228E+01 0.27358818E+01 -0.44873123E+01 0.38639853E+01 + -0.20221062E+01 0.50795317E+00 -0.10303020E+01 0.25454910E+02 + -0.35198113E+00 0.91766758E+01 0.36100191E+00 -0.26752716E+02 + -0.79657874E+01 0.40400887E+01 -0.13829774E+00 0.47660893E+00 + 0.37345991E+01 0.49525356E+00 0.16495342E+01 -0.32004577E+00 + 0.26923616E+02 -0.12705561E+02 0.77154822E+01 0.47243567E+01 + -0.21181992E+02 -0.15098258E+02 -0.13009449E+02 -0.24404039E+01 + -0.28010445E+01 -0.60208445E+01 -0.58497292E+00 0.13716582E+01 + -0.60833511E+01 -0.75704546E+01 -0.52916560E+01 0.16575651E+02 + -0.68116527E+01 -0.28722122E+02 0.83101597E+01 0.55782187E+00 + -0.92281694E+01 0.28159809E+01 0.46327085E+01 -0.30307541E+01 + 0.37459199E+01 -0.88170338E+00 0.22301374E+00 -0.31962299E+01 + -0.10003721E+01 0.17513151E+02 -0.10250561E+02 0.30598539E+00 + 0.16885279E+01 -0.19954594E+01 0.31069326E+01 -0.28071928E+01 + 0.13887663E+01 -0.67095476E+00 0.10415516E+01 -0.20710800E+02 + 0.89437598E+00 -0.42360601E+01 0.20117788E+01 0.17224686E+02 + 0.66144190E+01 -0.45690050E+01 -0.18276888E+00 -0.40452820E+00 + -0.32121382E+01 -0.92587352E-01 -0.48688596E+00 -0.14324802E+00 + -0.18712112E+02 0.78072858E+01 -0.87452765E+01 0.12498963E+02 + 0.17300508E+02 0.10375721E+02 0.82283955E+01 0.58782387E+00 + 0.11830969E+01 0.48081846E+01 0.77937979E+00 -0.73815536E+00 + 0.35488701E+01 0.98545418E+01 0.57349968E+01 -0.14113447E+02 + 0.14990282E+01 0.34328522E+02 -0.51231575E+01 0.11489592E+01 + 0.57513080E+01 -0.11141500E+01 -0.30930834E+01 0.25668888E+01 + -0.20892143E+01 0.63647670E+00 -0.29918632E-01 0.19186276E+00 + -0.70395470E-01 -0.77080011E-01 0.31567018E-01 -0.38534537E+00 + -0.50261641E+00 -0.21860758E-01 0.62904477E-01 -0.54080826E-02 + -0.92705972E-02 -0.40175516E-01 -0.11157576E-01 0.72898686E-01 + -0.50168097E-01 -0.10570348E+00 -0.67150486E-02 -0.14133672E+00 + 0.50753140E+00 -0.42581898E+00 -0.46848822E-01 0.22408159E-02 + 0.83338544E-02 0.41946094E-02 -0.58955322E-02 -0.26281827E-03 + -0.26040107E+00 0.76159227E+00 0.23537504E-01 -0.80746651E-01 + -0.17011432E+00 0.11547458E+00 -0.15361232E+00 0.17724210E+00 + 0.76225460E-01 -0.13381563E-01 -0.60893372E-02 -0.11518115E+00 + -0.31129288E-01 -0.51667415E-01 -0.24441698E+00 -0.31773394E+00 + 0.81835270E-01 -0.46549353E+00 0.17142838E+00 0.30523729E+00 + -0.57707924E-01 -0.20797607E-01 -0.15126068E-01 -0.33176009E-01 + -0.42346753E-01 -0.11050798E-01 0.59186462E-01 -0.11252823E+01 + 0.44319233E+00 -0.11809951E+00 -0.14963281E+00 0.52666683E-01 + -0.52684325E+00 -0.40326196E+00 0.12269676E+00 0.28846711E+00 + 0.12978292E+00 0.32258499E+00 -0.14862967E+00 -0.80570710E+00 + 0.17221977E+01 0.46162105E+00 -0.34327608E+00 0.13253001E+01 + 0.44412488E+00 0.28846556E+00 -0.34307167E+00 -0.36704320E+00 + 0.56617558E-01 0.18177402E+00 0.25099778E+00 -0.99185109E-01 + -0.19901596E+00 -0.17126940E+01 0.37629980E+00 0.45409292E+00 + 0.27510107E+00 0.15234835E-01 0.65682179E+00 -0.45590812E+00 + -0.21512812E+00 0.90877235E-01 -0.33986196E-01 0.28594887E+00 + 0.92194855E-01 -0.24209812E+00 0.65725392E+00 0.75583166E+00 + -0.39450559E+00 0.12069464E+01 -0.75257272E+00 -0.52532125E+00 + 0.99424243E-01 0.93963981E-01 0.45424551E-02 0.14965153E+00 + 0.19529074E+00 0.89346766E-01 0.76194298E+00 0.21998911E+01 + -0.61996317E+00 0.38401401E+00 0.65990424E+00 0.10685673E+01 + 0.16874924E+01 0.10111742E+01 -0.47734889E+00 -0.55955148E+00 + -0.36574561E-01 -0.54719484E+00 0.21022721E+00 0.96725518E+00 + -0.21709862E+01 -0.58654189E+00 0.52371085E-01 -0.19939440E+01 + -0.13083380E+01 0.97265768E+00 0.10472490E+01 0.79788142E+00 + -0.23003297E+00 -0.31732583E+00 -0.59758753E+00 0.17752629E-01 + -0.48324671E-01 -0.39871577E-01 0.35558343E-02 -0.26979163E-01 + 0.43359701E-01 0.12917670E-01 0.17010417E-01 0.27531302E+00 + -0.38564362E-01 -0.34878929E-02 -0.61485842E-02 -0.97274072E-02 + -0.18774368E-01 0.92524946E-01 -0.57997428E-01 0.36104076E-01 + 0.66196680E-01 -0.40818255E-01 0.68578762E-02 0.56706853E-02 + 0.14657996E-01 0.25169230E+00 0.17018355E-01 -0.13085435E-02 + 0.40550670E-03 -0.75565805E-02 -0.27891764E-01 -0.61812479E-01 + -0.66995502E-01 0.60951103E-01 -0.16235439E+00 -0.18117537E+00 + -0.63722014E-01 0.19130240E+00 0.34930456E+00 0.10013779E-03 + -0.18040525E-01 0.93262084E-02 0.29071178E-01 0.37352061E+00 + 0.23084080E+00 -0.11973948E+00 0.39940476E-01 0.16606478E+00 + -0.25743231E-01 -0.50882917E-01 -0.38867259E+00 0.90072393E-01 + -0.18342920E-01 -0.16830478E-01 0.65812240E-02 -0.11528601E-01 + -0.17556232E+00 -0.39191529E-01 0.14456748E-01 -0.31045396E-01 + -0.29462799E-01 0.17225456E-02 0.81582479E-02 0.32372475E-01 + -0.37683394E-01 0.90681970E-01 0.16984078E+00 -0.56379475E-02 + -0.16191300E-01 0.32786494E-02 0.13823363E-01 -0.58228843E-01 + 0.46045274E-01 -0.32285947E-01 -0.29173903E-01 -0.13254939E-02 + 0.33482354E-01 0.14193524E-01 -0.18655914E+00 0.75768769E-01 + 0.28235953E-01 -0.12667626E-01 -0.63085556E-01 -0.16578861E-01 + -0.65637641E-02 0.90851039E-02 -0.29999416E-01 0.40609591E-01 + -0.12365531E-01 0.32348711E-01 0.48897560E-02 -0.33822318E-02 + -0.95927678E-02 -0.10472466E+00 -0.49497220E-02 0.13566672E-01 + 0.51126848E-02 0.69563393E-02 0.21742020E-01 0.64151824E-01 + -0.15110991E-01 -0.11155132E-01 -0.23500491E-02 -0.49487539E-02 + -0.34136429E-01 -0.13634215E-01 -0.51828255E-02 -0.11964959E+00 + 0.16280919E-01 -0.15323649E-01 0.11045884E-01 0.15388856E-01 + 0.71778144E-02 0.13341841E-01 0.86160116E-02 0.35415869E-01 + 0.20430245E-01 -0.12541118E-01 0.64188945E-02 0.69954544E-02 + 0.14519761E-01 0.26640084E-01 -0.81357181E-01 -0.82582474E-01 + 0.33618689E-02 -0.22538288E-01 -0.19978171E-01 0.16238064E-01 + -0.12985624E-01 0.16977180E-01 -0.14756378E-01 -0.48074991E-03 + 0.21765309E-02 0.14442622E-01 0.29858343E-01 0