package com.dronecontrol.droneapi; import com.google.common.collect.Lists; import com.dronecontrol.droneapi.commands.ATCommand; import com.dronecontrol.droneapi.commands.simple.FlatTrimCommand; import com.dronecontrol.droneapi.commands.simple.FlightModeCommand; import com.dronecontrol.droneapi.commands.simple.FlightMoveCommand; import com.dronecontrol.droneapi.data.InternalState; import com.dronecontrol.droneapi.data.NavData; import com.dronecontrol.droneapi.data.enums.FlightMode; import com.dronecontrol.droneapi.listeners.NavDataListener; import javax.inject.Inject; import java.util.Collection; public class InternalStateWatcher implements NavDataListener { private static final float MOVE_THRESHOLD = 0.02f; private InternalState internalState; private NavData currentNavData; @Inject public InternalStateWatcher(NavigationDataRetriever navigationDataRetriever) { navigationDataRetriever.addNavDataListener(this); internalState = new InternalState(); } public Collection<ATCommand> getCommandsToUpholdInternalState() { if (currentNavData == null) { return Lists.newArrayList(); } Collection<ATCommand> commands = Lists.newArrayList(); addNecessaryCommands(commands); resetState(); return commands; } private void addNecessaryCommands(Collection<ATCommand> commands) { if (internalState.isTakeOffRequested() && !currentNavData.getState().isFlying()) { commands.add(new FlightModeCommand(FlightMode.TAKE_OFF)); } if (internalState.isLandRequested() && currentNavData.getState().isFlying()) { commands.add(new FlightModeCommand(FlightMode.LAND)); } if (internalState.isEmergencyRequested() && currentNavData.getState().isEmergency()) { commands.add(new FlightModeCommand(FlightMode.EMERGENCY)); } if (internalState.isFlatTrimRequested()) { commands.add(new FlatTrimCommand()); } if (internalState.isMoveRequested()) { commands.add(new FlightMoveCommand(internalState.getRequestedRoll(), internalState.getRequestedPitch(), internalState.getRequestedYaw(), internalState.getRequestedGaz())); } } private void resetState() { // Flat trim and move are one-off command, so it is reset here internalState.setFlatTrimRequested(false); internalState.setMoveRequested(false); // Emergency state may reset itself // If it is set in nav data, there is no need for further checks if (internalState.isEmergencyRequested() && currentNavData.getState().isEmergency()) { internalState.setEmergencyRequested(false); } // Flying and landing states can be reset whenever the requested state occurs if (internalState.isTakeOffRequested() && currentNavData.getState().isFlying()) { internalState.setTakeOffRequested(false); } if (internalState.isLandRequested() && !currentNavData.getState().isFlying()) { internalState.setLandRequested(false); } } public void requestTakeOff() { internalState.setTakeOffRequested(true); internalState.setLandRequested(false); } public void requestLand() { internalState.setLandRequested(true); internalState.setTakeOffRequested(false); } public void requestEmergency() { internalState.setLandRequested(false); internalState.setTakeOffRequested(false); internalState.setEmergencyRequested(true); } public void requestFlatTrim() { internalState.setFlatTrimRequested(true); } @Override public void onNavData(NavData navData) { currentNavData = navData; } public void requestMove(float roll, float pitch, float yaw, float gaz) { if (Math.abs(roll - internalState.getRequestedRoll()) > MOVE_THRESHOLD || Math.abs(pitch - internalState.getRequestedPitch()) > MOVE_THRESHOLD || Math.abs(yaw - internalState.getRequestedYaw()) > MOVE_THRESHOLD || Math.abs(gaz - internalState.getRequestedGaz()) > MOVE_THRESHOLD) { internalState.setMoveRequested(true); internalState.setRequestedRoll(roll); internalState.setRequestedPitch(pitch); internalState.setRequestedYaw(yaw); internalState.setRequestedGaz(gaz); } } }