1   /* Copyright 2002-2021 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.orekit.files.ccsds.ndm.odm.ocm;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import org.hipparchus.geometry.euclidean.threed.Vector3D;
24  import org.orekit.files.ccsds.definitions.DutyCycleType;
25  import org.orekit.files.ccsds.definitions.TimeConverter;
26  import org.orekit.files.ccsds.section.AbstractWriter;
27  import org.orekit.files.ccsds.utils.FileFormat;
28  import org.orekit.files.ccsds.utils.generation.Generator;
29  import org.orekit.utils.AccurateFormatter;
30  import org.orekit.utils.units.Unit;
31  
32  /** Writer for maneuvers history data.
33   * @author Luc Maisonobe
34   * @since 11.0
35   */
36  class ManeuverHistoryWriter extends AbstractWriter {
37  
38      /** Maneuvers history block. */
39      private final ManeuverHistory history;
40  
41      /** Converter for dates. */
42      private final TimeConverter timeConverter;
43  
44      /** Create a writer.
45       * @param maneuverHistory maneuvers history to write
46       * @param timeConverter converter for dates
47       */
48      ManeuverHistoryWriter(final ManeuverHistory maneuverHistory,
49                            final TimeConverter timeConverter) {
50          super(OcmDataSubStructureKey.man.name(), OcmDataSubStructureKey.MAN.name());
51          this.history       = maneuverHistory;
52          this.timeConverter = timeConverter;
53      }
54  
55      /** {@inheritDoc} */
56      @Override
57      protected void writeContent(final Generator generator) throws IOException {
58  
59          // maneuvers history block
60          final ManeuverHistoryMetadata metadata = history.getMetadata();
61          generator.writeComments(metadata.getComments());
62  
63          // identifiers
64          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_ID.name(),        metadata.getManID(),       null, false);
65          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_PREV_ID.name(),   metadata.getManPrevID(),   null, false);
66          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_NEXT_ID.name(),   metadata.getManNextID(),   null, false);
67          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_BASIS.name(),     metadata.getManBasis(),          false);
68          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_BASIS_ID.name(),  metadata.getManBasisID(),  null, false);
69          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_DEVICE_ID.name(), metadata.getManDeviceID(), null, false);
70  
71          // time
72          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_PREV_EPOCH.name(), timeConverter, metadata.getManPrevEpoch(), false);
73          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_NEXT_EPOCH.name(), timeConverter, metadata.getManNextEpoch(), false);
74  
75          // references
76          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_PURPOSE.name(),      metadata.getManPurpose(),                          false);
77          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_PRED_SOURCE.name(),  metadata.getManPredSource(),                 null, false);
78          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_REF_FRAME.name(),    metadata.getManReferenceFrame().getName(),   null, false);
79          generator.writeEntry(ManeuverHistoryMetadataKey.MAN_FRAME_EPOCH.name(),  timeConverter, metadata.getManFrameEpoch(),        false);
80          if (metadata.getGravitationalAssist() != null) {
81              generator.writeEntry(ManeuverHistoryMetadataKey.GRAV_ASSIST_NAME.name(), metadata.getGravitationalAssist().getName(), null, false);
82          }
83  
84          // duty cycle
85          final boolean notContinuous = metadata.getDcType() != DutyCycleType.CONTINUOUS;
86          final boolean timeAndAngle  = metadata.getDcType() == DutyCycleType.TIME_AND_ANGLE;
87          generator.writeEntry(ManeuverHistoryMetadataKey.DC_TYPE.name(),                metadata.getDcType(),                           false);
88          generator.writeEntry(ManeuverHistoryMetadataKey.DC_WIN_OPEN.name(),            timeConverter, metadata.getDcWindowOpen(),      notContinuous);
89          generator.writeEntry(ManeuverHistoryMetadataKey.DC_WIN_CLOSE.name(),           timeConverter, metadata.getDcWindowClose(),     notContinuous);
90          generator.writeEntry(ManeuverHistoryMetadataKey.DC_MIN_CYCLES.name(),          metadata.getDcMinCycles(),                      false);
91          generator.writeEntry(ManeuverHistoryMetadataKey.DC_MAX_CYCLES.name(),          metadata.getDcMaxCycles(),                      false);
92          generator.writeEntry(ManeuverHistoryMetadataKey.DC_EXEC_START.name(),          timeConverter, metadata.getDcExecStart(),       notContinuous);
93          generator.writeEntry(ManeuverHistoryMetadataKey.DC_EXEC_STOP.name(),           timeConverter, metadata.getDcExecStop(),        notContinuous);
94          generator.writeEntry(ManeuverHistoryMetadataKey.DC_REF_TIME.name(),            timeConverter, metadata.getDcRefTime(),         notContinuous);
95          generator.writeEntry(ManeuverHistoryMetadataKey.DC_TIME_PULSE_DURATION.name(), metadata.getDcTimePulseDuration(), Unit.SECOND, notContinuous);
96          generator.writeEntry(ManeuverHistoryMetadataKey.DC_TIME_PULSE_PERIOD.name(),   metadata.getDcTimePulsePeriod(),   Unit.SECOND, notContinuous);
97          if (timeAndAngle) {
98              generator.writeEntry(ManeuverHistoryMetadataKey.DC_REF_DIR.name(), toString(metadata.getDcRefDir()), null, timeAndAngle);
99              generator.writeEntry(ManeuverHistoryMetadataKey.DC_BODY_FRAME.name(),
100                                  metadata.getDcBodyFrame().toString().replace(' ', '_'),
101                                  null, timeAndAngle);
102             generator.writeEntry(ManeuverHistoryMetadataKey.DC_BODY_TRIGGER.name(),   toString(metadata.getDcBodyTrigger()), null,   timeAndAngle);
103             generator.writeEntry(ManeuverHistoryMetadataKey.DC_PA_START_ANGLE.name(), metadata.getDcPhaseStartAngle(), Unit.DEGREE,  timeAndAngle);
104             generator.writeEntry(ManeuverHistoryMetadataKey.DC_PA_STOP_ANGLE.name(),  metadata.getDcPhaseStopAngle(),  Unit.DEGREE,  timeAndAngle);
105         }
106 
107         // elements
108         final List<ManeuverFieldType> types       = metadata.getManComposition();
109         final StringBuilder           composition = new StringBuilder();
110         for (int i = 0; i < types.size(); ++i) {
111             if (i > 0) {
112                 composition.append(',');
113             }
114             composition.append(types.get(i).name());
115         }
116         generator.writeEntry(ManeuverHistoryMetadataKey.MAN_COMPOSITION.name(), composition.toString(),                        null, false);
117         generator.writeEntry(ManeuverHistoryMetadataKey.MAN_UNITS.name(), generator.unitsListToString(metadata.getManUnits()), null, false);
118 
119         // data
120         for (final Maneuver maneuver : history.getManeuvers()) {
121             final StringBuilder line = new StringBuilder();
122             for (int i = 0; i < types.size(); ++i) {
123                 if (i > 0) {
124                     line.append(' ');
125                 }
126                 line.append(types.get(i).outputField(timeConverter, maneuver));
127             }
128             if (generator.getFormat() == FileFormat.XML) {
129                 generator.writeEntry(Ocm.MAN_LINE, line.toString(), null, true);
130             } else {
131                 generator.writeRawData(line);
132                 generator.newLine();
133             }
134         }
135     }
136 
137     /** Convert a vector to a space separated string.
138      * @param vector vector to convert
139      * @return orrespondong string
140      */
141     private String toString(final Vector3D vector) {
142         final StringBuilder builder = new StringBuilder();
143         builder.append(AccurateFormatter.format(Unit.ONE.fromSI(vector.getX())));
144         builder.append(' ');
145         builder.append(AccurateFormatter.format(Unit.ONE.fromSI(vector.getY())));
146         builder.append(' ');
147         builder.append(AccurateFormatter.format(Unit.ONE.fromSI(vector.getZ())));
148         return builder.toString();
149     }
150 
151 }