Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • orekit/rugged
  • sdinot/rugged
  • yzokras/rugged
  • youngcle/rugged-mod
4 results
Show changes
Showing
with 2527 additions and 406 deletions
# no Digital Elevation Model data for point {0}, {1}
NO_DEM_DATA_FOR_POINT = no Digital Elevation Model data for point {0}, {1}
# error parsing file {0}: {1}
ERROR_PARSING_FILE = error parsing file {0}: {1}
# missing pixel scale GeoTIFF tag in file {0}
MISSING_PIXEL_SCALE = missing pixel scale GeoTIFF tag in file {0}
# missing tie point GeoTIFF tag in file {0}
MISSING_TIE_POINT = missing tie point GeoTIFF tag in file {0}
# unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})
UNSUPPORTED_GEOTIFF_VERSION = unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})
# unable to retrieve value for key {0} in file {1}
UNABLE_TO_RETRIEVE_VALUE_FOR_KEY = unable to retrieve value for key {0} in file {1}
# unexpected GeoTIFF key {0} in file {1}
UNEXPECTED_GEOKEY = unexpected GeoTIFF key {0} in file {1}
# GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})
UNEXPECTED_GEOKEY_VALUE = GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})
# no Digital Elevation Model data for point {0}, {1}
NO_DEM_DATA_FOR_POINT = pas de données de Modèle Numérique de Terrain pour le point {0}, {1}
# error parsing file {0}: {1}
ERROR_PARSING_FILE = erreur lors de l''analyse du fichier {0} : {1}
# missing pixel scale GeoTIFF tag in file {0}
MISSING_PIXEL_SCALE = méta-donnée « pixel scale » GeoTIFF manquante dans le fichier {0}
# missing tie point GeoTIFF tag in file {0}
MISSING_TIE_POINT = méta-donnée « tie point » GeoTIFF manquante dans le fichier {0}
# unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})
UNSUPPORTED_GEOTIFF_VERSION = version GeoTIFF {0}/{1}.{2} du fichier {3} non prise en compte (version attendue : {4}/{5}.{6})
# unable to retrieve value for key {0} in file {1}
UNABLE_TO_RETRIEVE_VALUE_FOR_KEY = impossible de récupérer la valeur pour le clef {0} dans le fichier {1}
# unexpected GeoTIFF key {0} in file {1}
UNEXPECTED_GEOKEY = clef GeoTIFF {0} inattendue dans le fichier {1}
# GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})
UNEXPECTED_GEOKEY_VALUE = la clef GeoTIFF {0} du fichier {1} a la valeur inattendue {2} (valeur attendue : {3})
/* Copyright 2002-2014 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.rugged.geotiff;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
import org.junit.Assert;
import org.junit.Test;
public class AsterMessagesTest {
@Test
public void testMessageNumber() {
Assert.assertEquals(8, AsterMessages.values().length);
}
@Test
public void testAllKeysPresentInPropertiesFiles() {
for (final String language : new String[] { "en", "fr" } ) {
ResourceBundle bundle =
ResourceBundle.getBundle("assets/org/orekit/rugged/AsterMessages",
new Locale(language), new AsterMessages.UTF8Control());
for (AsterMessages message : AsterMessages.values()) {
final String messageKey = message.toString();
boolean keyPresent = false;
for (final Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) {
keyPresent |= messageKey.equals(keys.nextElement());
}
Assert.assertTrue("missing key \"" + message.name() + "\" for language " + language,
keyPresent);
}
Assert.assertEquals(language, bundle.getLocale().getLanguage());
}
}
@Test
public void testAllPropertiesCorrespondToKeys() {
for (final String language : new String[] { "en", "fr" } ) {
ResourceBundle bundle =
ResourceBundle.getBundle("assets/org/orekit/rugged/AsterMessages",
new Locale(language), new AsterMessages.UTF8Control());
for (final Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) {
final String propertyKey = keys.nextElement();
try {
Assert.assertNotNull(AsterMessages.valueOf(propertyKey));
} catch (IllegalArgumentException iae) {
Assert.fail("unknown key \"" + propertyKey + "\" in language " + language);
}
}
Assert.assertEquals(language, bundle.getLocale().getLanguage());
}
}
@Test
public void testNoMissingFrenchTranslation() {
for (AsterMessages message : AsterMessages.values()) {
String translated = message.getLocalizedString(Locale.FRENCH);
Assert.assertFalse(message.name(), translated.toLowerCase().contains("missing translation"));
}
}
@Test
public void testNoOpEnglishTranslation() {
for (AsterMessages message : AsterMessages.values()) {
String translated = message.getLocalizedString(Locale.ENGLISH);
Assert.assertEquals(message.getSourceString(), translated);
}
}
@Test
public void testVariablePartsConsistency() {
for (final String language : new String[] { "en", "fr" } ) {
Locale locale = new Locale(language);
for (AsterMessages message : AsterMessages.values()) {
MessageFormat source = new MessageFormat(message.getSourceString());
MessageFormat translated = new MessageFormat(message.getLocalizedString(locale));
Assert.assertEquals(message.name() + " (" + language + ")",
source.getFormatsByArgumentIndex().length,
translated.getFormatsByArgumentIndex().length);
}
}
}
}
/* Copyright 2013-2014 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.rugged.geotiff;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.math3.util.FastMath;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.orekit.rugged.api.RuggedException;
import org.orekit.rugged.core.raster.SimpleTile;
import org.orekit.rugged.core.raster.SimpleTileFactory;
import org.orekit.rugged.core.raster.TileFactory;
public class AsterTileUpdaterTest {
@Test
public void testAster() throws RuggedException {
File folder = warningFile.getParentFile();
List<int[]> corners = getCorners(folder);
if (corners.isEmpty()) {
// no ASTER data available in the test resources
// warn user, but don't allow the test to fail
displayWarning();
} else {
TileFactory<SimpleTile> factory = new SimpleTileFactory();
AsterTileUpdater updater = new AsterTileUpdater(folder);
for (int[] corner : corners) {
SimpleTile tile = factory.createTile();
updater.updateTile(FastMath.toRadians(corner[0] + 0.2),
FastMath.toRadians(corner[1] + 0.7),
tile);
tile.tileUpdateCompleted();
Assert.assertEquals(corner[0] + 1.0 / 7200.0, FastMath.toDegrees(tile.getMinimumLatitude()), 1.0e-10);
Assert.assertEquals(corner[1] - 1.0 / 7200.0, FastMath.toDegrees(tile.getMinimumLongitude()), 1.0e-10);
Assert.assertEquals(1.0 / 3600.0, FastMath.toDegrees(tile.getLatitudeStep()), 1.0e-10);
Assert.assertEquals(1.0 / 3600.0, FastMath.toDegrees(tile.getLongitudeStep()), 1.0e-10);
Assert.assertTrue(tile.getMinElevation() < 9000.0);
Assert.assertTrue(tile.getMaxElevation() > -1000.0);
}
}
}
@Before
public void setUp() {
try {
String warningResource = "org/orekit/rugged/geotiff/ASTER-files-warning.txt";
URL url = AsterTileUpdaterTest.class.getClassLoader().getResource(warningResource);
warningFile = new File(url.toURI().getPath());
} catch (URISyntaxException urise) {
Assert.fail(urise.getLocalizedMessage());
}
}
private List<int[]> getCorners(File folder) {
Pattern patter = Pattern.compile("ASTGTM2_([NS]\\d\\d)([EW]\\d\\d\\d)\\.zip$");
List<int[]> asterCorners = new ArrayList<int[]>();
for (final File file : folder.listFiles()) {
Matcher matcher = patter.matcher(file.getName());
if (matcher.matches()) {
int latCode = (matcher.group(1).startsWith("N") ? 1 : -1) * Integer.parseInt(matcher.group(1).substring(1));
int lonCode = (matcher.group(2).startsWith("E") ? 1 : -1) * Integer.parseInt(matcher.group(2).substring(1));
asterCorners.add(new int[] { latCode, lonCode });
}
}
return asterCorners;
}
private void displayWarning() {
try {
System.err.println("###### " + warningFile.getAbsolutePath() + " ######");
BufferedReader reader = new BufferedReader(new FileReader(warningFile));
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
System.err.println(line);
}
reader.close();
System.err.println("###### " + warningFile.getAbsolutePath() + " ######");
} catch (IOException ioe) {
Assert.fail(ioe.getLocalizedMessage());
}
}
private File warningFile;
}
For test purposes, some ASTER files should be put in the same folder as this file.
ASTER stands for Advanced Spaceborne Thermal Emission and Reflection Radiometer
and is a joint effort of the Ministry of Economy, Trade, and Industry (METI) of
Japan and the United States National Aeronautics and Space Administration (NASA).
More information on how to get the files is available here:
http://asterweb.jpl.nasa.gov/gdem.asp
The Rugged library cannot distribute such test files, so the distributed folder
contains only this warning text file and no real ASTER files. If the folder still does
not contain any ASTER files at tests run time, the content of this file is displayed
as a warning but the tests won't fail.
If users want to really perform tests, they have to retrieve ASTER files by themselves
and copy them in the folder. Then the files will automatically been picked up and used
for the tests. The files must have a name of the form ASTGTM2_v##h###.zip, where v
stands for either N or S, h stands for either E or W and # stands for digits. The zip
files themselves are used for the tests, users should not extract the _dem.tif files.
This diff is collapsed.
<?xml version="1.0"?>
<!--
This file contains some false positive bugs detected by spotbugs. Their
false positive nature has been analyzed individually and they have been
put here to instruct findbugs it must ignore them.
-->
<FindBugsFilter>
<!-- The following internal representation exposure are intentional,
They are used to pass data back and forth between classes
-->
<Match>
<Class name="org.orekit.rugged.adjustment.AdjustmentContext"/>
<Method name="&lt;init>"
params="java.util.Collection,
org.orekit.rugged.adjustment.measurements.Observables"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.adjustment.GroundOptimizationProblemBuilder"/>
<Method name="&lt;init>"
params="java.util.List,org.orekit.rugged.adjustment.measurements.Observables,
org.orekit.rugged.api.Rugged"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.adjustment.measurements.SensorToSensorMapping"/>
<Or>
<Method name="getBodyDistances"
params=""
returns="java.util.List" />
<Method name="getLosDistances"
params=""
returns="java.util.List" />
</Or>
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.api.Rugged"/>
<Or>
<Method name="getEllipsoid"
params=""
returns="org.orekit.rugged.utils.ExtendedEllipsoid" />
<Method name="getRefractionCorrection"
params=""
returns="org.orekit.rugged.refraction.AtmosphericRefraction" />
</Or>
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.api.RuggedBuilder"/>
<Or>
<Method name="getEllipsoid"
params=""
returns="org.orekit.rugged.utils.ExtendedEllipsoid" />
<Method name="getPositionsVelocities"
params=""
returns="java.util.List" />
<Method name="getQuaternions"
params=""
returns="java.util.List" />
<Method name="getRefractionCorrection"
params=""
returns="org.orekit.rugged.refraction.AtmosphericRefraction" />
</Or>
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.api.RuggedBuilder"/>
<Or>
<Method name="setRefractionCorrection"
params="org.orekit.rugged.refraction.AtmosphericRefraction"
returns="org.orekit.rugged.api.RuggedBuilder" />
<Method name="setTrajectory"
params="double,
int,
org.orekit.utils.CartesianDerivativesFilter,
org.orekit.utils.AngularDerivativesFilter,
org.orekit.propagation.Propagator"
returns="org.orekit.rugged.api.RuggedBuilder" />
<Method name="setTrajectory"
params="org.orekit.frames.Frame,
java.util.List,
int,
org.orekit.utils.CartesianDerivativesFilter,
java.util.List,
int,
org.orekit.utils.AngularDerivativesFilter"
returns="org.orekit.rugged.api.RuggedBuilder" />
</Or>
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.errors.RuggedExceptionWrapper"/>
<Method name="getException"
params=""
returns="org.orekit.rugged.errors.RuggedException" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.errors.RuggedExceptionWrapper"/>
<Method name="&lt;init>"
params="org.orekit.rugged.errors.RuggedException"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.linesensor.LineSensor"/>
<Method name="getPosition"
params=""
returns="org.hipparchus.geometry.euclidean.threed.Vector3D" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.linesensor.LineSensor"/>
<Method name="&lt;init>"
params="java.lang.String,
org.orekit.rugged.linesensor.LineDatation,
org.hipparchus.geometry.euclidean.threed.Vector3D,
org.orekit.rugged.los.TimeDependentLOS"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.linesensor.SensorMeanPlaneCrossing"/>
<Method name="getMeanPlaneNormal"
params=""
returns="org.hipparchus.geometry.euclidean.threed.Vector3D" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.linesensor.SensorMeanPlaneCrossing"/>
<Method name="&lt;init>"
params="org.orekit.rugged.linesensor.LineSensor,
org.orekit.rugged.utils.SpacecraftToObservedBody,
int,
int,
boolean,
boolean,
int,
double,
org.hipparchus.geometry.euclidean.threed.Vector3D,
java.util.stream.Stream"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.linesensor.SensorMeanPlaneCrossing$CrossingResult"/>
<Or>
<Method name="getTarget"
params=""
returns="org.hipparchus.geometry.euclidean.threed.Vector3D" />
<Method name="getTargetDirection"
params=""
returns="org.hipparchus.geometry.euclidean.threed.Vector3D" />
<Method name="getTargetDirectionDerivative"
params=""
returns="org.hipparchus.geometry.euclidean.threed.Vector3D" />
</Or>
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.linesensor.SensorMeanPlaneCrossing$CrossingResult"/>
<Method name="&lt;init>"
params="org.orekit.time.AbsoluteDate,
double,
org.hipparchus.geometry.euclidean.threed.Vector3D,
org.hipparchus.geometry.euclidean.threed.Vector3D,
org.hipparchus.geometry.euclidean.threed.Vector3D"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.los.FixedRotation"/>
<Method name="&lt;init>"
params="java.lang.String,
org.hipparchus.geometry.euclidean.threed.Vector3D,double"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.los.LOSBuilder"/>
<Method name="&lt;init>"
params="java.util.List"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.los.PolynomialRotation"/>
<Method name="&lt;init>"
params="java.lang.String,
org.hipparchus.geometry.euclidean.threed.Vector3D,
org.orekit.time.AbsoluteDate,
double[]"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.refraction.AtmosphericRefraction"/>
<Method name="getComputationParameters"
params=""
returns="org.orekit.rugged.refraction.AtmosphericComputationParameters" />
<Bug pattern="EI_EXPOSE_REP" />
</Match>
<Match>
<Class name="org.orekit.rugged.refraction.MultiLayerModel"/>
<Or>
<Method name="&lt;init>"
params="org.orekit.rugged.utils.ExtendedEllipsoid"
returns="void" />
<Method name="&lt;init>"
params="org.orekit.rugged.utils.ExtendedEllipsoid,
java.util.List"
returns="void" />
</Or>
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.utils.RoughVisibilityEstimator"/>
<Method name="&lt;init>"
params="org.orekit.bodies.OneAxisEllipsoid,
org.orekit.frames.Frame,java.util.List"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
<Match>
<Class name="org.orekit.rugged.utils.SpacecraftToObservedBody"/>
<Method name="&lt;init>"
params="org.orekit.frames.Frame,
org.orekit.frames.Frame,
org.orekit.time.AbsoluteDate,
org.orekit.time.AbsoluteDate,
double,
double,
java.util.List,
java.util.List"
returns="void" />
<Bug pattern="EI_EXPOSE_REP2" />
</Match>
</FindBugsFilter>
This diff is collapsed.
' Copyright 2013-2014 CS Systèmes d'Information
' Licensed to CS Systèmes d'Information (CS) under one or more
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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
......@@ -25,40 +25,53 @@
skinparam NoteFontColor #691616
skinparam ClassFontSize 11
package fr.cs.rugged #ECEBD8
package org.orekit.rugged #ECEBD8 {
package api #DDEBD8
package raster #DDEBD8 {
interface UpdatableTile {
+setGeometry(φref, λref, δφ, δλ, rows, columns)
+setGeometry(φ₀, λ₀, δφ, δλ, rows, columns)
+setElevation(i, j, h)
}
interface TileUpdater {
+updateTile(φ, λ, UpdatableTile)
}
UpdatableTile <-- TileUpdater : updates
end package
TileUpdater --> UpdatableTile : updates
package dem #DDEBD8
interface Tile
class SpecializedTile
interface "TileFactory<T extends Tile>" as TileFactory_T_ {
+T createTile()
}
class "TilesCache<T extends Tile>" as TilesCache_T_ {
+ T getTile(φ, λ)
}
Tile --|> UpdatableTile
Tile <|-- SpecializedTile
SpecializedTile "*" <--o "1" TilesCache_T_
TileUpdater "1" <--o "1" TilesCache_T_ : triggers
TileFactory_T_ "1" <--o "1" TilesCache_T_ : triggers
TileFactory_T_ --> SpecializedTile : creates
end package
interface Tile {
+ double interpolateElevation(φ, λ)
}
UpdatableTile <|.. Tile
Tile <|-- SimpleTile
TilesCache_T_ "1" o--> "*" Tile
TilesCache_T_ "1" o--> "1" TileUpdater : triggers
TilesCache_T_ "1" o--> "1" TileFactory_T_ : triggers
}
package intersection.duvenhage #DDEBD8 {
TileFactory_T_ <|-- MinMaxTreeTileFactory
SimpleTile <|-- MinMaxTreeTile
MinMaxTreeTileFactory -left-> MinMaxTreeTile : creates
note left
tile extended with Duvenhage
specific min/max kd-tree
end note
}
end package
}
package specific.interface #ECEBD8
package mission.specific #C4D2C5 {
class MissionSpecificDEM #D5E0D5/E2EBE2
TileUpdater <|-- MissionSpecificDEM
end package
note top #E2EBE2
user provides DEM loading
by implementing TileUpdater
end note
}
@enduml
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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.
@startuml
skinparam svek true
skinparam ClassBackgroundColor #F3EFEB/CCC9C5
skinparam ClassArrowColor #691616
skinparam ClassBorderColor #691616
skinparam NoteBackgroundColor #F3EFEB
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam ClassFontSize 11
package rugged #ECEBD8 {
package raster #DDEBD8 {
interface Tile {
+interpolateElevation(φ, λ)
+pixelIntersection(NormalizedGeodeticPoint, los, φ index, λ index)
}
}
package intersection #DDEBD8 {
interface IntersectionAlgorithm {
+intersection(ellipsoid, position, los)
+refineIntersection(ellipsoid, position, los, closeGuess)
}
Tile <-- IntersectionAlgorithm : evaluate DEM
}
package utils #DDEBD8 {
class ExtendedEllipsoid {
+pointAtLatitude(position, los, φ, closereference)
+pointAtLongitude(position, los, λ)
+pointAtAltitude(position, los, h)
+pointOnGround(position, los)
}
class SpacecraftToObservedBody
IntersectionAlgorithm --> ExtendedEllipsoid : compute grid points crossings
}
package api #DDEBD8 {
class Rugged {
+directLocation(sensorName, line)
}
IntersectionAlgorithm "1" <--o Rugged : delegate DEM intersection
ExtendedEllipsoid <-- Rugged : convert geodetic points
SpacecraftToObservedBody <-- Rugged : convert positions/directions
}
package linesensor #DDEBD8 {
class LineSensor
Rugged --> LineSensor : getLOS(date, pixel)
Rugged --> LineSensor : getDate(line)
}
}
package mission.specific #C4D2C5 {
class UserMain #D5E0D5/E2EBE2
UserMain --> Rugged
}
@enduml
' Copyright 2013-2014 CS Systèmes d'Information
' Licensed to CS Systèmes d'Information (CS) under one or more
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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
......@@ -21,6 +21,7 @@
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam SequenceActorBorderColor #6A584B
skinparam SequenceActorBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBorderColor #6A584B
skinparam SequenceLifeLineBackgroundColor #CCC9C5/F3EFEB
......@@ -31,40 +32,61 @@
hide footbox
participant "Application" as A
participant "Interface" as I
actor "UserMain" as A
participant "Rugged" as R
participant "Orekit" as O
participant "LineSensor" as LS
participant "SpacecraftToObservedBody" as S
participant "ExtendedEllipsoid" as E
participant "IntersectionAlgorithm" as G
participant "Tile" as T
activate A
A -> I : directLocalization(line)
activate I
I -> R : directLocalization(line)
A -> R : directLocation(name, number)
activate R
R -> LS : apply time stamping model
R -> S : get transforms at line date
R -> R : loop over line pixels pₖ
activate R
R -> R : apply time stamping model
R -> R : apply combined transform provider at date
R -> R : loop over line pixels pₖ
activate R
R -> O : convert(line-of-sight)
activate O
O --> R : line-of-sight in Earth frame
deactivate O
R -> O : intersection(ellipsoid, line-of-sight)
activate O
O --> R : geodetic point
deactivate O
R -> R : DEM intersection
activate R
R -> I : DEM callback
I --> R : DEM raw data cell
R --> R : φₖ, λₖ, hₖ
deactivate R
R --> R : list(φₖ, λₖ, hₖ)
deactivate R
R --> I : list(φₖ, λₖ, hₖ)
R -> R : fix aberration of light
R -> E : approximate point on ground
R -> R : fix speed of light delay in transforms
R -> G : intersection(ellipsoid, line-of-sight)
activate G
G -> E : grid points crossings
G -> T : elevation(φₖ, λₖ)
activate T
T -> A : DEM callback
A --> T : DEM raw data cell
T --> G : h(φₖ, λₖ)
deactivate T
G -> E : grid points crossings
G -> T : elevation(φₖ, λₖ)
activate T
T --> G : h(φₖ, λₖ)
deactivate T
G -> E : grid points crossings
G -> T : elevation(φₖ, λₖ)
activate T
T --> G : h(φₖ, λₖ)
deactivate T
G -> T : pixel intersection(los)
activate T
T --> G : φₖ, λₖ, hₖ
deactivate T
G --> R : φₖ, λₖ, hₖ
deactivate G
R -> R : refine speed of light delay in transforms
R -> G : refine intersection(ellipsoid, line-of-sight)
activate G
G -> T : refine pixel intersection(los)
activate T
T --> G : φₖ, λₖ, hₖ
deactivate T
deactivate G
R --> R : array(φₖ, λₖ, hₖ)
deactivate R
I --> A : list(φₖ, λₖ, hₖ)
deactivate I
R --> A : array(φₖ, λₖ, hₖ)
deactivate R
deactivate A
@enduml
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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.
@startuml
skinparam svek true
skinparam NoteBackgroundColor #F3EFEB
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam ActivityStartColor #6A584B
skinparam ActivityEndColor #6A584B
skinparam ActivityBarColor #6A584B
skinparam ActivityBorderColor #691616
skinparam ActivityBackgroundColor #F3EFEB/CCC9C5
skinparam ActivityArrowColor #691616
skinparam ActivityFontSize 11
start
if (recursion depth > 30?) then (yes)
: search failed;
stop
endif
if (compare start and end point) then (same pixel)
: intersection ⇦ pixel intersection, with bilinear model;
: return intersection;
note left
this is the nominal return,
at final recursion level
end note
stop
endif
:compute kd-tree deepest\nlevel sub-tile containing\nboth segment endpoints;
if (compare segment and sub-tile maximum elevation) then (fully above)
: return null;
note left
when the line-of-sight segment is fully above
Digital Elevation Model, we can safely reject
it and proceed immediately to next segment
end note
stop
endif
:previous ⇦ start;
: crossings ⇦ line-of-sight segment crossings of next level sub-tiles;
note right
crossings can be computed either
using flat body hypothesis
or taking curvature into account
end note
repeat
:intersection ⇦ recurse(previous, crossing);
if (intersection found?) then (yes)
: return intersection;
stop
endif
:previous ⇦ crossing;
repeat while (more crossings?)
:intersection ⇦ recurse(previous, end);
: return intersection;
stop
@enduml
' Copyright 2013-2014 CS Systèmes d'Information
' Licensed to CS Systèmes d'Information (CS) under one or more
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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
......@@ -20,51 +20,53 @@
skinparam NoteBackgroundColor #F3EFEB
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam SequenceActorBorderColor #6A584B
skinparam SequenceParticipantBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBorderColor #6A584B
skinparam SequenceLifeLineBackgroundColor #CCC9C5/F3EFEB
skinparam SequenceLifeLineBorderColor #6A584B
skinparam SequenceArrowColor #6A584B
skinparam SequenceBorderColor #6A584B
skinparam SequenceFontSize 11
skinparam ActivityStartColor #6A584B
skinparam ActivityEndColor #6A584B
skinparam ActivityBarColor #6A584B
skinparam ActivityBorderColor #691616
skinparam ActivityBackgroundColor #F3EFEB/CCC9C5
skinparam ActivityArrowColor #691616
skinparam ActivityFontSize 11
hide footbox
participant "Application" as A
participant "Interface" as I
participant "Rugged" as R
participant "Orekit" as O
activate A
A -> I : init
activate I
I -> I : loadModels
I -> R : initiliaze(sensors, ephemeris)
activate R
R -> R : unfoldOpticalPath(sensors)
activate R
R -> O : composeTransforms
activate O
O --> R : sensors transforms
deactivate O
deactivate R
R -> O : createPropagator(ephemeris)
activate O
O --> R : interpolating propagator
deactivate O
R -> O : createTransformProvider(sensors transforms, propagator)
activate O
O --> R : combined TransformProvider with caching feature
deactivate O
deactivate R
I -> R : registerLineTimeStampingModel
activate R
deactivate R
I -> R : registerDEMCallback
activate R
deactivate R
deactivate I
deactivate A
start
: gp₀ ⇦ point at altitude 0;
: select tile containing gp₀;
: current point ⇦ null;
: hmax ⇦ tile maximum elevation;
while (current point is null)
: current ⇦ point at altitude hmax;
if (locate current point) then (in selected tile)
else (outside of selected tile)
: select tile containing current point;
: hmax ⇦ max(hmax, tile maximum elevation);
: current point ⇦ null;
endif
endwhile
repeat
: exit ⇦ line-of-sight exit point from tile;
: intersection ⇦ Duvenhage(current, exit);
if (intersection found?) then (yes)
: return intersection;
stop
endif
if (tile exit) then (bottom)
: searching ⇦ false;
else (side)
: forward point ⇦ point slightly after exit point;
: select tile containing forward point;
if (DEM traversed between\ncurrent and forward points?) then (yes)
: return current point;
note right
extremely rare case!
end note
stop
endif
: current point ⇦ forward point;
endif
repeat while (searching ?)
:search failed;
note left
this should never happen
end note
@enduml
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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.
@startuml
skinparam svek true
skinparam ClassBackgroundColor #F3EFEB/CCC9C5
skinparam ClassArrowColor #691616
skinparam ClassBorderColor #691616
skinparam NoteBackgroundColor #F3EFEB
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam ClassFontSize 11
package orekit #ECEBD8 {
class OneAxisEllipsoid
class PVCoordinatesProvider
class Frame
class AttitudeProvider
}
package mission.specific #C4D2C5 {
class UserMain #D5E0D5/E2EBE2
note top #E2EBE2
user configures Rugged either by
selecting from a few predefined
choices or by directly building
Orekit objects
end note
class MissionSpecificDEM #D5E0D5/E2EBE2
MissionSpecificDEM <-left- UserMain : creates
}
package rugged #ECEBD8 {
package utils #DDEBD8 {
class ExtendedEllipsoid
class SpacecraftToObservedBody
OneAxisEllipsoid <|-- ExtendedEllipsoid
Frame "2" <--o SpacecraftToObservedBody
PVCoordinatesProvider "1" <--o SpacecraftToObservedBody
AttitudeProvider "1" <--o SpacecraftToObservedBody
}
package raster #DDEBD8 {
interface TileUpdater
}
package api #DDEBD8 {
class Rugged {
+setLightTimeCorrection(boolean)
+setAberrationOfLightCorrection(boolean)
+addLineSensor(lineSensor)
}
enum AlgorithmId {
+DUVENHAGE
+DUVENHAGE_FLAT_BODY
+BASIC_SCAN
+IGNORE_DEM
}
enum EllipsoidId {
+GRS80
+WGS84
+IERS96
+IERS2003
}
enum BodyRotatingFrameId {
+ITRF
+ITRF_EQUINOX
+GTOD
}
enum InertialFrameId {
+GCRF
+EME2000
+MOD
+TOD
+VEIS1950
}
ExtendedEllipsoid "1" <--o Rugged
SpacecraftToObservedBody "1" <--o Rugged
Rugged --> AlgorithmId
Rugged --> EllipsoidId
Rugged --> BodyRotatingFrameId
Rugged --> InertialFrameId
MissionSpecificDEM --|> TileUpdater
UserMain --> Rugged : configures
}
package linesensor #DDEBD8 {
class LineSensor
Rugged o--> "*" LineSensor
UserMain --> LineSensor : creates
}
}
@enduml
' Copyright 2013-2014 CS Systèmes d'Information
' Licensed to CS Systèmes d'Information (CS) under one or more
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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
......@@ -21,6 +21,7 @@
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam SequenceActorBorderColor #6A584B
skinparam SequenceActorBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBorderColor #6A584B
skinparam SequenceLifeLineBackgroundColor #CCC9C5/F3EFEB
......@@ -31,27 +32,53 @@
hide footbox
participant "Caller" as C
actor "UserMain" as A
participant "MissionSpecificDEM" as B
participant "Rugged" as R
participant "ExtendedEllipsoid" as E
participant "SpacecraftToObservedBody" as S
participant "LineSensor" as LS
participant "Orekit" as O
activate C
C -> R : compute geometry at date
activate A
A -> A : loadModels
A -> B : create
activate B
deactivate B
A -> A : unfoldOpticalPath
activate A
deactivate A
A -> R : create(DEM, algorithm, frames, ellipsoid, ephemeris)
activate R
R -> O : interpolate(date)
R -> E : create
activate E
deactivate E
R -> O : createProviders(ephemeris)
activate O
O --> R : orbite/attitude
O --> R : position/velocity/atttitude providers
deactivate O
R -> O : getTransform(date)
activate O
O --> R : Earth to inertial transform
deactivate O
R -> O : compose transforms
activate O
O --> R : spacecraft to Earth transform
deactivate O
R --> C : spacecraft to Earth transform
R -> S : create
activate S
deactivate S
deactivate R
A -> LS : create
activate LS
deactivate LS
A -> R : addLineSensor
activate R
deactivate R
A -> LS : create
activate LS
deactivate LS
A -> R : addLineSensor
activate R
deactivate R
A -> LS : create
activate LS
deactivate LS
A -> R : addLineSensor
activate R
deactivate R
deactivate C
deactivate A
@enduml
' Copyright 2013-2014 CS Systèmes d'Information
' Licensed to CS Systèmes d'Information (CS) under one or more
' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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
......@@ -21,6 +21,7 @@
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam SequenceActorBorderColor #6A584B
skinparam SequenceActorBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBackgroundColor #F3EFEB/CCC9C5
skinparam SequenceParticipantBorderColor #6A584B
skinparam SequenceLifeLineBackgroundColor #CCC9C5/F3EFEB
......@@ -31,57 +32,66 @@
hide footbox
participant "Application" as A
participant "Interface" as I
actor "UserMain" as A
participant "Rugged" as R
participant "Orekit" as O
participant "SensorMeanPlaneCrossing" as P
participant "SensorPixelCrossing" as X
participant "SpacecraftToObservedBody" as S
participant "ExtendedEllipsoid" as E
participant "Transform" as T
participant "Math" as M
activate A
A -> I : inverseLocalization(φ, λ)
activate I
I -> R : inverseLocalization(φ, λ)
activate R
R -> R : elevation(φ, λ)
activate R
R -> I : DEM callback
I --> R : DEM raw data cell
R --> R : h(φ, λ)
deactivate R
R -> O : convert(ellipsoid, φ, λ, h)
activate O
O --> R : P(φ, λ, h) in Earth frame
deactivate O
R -> R : createSwathOffset(P, interpolator)
activate R
R --> R : function f(t)
deactivate R
R -> M : solve f(t₀) = 0
activate M
M --> R : evaluate f(t)
activate R
R -> R : apply combined transform provider at date
R --> M : f(t)
deactivate R
M --> R : evaluate f(t)
activate R
R -> R : apply combined transform provider at date
R --> M : f(t)
deactivate R
M --> R : evaluate f(t)
activate R
R -> R : apply combined transform provider at date
R --> M : f(t)
deactivate R
M --> R : t₀
deactivate M
R -> R : apply combined transform provider at date
R -> R : apply inverse time stamping model
R -> R : locate pixel in line for solved geometry
R --> I : pixel coordinates
deactivate R
I --> A : pixel coordinates
deactivate I
A -> R : inverseLocation
activate R
R -> P : getMeanPlaneFinder
activate P
P -> S : getTransform(each line)
note left
transforms are computed
only once and reused
across successive inverse
location calls
end note
activate S
S -> T : create
activate T
deactivate T
deactivate S
deactivate P
R -> E : transform(φ, λ, h)
activate E
E --> R : x, y, z
deactivate E
R -> P : findCrossing(ground target)
activate P
P -> T : interpolate
activate T
deactivate T
note left
algorithm converges
in 2 or 3 iterations
end note
P -> T : interpolate
activate T
deactivate T
P --> R : target direction at mean plane crossing\n(with time derivative)
deactivate P
R -> X : create(target direction at crossing time)
activate X
deactivate X
R -> X : locatePixel
activate X
X -> M : solve f(x) = 0
activate M
M --> X : x₀
deactivate M
X --> R : coarse pixel crossing
deactivate X
R -> R : fix line, considering closest pixel position
R -> R : fix pixel
R --> A : accurate line/pixel
deactivate R
deactivate A
@enduml
src/design/mayon-volcano.png

92.5 KiB

' Copyright 2013-2022 CS GROUP
' Licensed to CS GROUP (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.
@startuml
skinparam svek true
skinparam ClassBackgroundColor #F3EFEB/CCC9C5
skinparam ClassArrowColor #691616
skinparam ClassBorderColor #691616
skinparam NoteBackgroundColor #F3EFEB
skinparam NoteBorderColor #691616
skinparam NoteFontColor #691616
skinparam ClassFontSize 11
package org.orekit.rugged #ECEBD8 {
package utils #DDEBD8 {
interface ParametricModel {
+getNbEstimatedParameters()
+getEstimatedParameters(parameters, start, length)
+setEstimatedParameters(parameters, start, length)
}
enum ParameterType {
+FIXED
+ESTIMATED
}
}
package linesensor #DDEBD8 {
class LineSensor
}
package los #DDEBD8 {
interface TimeDependentLOS {
+getNbPixels()
+getLOS(index, date)
+getLOS(index, date, parameters)
}
interface LOSTransform {
+transformLOS(i, los, date)
}
interface TimeIndependentLOSTransform {
+transformLOS(i, los)
}
class LOSBuilder {
+LOSBuilder(List<Vector3D> rawLOS)
+LOSBuilder addTransform(TimeIndependentLOSTransform transform)
+LOSBuilder addTransform(LOSTransform transform)
+TimeDependentLOS build()
}
ParametricModel <|.. TimeDependentLOS
ParametricModel <|.. LOSTransform
ParametricModel <|.. TimeIndependentLOSTransform
PolynomialRotation --|> LOSTransform
ParameterType <--* PolynomialRotation
FixedRotation --|> TimeIndependentLOSTransform
ParameterType <--* FixedRotation
TimeDependentLOS <-- LOSBuilder : builds
TimeIndependentLOSTransform <-- LOSBuilder : combines
LOSTransform <-- LOSBuilder : combines
LineSensor "1" *--> TimeDependentLOS
}
}
package o.a.c.m.analysis.differentiation #C4D2C5 {
class DerivativeStructure #D5E0D5/E2EBE2 {
+getOrder()
+getValue()
+getPartialDerivatives(order1, order2, ...)
}
LOSTransform --> DerivativeStructure
TimeIndependentLOSTransform --> DerivativeStructure
}
@enduml
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.rugged.adjustment;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresOptimizer.Optimum;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;
import org.orekit.rugged.adjustment.measurements.Observables;
import org.orekit.rugged.api.Rugged;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.linesensor.LineSensor;
/** Create adjustment context for viewing model refining.
* @author Lucie LabatAllee
* @author Jonathan Guinet
* @author Luc Maisonobe
* @author Guylaine Prat
* @since 2.0
*/
public class AdjustmentContext {
/** List of Rugged instances to optimize. */
private final Map<String, Rugged> viewingModel;
/** Set of measurements. */
private final Observables measurements;
/** Least square optimizer choice.*/
private OptimizerId optimizerID;
/** Build a new instance.
* The default optimizer is Gauss Newton with QR decomposition.
* @param viewingModel viewing model
* @param measurements control and tie points
*/
public AdjustmentContext(final Collection<Rugged> viewingModel, final Observables measurements) {
this.viewingModel = new HashMap<String, Rugged>();
for (final Rugged r : viewingModel) {
this.viewingModel.put(r.getName(), r);
}
this.measurements = measurements;
this.optimizerID = OptimizerId.GAUSS_NEWTON_QR;
}
/** Setter for optimizer algorithm.
* @param optimizerId the chosen algorithm
*/
public void setOptimizer(final OptimizerId optimizerId)
{
this.optimizerID = optimizerId;
}
/**
* Estimate the free parameters in viewing model to match specified sensor
* to ground mappings.
* <p>
* This method is typically used for calibration of on-board sensor
* parameters, like rotation angles polynomial coefficients.
* </p>
* <p>
* Before using this method, the {@link org.orekit.utils.ParameterDriver viewing model
* parameters} retrieved by calling the
* {@link LineSensor#getParametersDrivers() getParametersDrivers()} method
* on the desired sensors must be configured. The parameters that should be
* estimated must have their {@link org.orekit.utils.ParameterDriver#setSelected(boolean)
* selection status} set to {@code true} whereas the parameters that should
* retain their current value must have their
* {@link org.orekit.utils.ParameterDriver#setSelected(boolean) selection status} set to
* {@code false}. If needed, the {@link org.orekit.utils.ParameterDriver#setValue(double)
* value} of the estimated/selected parameters can also be changed before
* calling the method, as this value will serve as the initial value in the
* estimation process.
* </p>
* <p>
* The method solves a least-squares problem to minimize the residuals
* between test locations and the reference mappings by adjusting the
* selected viewing models parameters.
* </p>
* <p>
* The estimated parameters can be retrieved after the method completes by
* calling again the {@link LineSensor#getParametersDrivers()
* getParametersDrivers()} method on the desired sensors and checking the
* updated values of the parameters. In fact, as the values of the
* parameters are already updated by this method, if users want to use the
* updated values immediately to perform new direct/inverse locations, they
* can do so without looking at the parameters: the viewing models are
* already aware of the updated parameters.
* </p>
*
* @param ruggedNameList list of rugged to refine
* @param maxEvaluations maximum number of evaluations
* @param parametersConvergenceThreshold convergence threshold on normalized
* parameters (dimensionless, related to parameters scales)
* @return optimum of the least squares problem
*/
public Optimum estimateFreeParameters(final Collection<String> ruggedNameList, final int maxEvaluations,
final double parametersConvergenceThreshold) {
final List<Rugged> ruggedList = new ArrayList<>();
final List<LineSensor> selectedSensors = new ArrayList<>();
for (String ruggedName : ruggedNameList) {
final Rugged rugged = this.viewingModel.get(ruggedName);
if (rugged == null) {
throw new RuggedException(RuggedMessages.INVALID_RUGGED_NAME);
}
ruggedList.add(rugged);
selectedSensors.addAll(rugged.getLineSensors());
}
final LeastSquareAdjuster adjuster = new LeastSquareAdjuster(this.optimizerID);
LeastSquaresProblem theProblem = null;
// builder
switch (ruggedList.size()) {
case 1:
final Rugged rugged = ruggedList.get(0);
final GroundOptimizationProblemBuilder groundOptimizationProblem = new GroundOptimizationProblemBuilder(selectedSensors, measurements, rugged);
theProblem = groundOptimizationProblem.build(maxEvaluations, parametersConvergenceThreshold);
break;
case 2:
final InterSensorsOptimizationProblemBuilder interSensorsOptimizationProblem = new InterSensorsOptimizationProblemBuilder(selectedSensors, measurements, ruggedList);
theProblem = interSensorsOptimizationProblem.build(maxEvaluations, parametersConvergenceThreshold);
break;
default :
throw new RuggedException(RuggedMessages.UNSUPPORTED_REFINING_CONTEXT, ruggedList.size());
}
return adjuster.optimize(theProblem);
}
}
/* Copyright 2013-2022 CS GROUP
* Licensed to CS GROUP (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.rugged.adjustment;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hipparchus.analysis.differentiation.Gradient;
import org.hipparchus.linear.Array2DRowRealMatrix;
import org.hipparchus.linear.ArrayRealVector;
import org.hipparchus.linear.RealMatrix;
import org.hipparchus.linear.RealVector;
import org.hipparchus.optim.ConvergenceChecker;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresBuilder;
import org.hipparchus.optim.nonlinear.vector.leastsquares.LeastSquaresProblem;
import org.hipparchus.optim.nonlinear.vector.leastsquares.MultivariateJacobianFunction;
import org.hipparchus.optim.nonlinear.vector.leastsquares.ParameterValidator;
import org.hipparchus.util.FastMath;
import org.hipparchus.util.Pair;
import org.orekit.bodies.GeodeticPoint;
import org.orekit.rugged.adjustment.measurements.Observables;
import org.orekit.rugged.adjustment.measurements.SensorToGroundMapping;
import org.orekit.rugged.api.Rugged;
import org.orekit.rugged.errors.RuggedException;
import org.orekit.rugged.errors.RuggedMessages;
import org.orekit.rugged.linesensor.LineSensor;
import org.orekit.rugged.linesensor.SensorPixel;
import org.orekit.utils.ParameterDriver;
/** Ground optimization problem builder.
* builds the optimization problem relying on ground measurements.
* @author Guylaine Prat
* @author Lucie Labat Allee
* @author Jonathan Guinet
* @author Luc Maisonobe
* @since 2.0
*/
public class GroundOptimizationProblemBuilder extends OptimizationProblemBuilder {
/** Key for target. */
private static final String TARGET = "Target";
/** Key for weight. */
private static final String WEIGHT = "Weight";
/** Rugged instance to refine.*/
private final Rugged rugged;
/** Sensor to ground mapping to generate target tab for optimization.*/
private List<SensorToGroundMapping> sensorToGroundMappings;
/** Minimum line for inverse location estimation.*/
private int minLine;
/** Maximum line for inverse location estimation.*/
private int maxLine;
/** Target and weight (the solution of the optimization problem).*/
private HashMap<String, double[] > targetAndWeight;
/** Build a new instance of the optimization problem.
* @param sensors list of sensors to refine
* @param measurements set of observables
* @param rugged name of rugged to refine
*/
public GroundOptimizationProblemBuilder(final List<LineSensor> sensors,
final Observables measurements, final Rugged rugged) {
super(sensors, measurements);
this.rugged = rugged;
this.initMapping();
}
/** {@inheritDoc} */
@Override
protected void initMapping() {
final String ruggedName = rugged.getName();
this.sensorToGroundMappings = new ArrayList<>();
for (final LineSensor lineSensor : this.getSensors()) {
final SensorToGroundMapping mapping = this.getMeasurements().getGroundMapping(ruggedName, lineSensor.getName());
if (mapping != null) {
this.sensorToGroundMappings.add(mapping);
}
}
}
/** {@inheritDoc} */
@Override
protected void createTargetAndWeight() {
int n = 0;
for (final SensorToGroundMapping reference : this.sensorToGroundMappings) {
n += reference.getMapping().size();
}
if (n == 0) {
throw new RuggedException(RuggedMessages.NO_REFERENCE_MAPPINGS);
}
final double[] target = new double[2 * n];
final double[] weight = new double[2 * n];
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
int k = 0;
for (final SensorToGroundMapping reference : this.sensorToGroundMappings) {
for (final Map.Entry<SensorPixel, GeodeticPoint> mapping : reference.getMapping()) {
final SensorPixel sp = mapping.getKey();
weight[k] = 1.0;
target[k++] = sp.getLineNumber();
weight[k] = 1.0;
target[k++] = sp.getPixelNumber();
min = FastMath.min(min, sp.getLineNumber());
max = FastMath.max(max, sp.getLineNumber());
}
}
this.minLine = (int) FastMath.floor(min - ESTIMATION_LINE_RANGE_MARGIN);
this.maxLine = (int) FastMath.ceil(max - ESTIMATION_LINE_RANGE_MARGIN);
this.targetAndWeight = new HashMap<String, double[]>();
this.targetAndWeight.put(TARGET, target);
this.targetAndWeight.put(WEIGHT, weight);
}
/** {@inheritDoc} */
@Override
protected MultivariateJacobianFunction createFunction() {
// model function
final MultivariateJacobianFunction model = point -> {
// set the current parameters values
int i = 0;
for (final ParameterDriver driver : this.getDrivers()) {
driver.setNormalizedValue(point.getEntry(i++));
}
final double[] target = this.targetAndWeight.get(TARGET);
// compute inverse loc and its partial derivatives
final RealVector value = new ArrayRealVector(target.length);
final RealMatrix jacobian = new Array2DRowRealMatrix(target.length, this.getNbParams());
int l = 0;
for (final SensorToGroundMapping reference : this.sensorToGroundMappings) {
for (final Map.Entry<SensorPixel, GeodeticPoint> mapping : reference.getMapping()) {
final GeodeticPoint gp = mapping.getValue();
final Gradient[] ilResult = this.rugged.inverseLocationDerivatives(reference.getSensorName(), gp, minLine, maxLine, this.getGenerator());
if (ilResult == null) {
value.setEntry(l, minLine - 100.0); // arbitrary
// line far
// away
value.setEntry(l + 1, -100.0); // arbitrary
// pixel far away
} else {
// extract the value
value.setEntry(l, ilResult[0].getValue());
value.setEntry(l + 1, ilResult[1].getValue());
// extract the Jacobian
final int[] orders = new int[this.getNbParams()];
int m = 0;
for (final ParameterDriver driver : this.getDrivers()) {
final double scale = driver.getScale();
orders[m] = 1;
jacobian.setEntry(l, m,
ilResult[0]
.getPartialDerivative(orders) *
scale);
jacobian.setEntry(l + 1, m,
ilResult[1]
.getPartialDerivative(orders) *
scale);
orders[m] = 0;
m++;
}
}
l += 2;
}
}
// inverse loc result with Jacobian for all reference points
return new Pair<RealVector, RealMatrix>(value, jacobian);
};
return model;
}
/** Least square problem builder.
* @param maxEvaluations maxIterations and evaluations
* @param convergenceThreshold parameter convergence threshold
* @return the least square problem
*/
@Override
public final LeastSquaresProblem build(final int maxEvaluations, final double convergenceThreshold) {
this.createTargetAndWeight();
final double[] target = this.targetAndWeight.get(TARGET);
final double[] start = this.createStartTab();
final ParameterValidator validator = this.createParameterValidator();
final ConvergenceChecker<LeastSquaresProblem.Evaluation> checker = this.createChecker(convergenceThreshold);
final MultivariateJacobianFunction model = this.createFunction();
return new LeastSquaresBuilder()
.lazyEvaluation(false).maxIterations(maxEvaluations)
.maxEvaluations(maxEvaluations).weight(null).start(start)
.target(target).parameterValidator(validator).checker(checker)
.model(model).build();
}
}