public SatelliteStateOutput(
      TLEPredictorProcess parentProcess,
      String name,
      TLEOutput tleOutput,
      double outputPeriod,
      double predictHorizon) {
    this.parentProcess = parentProcess;
    this.eventHandler = new BasicEventHandler();
    this.orbitPredictor = new TLEOrbitPredictor(tleOutput);
    this.name = name;
    this.outputPeriod = outputPeriod;
    this.predictHorizon = predictHorizon;

    // create output structure
    SWEHelper fac = new SWEHelper();
    DataRecord rec = fac.newDataRecord();
    rec.setName(getName());
    rec.setDefinition(SWEConstants.DEF_PLATFORM_LOC.replace("Location", "State"));
    rec.addField("time", fac.newTimeStampIsoUTC());
    rec.addField("position", fac.newLocationVectorECEF(SWEConstants.DEF_PLATFORM_LOC));
    rec.addField(
        "velocity",
        fac.newVelocityVectorECEF(
            SWEConstants.DEF_PLATFORM_LOC.replace("Location", "Velocity"), "m/s"));
    this.outputDef = rec;

    this.outputEncoding = fac.newTextEncoding();
  }
  @Override
  protected void init() {
    SWEHelper fac = new SWEHelper();

    // build SWE Common record structure
    laserData = fac.newDataRecord(5);
    laserData.setName(getName());
    laserData.setDefinition("http://sensorml.com/ont/swe/property/LaserRangeData");

    // add time, horizontalDistance, azimuth, inclination, and slopeDistance
    laserData.addComponent("time", fac.newTimeStampIsoUTC());
    laserData.addComponent(
        "horizDistance",
        fac.newQuantity(
            SWEHelper.getPropertyUri("HorizontalDistance"), "Horizontal Distance", null, "m"));
    laserData.addComponent(
        "slopeDistance",
        fac.newQuantity(
            SWEHelper.getPropertyUri("LineOfSightDistance"), "Line-of-Sight Distance", null, "m"));

    // for azimuth (trueHeading), we also specify a reference frame
    Quantity q =
        fac.newQuantity(SWEHelper.getPropertyUri("TrueHeading"), "True Heading", null, "deg");
    q.setReferenceFrame("http://sensorml.com/ont/swe/property/NED");
    q.setAxisID("z");
    laserData.addComponent("azimuth", q);

    // for inclination, we also specify a reference frame
    q = fac.newQuantity(SWEHelper.getPropertyUri("Inclination"), "Inclination", null, "deg");
    q.setReferenceFrame("http://sensorml.com/ont/swe/property/NED");
    q.setAxisID("y");
    laserData.addComponent("inclination", q);

    // also generate encoding definition as text block
    dataEncoding = fac.newTextEncoding(",", "\n");
  }