package com.o3dr.android.client.apis;
import android.content.Context;
import android.os.Bundle;
import android.util.SparseArray;
import com.o3dr.services.android.lib.model.AbstractCommandListener;
import com.o3dr.services.android.lib.model.action.Action;
import junit.framework.Assert;
import org.droidplanner.services.android.impl.mock.MockDrone;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import static com.o3dr.services.android.lib.drone.action.ControlActions.ACTION_SET_VELOCITY;
import static com.o3dr.services.android.lib.drone.action.ControlActions.EXTRA_VELOCITY_X;
import static com.o3dr.services.android.lib.drone.action.ControlActions.EXTRA_VELOCITY_Y;
import static com.o3dr.services.android.lib.drone.action.ControlActions.EXTRA_VELOCITY_Z;
/**
* Created by Fredia Huya-Kouadio on 10/23/15.
*/
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = com.o3dr.android.client.BuildConfig.class, sdk = 18)
public class ControlApiTest {
private static final SparseArray<float[][]> expectedVelocitiesPerAttitude = new SparseArray<>();
static {
expectedVelocitiesPerAttitude.append(0, new float[][]{{1f, 0f, 1f}, {1f, 0f, 1f}});
expectedVelocitiesPerAttitude.append(45, new float[][]{{1f, 1f, 1f}, {0f, (float) Math.sqrt(2), 1f}});
expectedVelocitiesPerAttitude.append(90, new float[][]{{1f, 1f, 1f}, {-1f, 1f, 1f}});
expectedVelocitiesPerAttitude.append(135, new float[][]{{1f, 1f, 1f}, {-(float) Math.sqrt(2), 0, 1f}});
expectedVelocitiesPerAttitude.append(180, new float[][]{{1f, 1f, 1f}, {-1f, -1f, 1f}});
expectedVelocitiesPerAttitude.append(225, new float[][]{{1f, 1f, 1f}, {0f, -(float) Math.sqrt(2), 1f}});
expectedVelocitiesPerAttitude.append(270, new float[][]{{1f, 1f, 1f}, {1f, -1f, 1f}});
expectedVelocitiesPerAttitude.append(315, new float[][]{{1f, 1f, 1f}, {(float) Math.sqrt(2), 0, 1f}});
expectedVelocitiesPerAttitude.append(360, new float[][]{{1f, 1f, 1f}, {1f, 1f, 1f}});
}
/**
* Tests the ControlApi#manualControl(...) method.
* Ensures the method correctly interpret its given parameters.
*
* @throws Exception
*/
@Test
public void testMoveAtVelocity() throws Exception {
final Context context = ShadowApplication.getInstance().getApplicationContext();
final MockDrone mockDrone = new MockDrone(context) {
@Override
public boolean performAsyncActionOnDroneThread(Action action, AbstractCommandListener listener) {
this.asyncAction = action;
return true;
}
};
final ControlApi controlApi = ControlApi.getApi(mockDrone);
//Test with the EARTH NED coordinate frame. What goes in should be what comes out.
final int testCount = 100;
for (int i = 0; i < testCount; i++) {
final float randomX = (float) ((Math.random() * 2) - 1f);
final float randomY = (float) ((Math.random() * 2) - 1f);
final float randomZ = (float) ((Math.random() * 2) - 1f);
controlApi.manualControl(randomX, randomY, randomZ, null);
Assert.assertTrue(mockDrone.getAsyncAction().getType().equals(ACTION_SET_VELOCITY));
Bundle params = mockDrone.getAsyncAction().getData();
Assert.assertEquals(params.getFloat(EXTRA_VELOCITY_X), randomX, 0.001);
Assert.assertEquals(params.getFloat(EXTRA_VELOCITY_Y), randomY, 0.001);
Assert.assertEquals(params.getFloat(EXTRA_VELOCITY_Z), randomZ, 0.001);
}
// //Test with the VEHICLE coordinate frame. The output is dependent on the vehicle attitude data.
// final Attitude attitude = new Attitude();
// final int expectedValuesCount = expectedVelocitiesPerAttitude.size();
// for(int i = 0; i < expectedValuesCount; i++) {
// final int yaw = expectedVelocitiesPerAttitude.keyAt(i);
// final float[][] paramsAndResults = expectedVelocitiesPerAttitude.valueAt(i);
// final float[] params = paramsAndResults[0];
//
// attitude.setYaw(yaw);
// mockDrone.setAttribute(AttributeType.ATTITUDE, attitude);
//
// controlApi.manualControl(ControlApi.VEHICLE_COORDINATE_FRAME, params[0], params[1], params[2], null);
//
// Assert.assertTrue(mockDrone.getAsyncAction().getType().equals(ACTION_SET_VELOCITY));
//
// final float[] expectedValues = paramsAndResults[1];
// Bundle data = mockDrone.getAsyncAction().getData();
// Assert.assertEquals("Invalid x velocity for attitude = " + yaw, data.getFloat(EXTRA_VELOCITY_X), expectedValues[0], 0.001);
// Assert.assertEquals("Invalid y velocity for attitude = " + yaw, data.getFloat(EXTRA_VELOCITY_Y), expectedValues[1], 0.001);
// Assert.assertEquals("Invalid z velocity for attitude = " + yaw, data.getFloat(EXTRA_VELOCITY_Z), expectedValues[2], 0.001);
// }
}
}