blob: ee98185aa89d5b178a392274da2ac29e718b56e8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pierre Allard,
* Regent L'Archeveque - initial API and implementation
*
* SPDX-License-Identifier: EPL-1.0
*******************************************************************************/
package org.eclipse.apogy.examples.antenna.apogy.impl;
import org.eclipse.apogy.addons.sensors.fov.ApogyAddonsSensorsFOVFacade;
import org.eclipse.apogy.addons.sensors.fov.ConicalFieldOfView;
import org.eclipse.apogy.common.math.Tuple3d;
import org.eclipse.apogy.core.ApogySystem;
import org.eclipse.apogy.core.environment.ApogyCoreEnvironmentFacade;
import org.eclipse.apogy.core.invocator.AbstractInitializationData;
import org.eclipse.apogy.core.invocator.Environment;
import org.eclipse.apogy.core.invocator.Type;
import org.eclipse.apogy.examples.antenna.PTUDishAntenna;
import org.eclipse.apogy.examples.antenna.apogy.ApogyExamplesAntennaApogyFactory;
import org.eclipse.apogy.examples.antenna.apogy.PTUDishAntennaData;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.ecore.EObject;
public class PTUDishAntennaApogySystemApiAdapterCustomImpl extends PTUDishAntennaApogySystemApiAdapterImpl {
/**
* This is the environment in which the Apogy system operates
*/
protected Environment environment;
/**
* This is the core Apogy system and the utilities it provides.
*/
protected ApogySystem apogySystem;
/**
* This is the sun tracker job, which may be available, depending on the
* instance's exact type.
*/
protected Job sunTrackerJob = null;
/**
* This is the callback method that is called by the API adapter when the PTU
* dish antenna instance is being initialized by Apogy.
*
* @param environment The environment in which Apogy and its components are
* operating.
* @param elementType The type (e.g. class) of the given instance.
* @param instance The instance which is being handled by this API adapter.
*/
@Override
public void init(Environment environment, Type elementType, EObject instance) {
// Call the superclass's version of this method
super.init(environment, elementType, instance);
// Create the sun tracker job
this.sunTrackerJob = new SunTrackerJob(this, "PTU Dish Antenna Sun Tracker");
// Schedule it to be run
this.sunTrackerJob.schedule();
}
/**
* This is the callback method that is called by the API adapter when the PTU
* dish antenna instance is being disposed (i.e. shutdown / destroyed) by Apogy
*/
@Override
public void dispose() {
// If there is a sun tracker job
// (it may not be appropriate for all
// implementations of the antenna instance)
if (this.sunTrackerJob != null) {
// Cancel the job
this.sunTrackerJob.cancel();
}
// Call the superclass's version of this method
super.dispose();
}
/**
* This is used to retrieve the API adapter's PTU dish antenna instance.
*
* @return The PTU dish antenna instance associated with this API adapter
*/
protected PTUDishAntenna getPTUDishAntenna() {
// Just return the casted instance reference
return (PTUDishAntenna) getInstance();
}
/**
* This is a factory method which can be called by the API adapter in order to
* create an initialization data instance of the appropriate type.
*/
@Override
public AbstractInitializationData createInitializationData() {
// Use the relevant factory method to create the desired
// initialization data object, which, in this case, is
// an instance of PTUDishAntennaData
return ApogyExamplesAntennaApogyFactory.eINSTANCE.createPTUDishAntennaData();
}
/**
* This is a method which is used to apply the given initialization data object
* to the API adapter's instance; this is particularly useful in conjunction
* with collect() as it can be used to save state and then load it back later.
*
* @param initializationData The initialization data that is to be applied to
* the adapter's instance.
* @see #collect(AbstractInitializationData)
*/
@Override
public void apply(AbstractInitializationData initializationData) {
// Call the superclass's version of this method
super.apply(initializationData);
// If this is an initialization data object which is
// relevant to the PTU dish antenna adapter
if (initializationData instanceof PTUDishAntennaData) {
// Cast it appropriately
PTUDishAntennaData ptuDishAntennaData = (PTUDishAntennaData) initializationData;
// If the PTU dish antenna is supposed to be initialized
if (ptuDishAntennaData.isInitialized() == true) {
// If the PTU dish isn't already initialized
if (this.getPTUDishAntenna().isInitialized() == false) {
// Just initialize it
this.getPTUDishAntenna().init();
}
// Move dish antenna to the given pan and tilt angle
this.getPTUDishAntenna().moveTo(ptuDishAntennaData.getPanAngle(), ptuDishAntennaData.getTiltAngle());
// Indicate whether the sun should be tracked
this.getPTUDishAntenna().trackSun(ptuDishAntennaData.isTrackingSun());
// If the initialization data has a field of view in it
if (ptuDishAntennaData.getFov() != null) {
// Create a copy of that field of view object
ConicalFieldOfView fov = ApogyAddonsSensorsFOVFacade.INSTANCE
.createConicalFieldOfView(ptuDishAntennaData.getFov());
// Update the FOV accordingly
this.getPTUDishAntenna().setFov(fov);
}
// Otherwise,
else {
// Just set it to null
this.getPTUDishAntenna().setFov(null);
}
}
// Otherwise, it's not supposed to be initialized
else {
// If the PTU dish is already initialized (Bad Case)
if (this.getPTUDishAntenna().isInitialized() == true) {
// Generate the error message
String message = "The given initialization data cannot be applied "
+ "to this PTU antenna; the given init data says that "
+ "the antenna should not be initialized, when " + "it already is in that state.";
// Throw an exception to indicate that the apply() has failed; this will
// be caught and logged by Apogy
throw new RuntimeException(message);
}
}
}
}
/**
* This is a method which is used to collect and fill the given initialization
* data object with relevant data from the API adapter's instance; this is
* particularly useful in conjunction with apply() as it can be used to save
* data, which can then be loaded back later.
*
* @param initializationData The initialization data that is to store the state
* of the adapter's instance.
* @see #apply(AbstractInitializationData)
*/
@Override
public void collect(AbstractInitializationData initializationData) {
// Call the superclass's version of this method
super.collect(initializationData);
// If this is an initialization data object which is
// relevant to the PTU dish antenna adapter
if (initializationData instanceof PTUDishAntennaData) {
// Cast it accordingly
PTUDishAntennaData ptuDishAntennaData = (PTUDishAntennaData) initializationData;
// If the antenna had a field of view
if (this.getPTUDishAntenna().getFov() != null) {
// Store a copy of it in the initialization data object
ptuDishAntennaData.setFov(ApogyAddonsSensorsFOVFacade.INSTANCE
.createConicalFieldOfView(this.getPTUDishAntenna().getFov()));
}
// Otherwise
else {
// Just set it to null
ptuDishAntennaData.setFov(null);
}
// Just store the other values
ptuDishAntennaData.setInitialized(this.getPTUDishAntenna().isInitialized());
ptuDishAntennaData.setPanAngle(this.getPTUDishAntenna().getPanAngle());
ptuDishAntennaData.setTiltAngle(this.getPTUDishAntenna().getTiltAngle());
ptuDishAntennaData.setTrackingSun(this.getPTUDishAntenna().isTrackingSun());
}
}
} // PTUDishAntennaApogySystemApiAdapterImpl
/**
* This class is used to implement the sun tracking functionality for the PTU
* dish antenna.
*/
class SunTrackerJob extends Job {
/**
* This is the length of time (in milliseconds) between subsequent updates of
* the antenna's position.
*/
private static final int SUN_TRACK_UPDATE_PERIOD = 200;
/**
* This is used to keep track of the relevant API adapter
*/
private final PTUDishAntennaApogySystemApiAdapterCustomImpl apiAdapter;
/**
* This is the constructor for the SunTrackerJob class and as such, performs the
* required initialization and creation operations.
*/
protected SunTrackerJob(PTUDishAntennaApogySystemApiAdapterCustomImpl apiAdapter, String jobName) {
// Just call the constructor for the superclass
super(jobName);
// Keep track of the API adapter
this.apiAdapter = apiAdapter;
}
/**
* This is the workhorse of the SunTrackerJob class, actually performing the
* updates required to keep tracking the sun.
*
* @param monitor This is used to keep track of the job's progress and status
* @return The status of the job when it finished running
*/
@Override
protected IStatus run(IProgressMonitor monitor) {
// While the job hasn't been cancelled yet
while (monitor.isCanceled() == false) {
// If there actually is an instance and tracking of the sun is enabled
if ((this.apiAdapter.getPTUDishAntenna() != null)
&& (this.apiAdapter.getPTUDishAntenna().isTrackingSun() == true)) {
// Get a vector pointing to the sun
Tuple3d sunVector = ApogyCoreEnvironmentFacade.INSTANCE.getSunVector(this.apiAdapter.getApogySystem(),
"PTU_DISH_ANTENNA_SYM_SYS_ROOT");
// If the sun vector was available
if (sunVector != null) {
// Get the length of the sun vector hypotenuse
double l = Math.sqrt((sunVector.getX() * sunVector.getX()) + (sunVector.getY() * sunVector.getY()));
// Extract the required pan angle (e.g. azimuth) for the antenna
double panAngle = Math.atan2(sunVector.getY(), sunVector.getX());
// Extract the required tilt angle (e.g. elevation) for the antenna
double tiltAngle = Math.atan2(sunVector.getZ(), l);
// Set the PTU dish's pan and tilt angles accordingly
this.apiAdapter.getPTUDishAntenna().setPanAngle(panAngle);
this.apiAdapter.getPTUDishAntenna().setTiltAngle(tiltAngle);
}
}
try {
// Sleep for a period of time
Thread.sleep(SUN_TRACK_UPDATE_PERIOD);
} catch (InterruptedException ex) {
// Print out the stack trace
ex.printStackTrace();
}
}
// Just indicate that the sun tracker job completed successfully
return Status.OK_STATUS;
}
}