AEMWriter.java
- /* Copyright 2002-2020 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.files.ccsds;
- import java.io.BufferedWriter;
- import java.io.IOException;
- import java.nio.charset.StandardCharsets;
- import java.nio.file.Files;
- import java.nio.file.Paths;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- import org.orekit.errors.OrekitIllegalArgumentException;
- import org.orekit.errors.OrekitMessages;
- import org.orekit.files.ccsds.StreamingAemWriter.AEMSegment;
- import org.orekit.files.general.AttitudeEphemerisFile;
- import org.orekit.files.general.AttitudeEphemerisFile.SatelliteAttitudeEphemeris;
- import org.orekit.files.general.AttitudeEphemerisFile.AttitudeEphemerisSegment;
- import org.orekit.files.general.AttitudeEphemerisFileWriter;
- import org.orekit.time.TimeScale;
- import org.orekit.utils.TimeStampedAngularCoordinates;
- /**
- * A writer for Attitude Ephemeris Messsage (AEM) files.
- * @author Bryan Cazabonne
- * @since 10.2
- */
- public class AEMWriter implements AttitudeEphemerisFileWriter {
- /** Originator name, usually the organization and/or country. **/
- private final String originator;
- /** Space object ID, usually an official international designator such as "1998-067A". */
- private final String spaceObjectId;
- /** Space object name, usually a common name for an object like "ISS". **/
- private final String spaceObjectName;
- /** Format for attitude ephemeris data output. */
- private final String attitudeFormat;
- /**
- * Standard default constructor that creates a writer with default configurations
- * including {@link StreamingAemWriter#DEFAULT_ATTITUDE_FORMAT Default formatting}.
- */
- public AEMWriter() {
- this(StreamingAemWriter.DEFAULT_ORIGINATOR, null, null,
- StreamingAemWriter.DEFAULT_ATTITUDE_FORMAT);
- }
- /**
- * Constructor used to create a new AEM writer configured with the necessary parameters
- * to successfully fill in all required fields that aren't part of a standard object
- * and using {@link StreamingAemWriter#DEFAULT_ATTITUDE_FORMAT default formatting}
- * for attitude ephemeris data output.
- *
- * @param originator the originator field string
- * @param spaceObjectId the spacecraft ID
- * @param spaceObjectName the space object common name
- */
- public AEMWriter(final String originator, final String spaceObjectId,
- final String spaceObjectName) {
- this(originator, spaceObjectId, spaceObjectName,
- StreamingAemWriter.DEFAULT_ATTITUDE_FORMAT);
- }
- /**
- * Constructor used to create a new AEM writer configured with the necessary
- * parameters to successfully fill in all required fields that aren't part
- * of a standard object and user-defined attitude ephemeris data output format.
- *
- * @param originator the originator field string
- * @param spaceObjectId the spacecraft ID
- * @param spaceObjectName the space object common name
- * @param attitudeFormat {@link java.util.Formatter format parameters} for
- * attitude ephemeris data output
- * @since 10.3
- */
- public AEMWriter(final String originator, final String spaceObjectId,
- final String spaceObjectName, final String attitudeFormat) {
- this.originator = originator;
- this.spaceObjectId = spaceObjectId;
- this.spaceObjectName = spaceObjectName;
- this.attitudeFormat = attitudeFormat;
- }
- /** {@inheritDoc} */
- @Override
- public void write(final Appendable writer, final AttitudeEphemerisFile ephemerisFile)
- throws IOException {
- if (writer == null) {
- throw new OrekitIllegalArgumentException(OrekitMessages.NULL_ARGUMENT, "writer");
- }
- if (ephemerisFile == null) {
- return;
- }
- final String idToProcess;
- if (spaceObjectId != null) {
- if (ephemerisFile.getSatellites().containsKey(spaceObjectId)) {
- idToProcess = spaceObjectId;
- } else {
- throw new OrekitIllegalArgumentException(OrekitMessages.VALUE_NOT_FOUND, spaceObjectId, "ephemerisFile");
- }
- } else if (ephemerisFile.getSatellites().keySet().size() == 1) {
- idToProcess = ephemerisFile.getSatellites().keySet().iterator().next();
- } else {
- throw new OrekitIllegalArgumentException(OrekitMessages.EPHEMERIS_FILE_NO_MULTI_SUPPORT);
- }
- // Get satellite and attitude ephemeris segments to output.
- final SatelliteAttitudeEphemeris satEphem = ephemerisFile.getSatellites().get(idToProcess);
- final List<? extends AttitudeEphemerisSegment> segments = satEphem.getSegments();
- if (segments.isEmpty()) {
- // No data -> No output
- return;
- }
- // First segment
- final AttitudeEphemerisSegment firstSegment = segments.get(0);
- final String objectName = this.spaceObjectName == null ? idToProcess : this.spaceObjectName;
- // Only one time scale per AEM file, see Section 4.2.5.4.2
- final TimeScale timeScale = firstSegment.getTimeScale();
- // Metadata that is constant for the whole AEM file
- final Map<Keyword, String> metadata = new LinkedHashMap<>();
- metadata.put(Keyword.TIME_SYSTEM, firstSegment.getTimeScaleString());
- metadata.put(Keyword.ORIGINATOR, this.originator);
- // Only one object in an AEM file, see Section 2.3.1
- metadata.put(Keyword.OBJECT_NAME, objectName);
- metadata.put(Keyword.OBJECT_ID, idToProcess);
- // Header comments. If header comments are presents, they are assembled together in a single line
- if (ephemerisFile instanceof AEMFile) {
- // Cast to OEMFile
- final AEMFile aemFile = (AEMFile) ephemerisFile;
- if (!aemFile.getHeaderComment().isEmpty()) {
- // Loop on comments
- final StringBuffer buffer = new StringBuffer();
- for (String comment : aemFile.getHeaderComment()) {
- buffer.append(comment);
- }
- // Update metadata
- metadata.put(Keyword.COMMENT, buffer.toString());
- }
- }
- // Writer for AEM files
- final StreamingAemWriter aemWriter =
- new StreamingAemWriter(writer, timeScale, metadata, attitudeFormat);
- aemWriter.writeHeader();
- // Loop on segments
- for (final AttitudeEphemerisSegment segment : segments) {
- // Segment specific metadata
- metadata.clear();
- metadata.put(Keyword.CENTER_NAME, segment.getFrameCenterString());
- metadata.put(Keyword.REF_FRAME_A, segment.getRefFrameAString());
- metadata.put(Keyword.REF_FRAME_B, segment.getRefFrameBString());
- metadata.put(Keyword.ATTITUDE_DIR, segment.getAttitudeDirection());
- metadata.put(Keyword.START_TIME, segment.getStart().toString(timeScale));
- metadata.put(Keyword.STOP_TIME, segment.getStop().toString(timeScale));
- metadata.put(Keyword.ATTITUDE_TYPE, segment.getAttitudeType());
- metadata.put(Keyword.INTERPOLATION_METHOD, segment.getInterpolationMethod());
- metadata.put(Keyword.INTERPOLATION_DEGREE,
- String.valueOf(segment.getInterpolationSamples() - 1));
- final AEMSegment segmentWriter = aemWriter.newSegment(metadata);
- segmentWriter.writeMetadata();
- segmentWriter.startAttitudeBlock();
- // Loop on attitude data
- for (final TimeStampedAngularCoordinates coordinates : segment.getAngularCoordinates()) {
- segmentWriter.writeAttitudeEphemerisLine(coordinates, segment.isFirst(),
- segment.getAttitudeType(), segment.getRotationOrder());
- }
- segmentWriter.endAttitudeBlock();
- }
- }
- /**
- * Write the passed in {@link AEMFile} using the passed in {@link Appendable}.
- * @param writer a configured Appendable to feed with text
- * @param aemFile a populated aem file to serialize into the buffer
- * @throws IOException if any buffer writing operations fail or if the underlying
- * format doesn't support a configuration in the EphemerisFile
- * for example having multiple satellites in one file, having
- * the origin at an unspecified celestial body, etc.)
- */
- public void write(final Appendable writer, final AEMFile aemFile) throws IOException {
- write(writer, (AttitudeEphemerisFile) aemFile);
- }
- /**
- * Write the passed in {@link AEMFile} to a file at the output path specified.
- * @param outputFilePath a file path that the corresponding file will be written to
- * @param aemFile a populated aem file to serialize into the buffer
- * @throws IOException if any file writing operations fail or if the underlying
- * format doesn't support a configuration in the EphemerisFile
- * (for example having multiple satellites in one file, having
- * the origin at an unspecified celestial body, etc.)
- */
- public void write(final String outputFilePath, final AEMFile aemFile)
- throws IOException {
- try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputFilePath), StandardCharsets.UTF_8)) {
- write(writer, (AttitudeEphemerisFile) aemFile);
- }
- }
- }