org.hbird.business.groundstation.base.TrackingSupport.java Source code

Java tutorial

Introduction

Here is the source code for org.hbird.business.groundstation.base.TrackingSupport.java

Source

/**
 * Licensed to the Hummingbird Foundation (HF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The HF 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.hbird.business.groundstation.base;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import org.hbird.business.api.IDataAccess;
import org.hbird.business.api.IPointingData;
import org.hbird.business.groundstation.configuration.GroundStationDriverConfiguration;
import org.hbird.exchange.constants.StandardArguments;
import org.hbird.exchange.core.CommandBase;
import org.hbird.exchange.groundstation.GroundStation;
import org.hbird.exchange.groundstation.IPointingDataOptimizer;
import org.hbird.exchange.groundstation.ITrackingDevice;
import org.hbird.exchange.groundstation.Track;
import org.hbird.exchange.navigation.ContactParameterRange;
import org.hbird.exchange.navigation.ExtendedContactParameterRange;
import org.hbird.exchange.navigation.LocationContactEvent;
import org.hbird.exchange.navigation.PointingData;
import org.hbird.exchange.navigation.Satellite;
import org.hbird.exchange.util.Dates;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 */
public abstract class TrackingSupport<C extends GroundStationDriverConfiguration> implements ITrackingDevice {

    private static final Logger LOG = LoggerFactory.getLogger(TrackingSupport.class);

    protected static final List<CommandBase> NO_COMMANDS = Collections.emptyList();

    protected final C configuration;

    protected final IDataAccess dao;

    protected final IPointingDataOptimizer<C> optimizer;

    protected IPointingData orbitDataCalculator;

    /**
     * @param configuration
     * @param failOldRequests
     * @param dataAccess
     * @param orbitPrediction
     * @param optimizer
     */
    public TrackingSupport(C configuration, IDataAccess dao, IPointingData orbitDataCalculator,
            IPointingDataOptimizer<C> optimizer) {
        this.configuration = configuration;
        this.dao = dao;
        this.optimizer = optimizer;
        this.orbitDataCalculator = orbitDataCalculator;
    }

    /**
     * @see org.hbird.exchange.groundstation.ITrackingDevice#track(org.hbird.exchange.groundstation.Track)
     */
    @Override
    public List<CommandBase> track(Track command) {
        LOG.debug("Creating tracking commands ...");
        List<String> missing = command.checkArguments();
        if (!missing.isEmpty()) {
            LOG.error("Missing command arguments for the command '{}' - '{}'; tracking not possible",
                    command.getClass().getSimpleName(), missing);
            return NO_COMMANDS;
        }

        LocationContactEvent contact = command.getLocationContactEvent();
        Satellite satellite = command.getSatellite();

        if (!validateArgument(contact, StandardArguments.START)) {
            return NO_COMMANDS;
        }
        if (!validateArgument(satellite, StandardArguments.SATELLITE_ID)) {
            return NO_COMMANDS;
        }

        String groundStationId = configuration.getGroundstationId();
        GroundStation groundStation = null;
        try {
            groundStation = (GroundStation) dao.resolve(groundStationId);
        } catch (Exception e) {
            LOG.error("Failed to resolve groundstation for the ID '{}'", groundStationId, e);
            return NO_COMMANDS;
        }

        if (groundStation == null) {
            LOG.error("GroundStation not found for the ID '{}'", groundStationId);
            return NO_COMMANDS;
        }

        long now = System.currentTimeMillis();
        long contactStartTime = contact.getStartTime();

        if (!validateByTime(contactStartTime, now, configuration.isSkipOutDatedCommands())) {
            return NO_COMMANDS;
        }

        if (!isTrackingPossible(contact, groundStation, satellite)) {
            return NO_COMMANDS;
        }

        ContactParameterRange azimuth = contact.getAzimuth();
        ExtendedContactParameterRange elevation = contact.getElevation();
        ContactParameterRange doppler = contact.getDoppler();
        LOG.info("Creating tracking commands for the satellite '{}' in the ground station '{}'", satellite,
                groundStation);
        LOG.info("   Contact - start: {}; end: {}", Dates.toDefaultDateFormat(contactStartTime),
                Dates.toDefaultDateFormat(contact.getEndTime()));
        LOG.info("   Azimuth - start: {}; end: {}", azimuth.getStart(), azimuth.getEnd());
        LOG.info("   Elevation - max: {}", elevation.getMax());
        LOG.info("   Doppler - start: {}; end: {}", doppler.getStart(), doppler.getEnd());

        List<PointingData> pointingData = null;
        try {
            pointingData = orbitDataCalculator.calculateContactData(contact, groundStation,
                    configuration.getCommandInterval());
        } catch (Exception e) {
            LOG.error(
                    "Failed to calculate pointing data for the contact; ground station: '{}'; satellite: '{}'; contact start time: '{}'; Exception: ",
                    new Object[] { groundStation.getGroundStationID(), satellite.getSatelliteID(),
                            Dates.toIso8601DateFormat(contactStartTime), e });
            return NO_COMMANDS;
        }

        LOG.debug("Optimizing pointing data");
        pointingData = optimize(pointingData, configuration, optimizer);
        LOG.debug("Pointing data optimized");

        List<CommandBase> commands = new LinkedList<CommandBase>();
        commands.addAll(createPreContactCommands(groundStation, satellite, pointingData, configuration, command));
        commands.addAll(createContactCommands(groundStation, satellite, pointingData, configuration, command));
        commands.addAll(createPostContactCommands(groundStation, satellite, pointingData, configuration, command));

        int size = commands.size();
        String firstCommand = new DateTime(commands.get(0).getExecutionTime())
                .toString(ISODateTimeFormat.dateTime());
        String lastCommand = new DateTime(commands.get(size - 1).getExecutionTime())
                .toString(ISODateTimeFormat.dateTime());
        LOG.info(
                "Created {} tracking commands for the satellite '{}' in groundstation '{}'; first command at {}; last command at {}",
                new Object[] { size, satellite, groundStation, firstCommand, lastCommand });

        return commands;
    }

    protected abstract List<CommandBase> createContactCommands(GroundStation gs, Satellite sat,
            List<PointingData> pointingData, C configuration, Track trackCommand);

    /**
     * Check if tracking is possible for the device.
     * 
     * By default returns true. Override for device specific checks.
     * 
     * @param start start of the contact
     * @param end end of the contact
     * @param gs {@link GroundStation}
     * @param satellite {@link Satellite}
     * @return true if tracking is possible
     */
    protected boolean isTrackingPossible(LocationContactEvent contactLocationEvent, GroundStation gs,
            Satellite satellite) {
        return true;
    }

    /**
     * Validates contact start event using current time stamp and value of failOldRequest flag.
     * 
     * @param commandTimestamp
     * @param now
     * @param failOldRequests
     * @return
     */
    protected boolean validateByTime(long commandTimestamp, long now, boolean failOldRequests) {
        if (commandTimestamp < now && failOldRequests) {
            LOG.info(
                    "Start event timestamp ({}) is before current moment ({}) and failOldRequests is set to {}; skipping the contact",
                    new Object[] { Dates.toIso8601DateFormat(commandTimestamp), Dates.toIso8601DateFormat(now),
                            failOldRequests });
            return false;
        }
        return true;
    }

    /**
     * Create setup commands to execute before the contact.
     * 
     * Setup command for the device. By default returns empty list. Override for device if needed.
     * 
     * @param gs
     * @param sat
     * @param pointingData
     * @return
     */
    protected List<CommandBase> createPreContactCommands(GroundStation gs, Satellite sat,
            List<PointingData> pointingData, C configuration, Track trackCommand) {
        return NO_COMMANDS;
    }

    protected List<CommandBase> createPostContactCommands(GroundStation gs, Satellite sat,
            List<PointingData> pointingData, C configuration, Track trackCommand) {
        return NO_COMMANDS;
    }

    protected boolean validateArgument(Object arg, String name) {
        if (arg == null) {
            LOG.error("Command argument '{}' is null; tracking not possible", name);
            return false;
        }
        return true;
    }

    protected List<PointingData> optimize(List<PointingData> pointingData, C configuration,
            IPointingDataOptimizer<C> optimizer) {
        if (optimizer == null) {
            return pointingData;
        }
        try {
            return optimizer.optimize(pointingData, configuration);
        } catch (Exception e) {
            LOG.error("Optimizre '{}' failed; using unoptimized pointing data for tracking",
                    optimizer.getClass().getName(), e);
            return pointingData;
        }
    }
}