From d129a0d9e9c90cc2c18392811baf1dd6803188e8 Mon Sep 17 00:00:00 2001 From: ne0fhyk Date: Mon, 5 Jan 2015 17:47:34 -0800 Subject: [PATCH 1/4] updated mavlink library with the latest definitions files. added experimentation spline follow modes. --- AidlLib/build.gradle | 4 +- .../android/lib/gcs/follow/FollowType.java | 4 +- ClientLib/mobile/build.gradle | 4 +- ClientLib/mobile/libs/AidlLib.jar | Bin 454730 -> 458634 bytes .../services/android/api/DroneApi.java | 79 +++++++----- .../android/location/FusedLocation.java | 7 +- .../core/MAVLink/MavLinkModes.java | 121 +++++++++++------- .../core/drone/variables/GuidedPoint.java | 6 + .../core/gcs/follow/FollowAlgorithm.java | 7 +- .../core/gcs/follow/FollowLeash.java | 6 +- .../core/gcs/follow/FollowSplineAbove.java | 31 +++++ .../core/gcs/follow/FollowSplineLeash.java | 47 +++++++ .../core/gcs/location/Location.java | 64 ++++----- .../message_definitions/ardupilotmega.xml | 27 +++- .../Mavlink/message_definitions/common.xml | 114 +++++++++++++---- .../src/com/MAVLink/MAVLinkPacket.java | 6 +- .../Mavlink/src/com/MAVLink/Parser.java | 1 + .../src/com/MAVLink/ardupilotmega/CRC.java | 2 +- .../ardupilotmega/msg_mount_status.java | 6 +- .../Mavlink/src/com/MAVLink/common/CRC.java | 2 +- .../MAVLink/common/msg_battery_status.java | 8 +- .../common/msg_global_position_int.java | 2 +- .../MAVLink/common/msg_hil_optical_flow.java | 76 +++++++---- .../src/com/MAVLink/common/msg_ping.java | 2 +- .../msg_position_target_global_int.java | 20 ++- .../common/msg_position_target_local_ned.java | 20 ++- .../msg_set_position_target_global_int.java | 20 ++- .../msg_set_position_target_local_ned.java | 20 ++- .../com/MAVLink/enums/GRIPPER_ACTIONS.java | 11 ++ .../src/com/MAVLink/enums/MAV_AUTOPILOT.java | 3 +- .../src/com/MAVLink/enums/MAV_CMD.java | 5 +- .../src/com/MAVLink/enums/MAV_FRAME.java | 5 +- .../src/com/MAVLink/enums/MAV_TYPE.java | 4 +- 33 files changed, 527 insertions(+), 207 deletions(-) create mode 100644 dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineAbove.java create mode 100644 dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineLeash.java create mode 100644 dependencyLibs/Mavlink/src/com/MAVLink/enums/GRIPPER_ACTIONS.java diff --git a/AidlLib/build.gradle b/AidlLib/build.gradle index 0e56692d7d..da9d86edbf 100644 --- a/AidlLib/build.gradle +++ b/AidlLib/build.gradle @@ -7,8 +7,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 20023 - versionName '2.0.23' + versionCode 20024 + versionName '2.0.24' } defaultPublishConfig "release" diff --git a/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java b/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java index d283705eb4..29f9a975f0 100644 --- a/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java +++ b/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java @@ -13,7 +13,9 @@ public enum FollowType implements Parcelable { RIGHT("Right"), LEFT("Left"), CIRCLE("Circle"), - ABOVE("Above"); + ABOVE("Above"), + SPLINE_LEASH("Spline Leash"), + SPLINE_ABOVE("Spline Above"); private final String typeLabel; diff --git a/ClientLib/mobile/build.gradle b/ClientLib/mobile/build.gradle index 79fe516db8..75c3fb22ac 100644 --- a/ClientLib/mobile/build.gradle +++ b/ClientLib/mobile/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' ext { PUBLISH_ARTIFACT_ID = '3dr-services-lib' - PUBLISH_VERSION = '2.1.33' + PUBLISH_VERSION = '2.1.34' PROJECT_DESCRIPTION = "3DR Services Client Library" PROJECT_LABELS = ['3DR', '3DR Services', 'DroneAPI', 'Android'] PROJECT_LICENSES = ['Apache-2.0'] @@ -15,7 +15,7 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 20133 + versionCode 20134 versionName PUBLISH_VERSION } diff --git a/ClientLib/mobile/libs/AidlLib.jar b/ClientLib/mobile/libs/AidlLib.jar index 72a27a44ea53ebd1f4a82095e85ea547f86ef084..bc7dff46c50d21bf6b14a313f253eaadaa59d4eb 100644 GIT binary patch delta 48908 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 XZYIy_dD`K$!?rEes_pKM7*zWo-u(xI delta 44555 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 JY=B|F004Ztc2fWV diff --git a/ServiceApp/src/org/droidplanner/services/android/api/DroneApi.java b/ServiceApp/src/org/droidplanner/services/android/api/DroneApi.java index abf94451e6..48be2c52f5 100644 --- a/ServiceApp/src/org/droidplanner/services/android/api/DroneApi.java +++ b/ServiceApp/src/org/droidplanner/services/android/api/DroneApi.java @@ -657,36 +657,7 @@ public void setGuidedVelocity(double xVel, double yVel, double zVel) throws Remo @Override public void enableFollowMe(FollowType followType) throws RemoteException { - final FollowAlgorithm.FollowModes selectedMode; - switch (followType) { - case ABOVE: - selectedMode = FollowAlgorithm.FollowModes.ABOVE; - break; - - case LEAD: - selectedMode = FollowAlgorithm.FollowModes.LEAD; - break; - - case LEASH: - selectedMode = FollowAlgorithm.FollowModes.LEASH; - break; - - case CIRCLE: - selectedMode = FollowAlgorithm.FollowModes.CIRCLE; - break; - - case LEFT: - selectedMode = FollowAlgorithm.FollowModes.LEFT; - break; - - case RIGHT: - selectedMode = FollowAlgorithm.FollowModes.RIGHT; - break; - - default: - selectedMode = null; - break; - } + final FollowAlgorithm.FollowModes selectedMode = followTypeToMode(followType); if (selectedMode != null) { final Follow followMe = this.droneMgr.getFollowMe(); @@ -907,6 +878,46 @@ public void onReceivedMavLinkMessage(MAVLinkMessage msg) { } } + private static FollowAlgorithm.FollowModes followTypeToMode(FollowType followType){ + final FollowAlgorithm.FollowModes followMode; + + switch (followType) { + case ABOVE: + followMode = FollowAlgorithm.FollowModes.ABOVE; + break; + + case LEAD: + followMode = FollowAlgorithm.FollowModes.LEAD; + break; + + default: + case LEASH: + followMode = FollowAlgorithm.FollowModes.LEASH; + break; + + case CIRCLE: + followMode = FollowAlgorithm.FollowModes.CIRCLE; + break; + + case LEFT: + followMode = FollowAlgorithm.FollowModes.LEFT; + break; + + case RIGHT: + followMode = FollowAlgorithm.FollowModes.RIGHT; + break; + + case SPLINE_LEASH: + followMode = FollowAlgorithm.FollowModes.SPLINE_LEASH; + break; + + case SPLINE_ABOVE: + followMode = FollowAlgorithm.FollowModes.SPLINE_ABOVE; + break; + } + return followMode; + } + private static FollowType followModeToType(FollowAlgorithm.FollowModes followMode) { final FollowType followType; @@ -935,6 +946,14 @@ private static FollowType followModeToType(FollowAlgorithm.FollowModes followMod case ABOVE: followType = FollowType.ABOVE; break; + + case SPLINE_LEASH: + followType = FollowType.SPLINE_LEASH; + break; + + case SPLINE_ABOVE: + followType = FollowType.SPLINE_ABOVE; + break; } return followType; diff --git a/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java b/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java index fda0a14092..faf39cb7af 100644 --- a/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java +++ b/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java @@ -1,5 +1,7 @@ package org.droidplanner.services.android.location; +import org.droidplanner.core.helpers.coordinates.Coord3D; +import org.droidplanner.core.helpers.units.Altitude; import org.droidplanner.services.android.utils.GoogleApiClientManager; import org.droidplanner.services.android.utils.GoogleApiClientManager.GoogleApiClientTask; import org.droidplanner.core.gcs.location.Location.LocationFinder; @@ -103,8 +105,9 @@ public void onLocationChanged(Location androidLocation) { currentSpeed); org.droidplanner.core.gcs.location.Location location = new org.droidplanner.core.gcs.location.Location( - new Coord2D(androidLocation.getLatitude(), androidLocation.getLongitude()), - androidLocation.getBearing(), androidLocation.getSpeed(), isLocationAccurate); + new Coord3D(androidLocation.getLatitude(), androidLocation.getLongitude(), + new Altitude(androidLocation.getAltitude())), androidLocation.getBearing(), + androidLocation.getSpeed(), isLocationAccurate, androidLocation.getTime()); mLastLocation = androidLocation; receiver.onLocationChanged(location); diff --git a/dependencyLibs/Core/src/org/droidplanner/core/MAVLink/MavLinkModes.java b/dependencyLibs/Core/src/org/droidplanner/core/MAVLink/MavLinkModes.java index 3677f4872e..dd0ba25fb3 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/MAVLink/MavLinkModes.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/MAVLink/MavLinkModes.java @@ -1,57 +1,84 @@ package org.droidplanner.core.MAVLink; -import org.droidplanner.core.model.Drone; - import com.MAVLink.Messages.ApmModes; import com.MAVLink.common.msg_mission_item; +import com.MAVLink.common.msg_set_position_target_global_int; import com.MAVLink.common.msg_set_mode; import com.MAVLink.enums.MAV_CMD; import com.MAVLink.enums.MAV_FRAME; +import org.droidplanner.core.model.Drone; + public class MavLinkModes { - public static void setGuidedMode(Drone drone, double latitude, double longitude, double d) { - msg_mission_item msg = new msg_mission_item(); - msg.seq = 0; - msg.current = 2; // TODO use guided mode enum - msg.frame = MAV_FRAME.MAV_FRAME_GLOBAL; - msg.command = MAV_CMD.MAV_CMD_NAV_WAYPOINT; // - msg.param1 = 0; // TODO use correct parameter - msg.param2 = 0; // TODO use correct parameter - msg.param3 = 0; // TODO use correct parameter - msg.param4 = 0; // TODO use correct parameter - msg.x = (float) latitude; - msg.y = (float) longitude; - msg.z = (float) d; - msg.autocontinue = 1; // TODO use correct parameter - msg.target_system = drone.getSysid(); - msg.target_component = drone.getCompid(); - drone.getMavClient().sendMavPacket(msg.pack()); - } - - public static void sendGuidedVelocity(Drone drone, double xVel, double yVel, double zVel) { - msg_mission_item msg = new msg_mission_item(); - msg.seq = 0; - msg.current = 2; // TODO use guided mode enum - msg.frame = MAV_FRAME.MAV_FRAME_GLOBAL; - msg.command = 91; // MAV_CMD_NAV_VELOCITY - msg.param1 = 0; // TODO use correct parameter - msg.param2 = 0; // TODO use correct parameter - msg.param3 = 0; // TODO use correct parameter - msg.param4 = 0; // TODO use correct parameter - msg.x = (float) (xVel ); - msg.y = (float) (yVel); - msg.z = (float) (zVel); - msg.autocontinue = 1; // TODO use correct parameter - msg.target_system = drone.getSysid(); - msg.target_component = drone.getCompid(); - drone.getMavClient().sendMavPacket(msg.pack()); - } - - public static void changeFlightMode(Drone drone, ApmModes mode) { - msg_set_mode msg = new msg_set_mode(); - msg.target_system = drone.getSysid(); - msg.base_mode = 1; // TODO use meaningful constant - msg.custom_mode = mode.getNumber(); - drone.getMavClient().sendMavPacket(msg.pack()); - } + + private static final int MAVLINK_SET_POS_TYPE_MASK_POS_IGNORE = ((1 << 0) | (1 << 1) | (1 << 2)); + private static final int MAVLINK_SET_POS_TYPE_MASK_VEL_IGNORE = ((1 << 3) | (1 << 4) | (1 << 5)); + private static final int MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE = ((1 << 6) | (1 << 7) | (1 << 8)); + + public static void setGuidedMode(Drone drone, double latitude, double longitude, double d) { + msg_mission_item msg = new msg_mission_item(); + msg.seq = 0; + msg.current = 2; // TODO use guided mode enum + msg.frame = MAV_FRAME.MAV_FRAME_GLOBAL; + msg.command = MAV_CMD.MAV_CMD_NAV_WAYPOINT; // + msg.param1 = 0; // TODO use correct parameter + msg.param2 = 0; // TODO use correct parameter + msg.param3 = 0; // TODO use correct parameter + msg.param4 = 0; // TODO use correct parameter + msg.x = (float) latitude; + msg.y = (float) longitude; + msg.z = (float) d; + msg.autocontinue = 1; // TODO use correct parameter + msg.target_system = drone.getSysid(); + msg.target_component = drone.getCompid(); + drone.getMavClient().sendMavPacket(msg.pack()); + } + + public static void sendGuidedPosition(Drone drone, double latitude, double longitude, double altitude){ + msg_set_position_target_global_int msg = new msg_set_position_target_global_int(); + msg.type_mask = MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE | MAVLINK_SET_POS_TYPE_MASK_VEL_IGNORE; + msg.coordinate_frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT; + msg.lat_int = (int) (latitude * 1E7); + msg.lon_int = (int) (longitude * 1E7); + msg.alt = (float) altitude; + msg.target_system = drone.getSysid(); + msg.target_component = drone.getCompid(); + drone.getMavClient().sendMavPacket(msg.pack()); + } + + public static void sendGuidedVelocity(Drone drone, double xVel, double yVel, double zVel){ + msg_set_position_target_global_int msg = new msg_set_position_target_global_int(); + msg.type_mask = MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE | MAVLINK_SET_POS_TYPE_MASK_POS_IGNORE; + msg.coordinate_frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT; + msg.vx = (float) xVel; + msg.vy = (float) yVel; + msg.vz = (float) zVel; + msg.target_system = drone.getSysid(); + msg.target_component = drone.getCompid(); + drone.getMavClient().sendMavPacket(msg.pack()); + } + + public static void sendGuidedPositionAndVelocity(Drone drone, double latitude, double longitude, double altitude, + double xVel, double yVel, double zVel){ + msg_set_position_target_global_int msg = new msg_set_position_target_global_int(); + msg.type_mask = MAVLINK_SET_POS_TYPE_MASK_ACC_IGNORE; + msg.coordinate_frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT; + msg.lat_int = (int) (latitude * 1E7); + msg.lon_int = (int) (longitude * 1E7); + msg.alt = (float) altitude; + msg.vx = (float) xVel; + msg.vy = (float) yVel; + msg.vz = (float) zVel; + msg.target_system = drone.getSysid(); + msg.target_component = drone.getCompid(); + drone.getMavClient().sendMavPacket(msg.pack()); + } + + public static void changeFlightMode(Drone drone, ApmModes mode) { + msg_set_mode msg = new msg_set_mode(); + msg.target_system = drone.getSysid(); + msg.base_mode = 1; // TODO use meaningful constant + msg.custom_mode = mode.getNumber(); + drone.getMavClient().sendMavPacket(msg.pack()); + } } diff --git a/dependencyLibs/Core/src/org/droidplanner/core/drone/variables/GuidedPoint.java b/dependencyLibs/Core/src/org/droidplanner/core/drone/variables/GuidedPoint.java index f5ab6e798f..8e67747727 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/drone/variables/GuidedPoint.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/drone/variables/GuidedPoint.java @@ -6,6 +6,7 @@ import org.droidplanner.core.drone.DroneInterfaces.OnDroneListener; import org.droidplanner.core.drone.DroneVariable; import org.droidplanner.core.helpers.coordinates.Coord2D; +import org.droidplanner.core.helpers.coordinates.Coord3D; import org.droidplanner.core.helpers.units.Altitude; import org.droidplanner.core.model.Drone; @@ -263,4 +264,9 @@ public void newGuidedVelocity( double xVel, double yVel, double zVel){ MavLinkModes.sendGuidedVelocity(myDrone,xVel,yVel,zVel); } + public void newGuidedPositionAndVelocity(Coord2D coord3d, double xVel, double yVel, double zVel){ + MavLinkModes.sendGuidedPositionAndVelocity(myDrone, coord3d.getLat(), coord3d.getLng(), + altitude.valueInMeters(), xVel, yVel, zVel); + } + } diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java index acd5ee63f2..d463619aa7 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java @@ -23,7 +23,8 @@ public void changeRadius(Double radius) { } public enum FollowModes { - LEASH("Leash"), LEAD("Lead"), RIGHT("Right"), LEFT("Left"), CIRCLE("Orbit"), ABOVE("Above"); + LEASH("Leash"), LEAD("Lead"), RIGHT("Right"), LEFT("Left"), CIRCLE("Orbit"), ABOVE("Above"), + SPLINE_LEASH("Spline Leash"), SPLINE_ABOVE("Spline Above"); private String name; @@ -54,6 +55,10 @@ public FollowAlgorithm getAlgorithmType(Drone drone) { return new FollowCircle(drone, new Length(15.0), 10.0); case ABOVE: return new FollowAbove(drone, new Length(0.0)); + case SPLINE_LEASH: + return new FollowSplineLeash(drone, new Length(8.0)); + case SPLINE_ABOVE: + return new FollowSplineAbove(drone, new Length(0.0)); } return null; // Should never reach this } diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowLeash.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowLeash.java index 7935dfaf70..6af03462f6 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowLeash.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowLeash.java @@ -28,10 +28,8 @@ public void processNewLocation(Location location) { final double radiusInMeters = radius.valueInMeters(); if (GeoTools.getDistance(locationCoord, dronePosition).valueInMeters() > radiusInMeters) { - double headingGCStoDrone = GeoTools.getHeadingFromCoordinates(locationCoord, - dronePosition); - Coord2D goCoord = GeoTools.newCoordFromBearingAndDistance(locationCoord, - headingGCStoDrone, radiusInMeters); + double headingGCStoDrone = GeoTools.getHeadingFromCoordinates(locationCoord, dronePosition); + Coord2D goCoord = GeoTools.newCoordFromBearingAndDistance(locationCoord, headingGCStoDrone, radiusInMeters); drone.getGuidedPoint().newGuidedCoord(goCoord); } } diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineAbove.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineAbove.java new file mode 100644 index 0000000000..10ff9ae124 --- /dev/null +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineAbove.java @@ -0,0 +1,31 @@ +package org.droidplanner.core.gcs.follow; + +import org.droidplanner.core.gcs.location.Location; +import org.droidplanner.core.helpers.coordinates.Coord2D; +import org.droidplanner.core.helpers.units.Length; +import org.droidplanner.core.model.Drone; + +/** + * Created by fhuya on 1/5/15. + */ +public class FollowSplineAbove extends FollowAlgorithm { + @Override + public void processNewLocation(Location location) { + Coord2D gcsLoc = new Coord2D(location.getCoord().getLat(), location.getCoord().getLng()); + double speed = location.getSpeed(); + double bearing = location.getBearing(); + double bearingInRad = Math.toRadians(bearing); + double xVel = speed * Math.cos(bearingInRad); + double yVel = speed * Math.sin(bearingInRad); + drone.getGuidedPoint().newGuidedPositionAndVelocity(gcsLoc, xVel, yVel, 0); + } + + @Override + public FollowModes getType() { + return FollowModes.SPLINE_ABOVE; + } + + public FollowSplineAbove(Drone drone, Length length) { + super(drone, length); + } +} diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineLeash.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineLeash.java new file mode 100644 index 0000000000..e2fd664a85 --- /dev/null +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowSplineLeash.java @@ -0,0 +1,47 @@ +package org.droidplanner.core.gcs.follow; + +import org.droidplanner.core.drone.variables.Altitude; +import org.droidplanner.core.gcs.location.Location; +import org.droidplanner.core.helpers.coordinates.Coord2D; +import org.droidplanner.core.helpers.coordinates.Coord3D; +import org.droidplanner.core.helpers.geoTools.GeoTools; +import org.droidplanner.core.helpers.units.Length; +import org.droidplanner.core.model.Drone; + +/** + * Created by fhuya on 1/5/15. + */ +public class FollowSplineLeash extends FollowAlgorithm { + @Override + public void processNewLocation(Location location) { + final Coord3D userLoc = location.getCoord(); + final Altitude droneAlt = drone.getAltitude(); + final Coord2D droneLoc = drone.getGps().getPosition(); + + if(userLoc == null || droneLoc == null) + return; + + final double radiusInMeters = radius.valueInMeters(); + if(GeoTools.getDistance(userLoc, droneLoc).valueInMeters() > radiusInMeters){ + double headingGCSToDrone = GeoTools.getHeadingFromCoordinates(userLoc, droneLoc); + Coord2D goCoord = GeoTools.newCoordFromBearingAndDistance(userLoc, headingGCSToDrone, radiusInMeters); + + double speed = location.getSpeed(); + double bearing = location.getBearing(); + double bearingInRad = Math.toRadians(bearing); + double xVel = speed * Math.cos(bearingInRad); + double yVel = speed * Math.sin(bearingInRad); + drone.getGuidedPoint().newGuidedPositionAndVelocity(goCoord, xVel, yVel, 0); + } + + } + + @Override + public FollowModes getType() { + return FollowModes.SPLINE_LEASH; + } + + public FollowSplineLeash(Drone drone, Length length) { + super(drone, length); + } +} diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/location/Location.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/location/Location.java index 4e2b1988eb..922bb81d27 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/gcs/location/Location.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/location/Location.java @@ -1,51 +1,53 @@ package org.droidplanner.core.gcs.location; -import org.droidplanner.core.helpers.coordinates.Coord2D; +import org.droidplanner.core.helpers.coordinates.Coord3D; public class Location { - public interface LocationReceiver { - public void onLocationChanged(Location location); - } + public interface LocationReceiver { + public void onLocationChanged(Location location); + } - public interface LocationFinder { - public void enableLocationUpdates(); + public interface LocationFinder { + public void enableLocationUpdates(); - public void disableLocationUpdates(); + public void disableLocationUpdates(); - public void setLocationListener(LocationReceiver receiver); - } + public void setLocationListener(LocationReceiver receiver); + } - private Coord2D coordinate; - private double heading = 0.0; - private double speed = 0.0; + private Coord3D coordinate; + private double heading = 0.0; + private double speed = 0.0; private boolean isAccurate; + private long fixTime; - public Location(Coord2D coord2d){ - coordinate = coord2d; - } - - public Location(Coord2D coord2d, float heading, float speed, boolean isAccurate) { - coordinate = coord2d; - this.heading = heading; - this.speed = speed; + public Location(Coord3D coord3d, float heading, float speed, boolean isAccurate, long fixTime) { + coordinate = coord3d; + this.heading = heading; + this.speed = speed; this.isAccurate = isAccurate; - } + this.fixTime = fixTime; + } - public Coord2D getCoord() { - return coordinate; - } + public Coord3D getCoord() { + return coordinate; + } - public boolean isAccurate(){ + public boolean isAccurate() { return this.isAccurate; } - public double getBearing() { - return heading; - } + public double getBearing() { + return heading; + } + + public double getSpeed() { + return speed; + } - public double getSpeed() { - return speed; - } + public long getFixTime() { + return fixTime; + } } diff --git a/dependencyLibs/Mavlink/message_definitions/ardupilotmega.xml b/dependencyLibs/Mavlink/message_definitions/ardupilotmega.xml index 072e1d61fa..255fdb82da 100644 --- a/dependencyLibs/Mavlink/message_definitions/ardupilotmega.xml +++ b/dependencyLibs/Mavlink/message_definitions/ardupilotmega.xml @@ -23,6 +23,16 @@ Empty Empty + + Mission command to operate EPM gripper + gripper number (a number from 1 to max number of grippers on the vehicle) + gripper action (0=release, 1=grab. See GRIPPER_ACTIONS enum) + Empty + Empty + Empty + Empty + Empty + @@ -75,6 +85,17 @@ + + + Gripper actions. + + gripper release of cargo + + + gripper grabs onto cargo + + + Camera heartbeat, announce camera component ID at 1hz @@ -194,9 +215,9 @@ Message with some status from APM to GCS about camera or antenna mount System ID Component ID - pitch(deg*100) or lat, depending on mount mode - roll(deg*100) or lon depending on mount mode - yaw(deg*100) or alt (in cm) depending on mount mode + pitch(deg*100) + roll(deg*100) + yaw(deg*100) diff --git a/dependencyLibs/Mavlink/message_definitions/common.xml b/dependencyLibs/Mavlink/message_definitions/common.xml index e88891efa1..f168c8ccd8 100644 --- a/dependencyLibs/Mavlink/message_definitions/common.xml +++ b/dependencyLibs/Mavlink/message_definitions/common.xml @@ -55,6 +55,9 @@ Aerob -- http://aerob.ru + + ASLUAV autopilot -- http://www.asl.ethz.ch + @@ -114,6 +117,13 @@ Onboard companion controller + + Two-rotor VTOL using control surfaces in vertical operation in addition. Tailsitter. + + + Quad-rotor VTOL using a V-shaped quad config in vertical operation. Tailsitter. + + @@ -416,6 +426,12 @@ Local coordinate frame, Z-down (x: east, y: north, z: up) + + Global coordinate frame, WGS84 coordinate system. First value / x: latitude in degrees*1.0e-7, second value / y: longitude in degrees*1.0e-7, third value / z: positive altitude over mean sea level (MSL) + + + Global coordinate frame, WGS84 coordinate system, relative altitude over ground with respect to the home position. First value / x: latitude in degrees*10e-7, second value / y: longitude in degrees*10e-7, third value / z: positive altitude with 0 being at the altitude of the home location. + Offset to the current local frame. Anything expressed in this frame should be added to the current local frame position. @@ -428,6 +444,9 @@ Global coordinate frame with above terrain level altitude. WGS84 coordinate system, relative altitude over terrain with respect to the waypoint coordinate. First value / x: latitude in degrees, second value / y: longitude in degrees, third value / z: positive altitude in meters with 0 being at ground level in terrain model. + + Global coordinate frame with above terrain level altitude. WGS84 coordinate system, relative altitude over terrain with respect to the waypoint coordinate. First value / x: latitude in degrees*10e-7, second value / y: longitude in degrees*10e-7, third value / z: positive altitude in meters with 0 being at ground level in terrain model. + @@ -559,6 +578,16 @@ Latitude Longitude Altitude + + + Continue on the current course and climb/descend to specified altitude. When the altitude is reached continue to the next command (i.e., don't proceed to the next command until the desired altitude is reached. + Empty + Empty + Empty + Empty + Empty + Empty + Desired altitude in meters Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. @@ -765,7 +794,17 @@ Empty Empty Empty - + + + Mission command to perform a landing. This is used as a marker in a mission to tell the autopilot where a sequence of mission items that represents a landing starts. It may also be sent via a COMMAND_LONG to trigger a landing, in which case the nearest (geographically) landing sequence in the mission will be used. The Latitude/Longitude is optional, and may be set to 0/0 if not needed. If specified then it will be used to help find the closest landing sequence. + Empty + Empty + Empty + Empty + Latitude + Longitude + Empty + Mission command to perform a landing from a rally point. Break altitude (meters) @@ -1032,8 +1071,10 @@ Create a panorama at the current position - Viewing angle horizontal of the panorama - Viewing angle vertical of panorama + Viewing angle horizontal of the panorama (in degrees, +- 0.5 the total angle) + Viewing angle vertical of panorama (in degrees) + Speed of the horizontal rotation (in degrees per second) + Speed of the vertical rotation (in degrees per second) @@ -1454,7 +1495,7 @@ A ping message either requesting or responding to a ping. This allows to measure the system latencies, including serial port, radio modem and UDP connections. - Unix timestamp in microseconds + Unix timestamp in microseconds or since system boot if smaller than MAVLink epoch (1.1.2009) PING sequence 0: request ping from all receiving systems, if greater than 0: message is a ping response and number is the system id of the requesting system 0: request ping from all receiving components, if greater than 0: message is a ping response and number is the system id of the requesting system @@ -1612,7 +1653,7 @@ Timestamp (milliseconds since system boot) Latitude, expressed as * 1E7 Longitude, expressed as * 1E7 - Altitude in meters, expressed as * 1000 (millimeters), above MSL + Altitude in meters, expressed as * 1000 (millimeters), WGS84 (not AMSL) Altitude above ground in meters, expressed as * 1000 (millimeters) Ground X Speed (Latitude), expressed as m/s * 100 Ground Y Speed (Longitude), expressed as m/s * 100 @@ -1889,7 +1930,7 @@ PARAM3, see MAV_CMD enum PARAM4, see MAV_CMD enum PARAM5 / local: x position in meters * 1e4, global: latitude in degrees * 10^7 - PARAM6 / y position: local: x position in meters * 1e4, global: longitude in degrees *10^7 + PARAM6 / y position: local: x position in meters * 1e4, global: longitude in degrees *10^7 PARAM7 / z position: global: altitude in meters (relative or absolute, depending on frame. @@ -1974,7 +2015,7 @@ System ID Component ID Valid options are: MAV_FRAME_LOCAL_NED = 1, MAV_FRAME_LOCAL_OFFSET_NED = 7, MAV_FRAME_BODY_NED = 8, MAV_FRAME_BODY_OFFSET_NED = 9 - Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate X Position in NED frame in meters Y Position in NED frame in meters Z Position in NED frame in meters (note, altitude is negative in NED) @@ -1984,12 +2025,14 @@ X acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Y acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Z acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N + yaw setpoint in rad + yaw rate setpoint in rad/s Set vehicle position, velocity and acceleration setpoint in local frame. Timestamp in milliseconds since system boot Valid options are: MAV_FRAME_LOCAL_NED = 1, MAV_FRAME_LOCAL_OFFSET_NED = 7, MAV_FRAME_BODY_NED = 8, MAV_FRAME_BODY_OFFSET_NED = 9 - Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate X Position in NED frame in meters Y Position in NED frame in meters Z Position in NED frame in meters (note, altitude is negative in NED) @@ -1999,6 +2042,8 @@ X acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Y acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Z acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N + yaw setpoint in rad + yaw rate setpoint in rad/s Set vehicle position, velocity and acceleration setpoint in the WGS84 coordinate system. @@ -2006,7 +2051,7 @@ System ID Component ID Valid options are: MAV_FRAME_GLOBAL_INT = 5, MAV_FRAME_GLOBAL_RELATIVE_ALT_INT = 6, MAV_FRAME_GLOBAL_TERRAIN_ALT_INT = 11 - Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate X Position in WGS84 frame in 1e7 * meters Y Position in WGS84 frame in 1e7 * meters Altitude in meters in WGS84 altitude, not AMSL if absolute or relative, above terrain if GLOBAL_TERRAIN_ALT_INT @@ -2016,12 +2061,14 @@ X acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Y acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Z acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N + yaw setpoint in rad + yaw rate setpoint in rad/s Set vehicle position, velocity and acceleration setpoint in the WGS84 coordinate system. Timestamp in milliseconds since system boot. The rationale for the timestamp in the setpoint is to allow the system to compensate for the transport delay of the setpoint. This allows the system to compensate processing latency. Valid options are: MAV_FRAME_GLOBAL_INT = 5, MAV_FRAME_GLOBAL_RELATIVE_ALT_INT = 6, MAV_FRAME_GLOBAL_TERRAIN_ALT_INT = 11 - Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate X Position in WGS84 frame in 1e7 * meters Y Position in WGS84 frame in 1e7 * meters Altitude in meters in WGS84 altitude, not AMSL if absolute or relative, above terrain if GLOBAL_TERRAIN_ALT_INT @@ -2031,6 +2078,8 @@ X acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Y acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N Z acceleration or force (if bit 10 of type_mask is set) in NED frame in meter / s^2 or N + yaw setpoint in rad + yaw rate setpoint in rad/s The offset in X, Y, Z and yaw between the LOCAL_POSITION_NED messages of MAV X and the global coordinate frame in NED coordinates. Coordinate frame is right-handed, Z-axis down (aeronautical frame, NED / north-east-down convention) @@ -2154,14 +2203,20 @@ Temperature in degrees celsius Bitmask for fields that have updated since last message, bit 0 = xacc, bit 12: temperature - - Optical flow from an omnidirectional flow sensor (e.g. PX4FLOW with wide angle lens) + + Optical flow from an angular rate flow sensor (e.g. PX4FLOW or mouse sensor) Timestamp (microseconds, synced to UNIX time or since system boot) Sensor ID - Flow in deci pixels (1 = 0.1 pixel) on left hemisphere - Flow in deci pixels (1 = 0.1 pixel) on right hemisphere - Optical flow quality / confidence. 0: bad, 255: maximum quality - Front distance in meters. Positive value (including zero): distance known. Negative value: Unknown distance + Integration time in microseconds. Divide integrated_x and integrated_y by the integration time to obtain average flow. The integration time also indicates the. + Flow in radians around X axis (Sensor RH rotation about the X axis induces a positive flow. Sensor linear motion along the positive Y axis induces a negative flow.) + Flow in radians around Y axis (Sensor RH rotation about the Y axis induces a positive flow. Sensor linear motion along the positive X axis induces a positive flow.) + RH rotation around X axis (rad) + RH rotation around Y axis (rad) + RH rotation around Z axis (rad) + Temperature * 100 in centi-degrees Celsius + Optical flow quality / confidence. 0: no valid flow, 255: maximum quality + Time in microseconds since the distance was sampled. + Distance to the center of the flow field in meters. Positive value (including zero): distance known. Negative value: Unknown distance. The IMU readings in SI units in NED body frame @@ -2224,6 +2279,11 @@ System ID (0 for broadcast) Component ID (0 for broadcast) Variable length payload. The length is defined by the remaining message length when subtracting the header and other fields. The entire content of this block is opaque unless you understand any the encoding message_type. The particular encoding used can be extension specific and might not always be documented as part of the mavlink specification. + + + Time synchronization message. + Time sync timestamp 1 + Time sync timestamp 2 The global position, as returned by the Global Positioning System (GPS). This is @@ -2243,15 +2303,19 @@ Number of satellites visible. If unknown, set to 255 - Simulated optical flow from a flow sensor (e.g. optical mouse sensor) - Timestamp (UNIX) + Simulated optical flow from a flow sensor (e.g. PX4FLOW or optical mouse sensor) + Timestamp (microseconds, synced to UNIX time or since system boot) Sensor ID - Flow in pixels in x-sensor direction - Flow in pixels in y-sensor direction - Flow in meters in x-sensor direction, angular-speed compensated - Flow in meters in y-sensor direction, angular-speed compensated - Optical flow quality / confidence. 0: bad, 255: maximum quality - Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + Integration time in microseconds. Divide integrated_x and integrated_y by the integration time to obtain average flow. The integration time also indicates the. + Flow in radians around X axis (Sensor RH rotation about the X axis induces a positive flow. Sensor linear motion along the positive Y axis induces a negative flow.) + Flow in radians around Y axis (Sensor RH rotation about the Y axis induces a positive flow. Sensor linear motion along the positive X axis induces a positive flow.) + RH rotation around X axis (rad) + RH rotation around Y axis (rad) + RH rotation around Z axis (rad) + Temperature * 100 in centi-degrees Celsius + Optical flow quality / confidence. 0: no valid flow, 255: maximum quality + Time in microseconds since the distance was sampled. + Distance to the center of the flow field in meters. Positive value (including zero): distance known. Negative value: Unknown distance. Sent from simulation to autopilot, avoids in contrast to HIL_STATE singularities. This packet is useful for high throughput applications such as hardware in the loop simulations. @@ -2450,7 +2514,7 @@ Battery information Battery ID - Function of the battery + Function of the battery Type (chemistry) of the battery Temperature of the battery in centi-degrees celsius. INT16_MAX for unknown temperature. Battery voltage of cells, in millivolts (1 = 1 millivolt) diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/MAVLinkPacket.java b/dependencyLibs/Mavlink/src/com/MAVLink/MAVLinkPacket.java index f77aaa9522..f9d8688a43 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/MAVLinkPacket.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/MAVLinkPacket.java @@ -333,8 +333,8 @@ public MAVLinkMessage unpack() { return new msg_vicon_position_estimate(this); case msg_highres_imu.MAVLINK_MSG_ID_HIGHRES_IMU: return new msg_highres_imu(this); - case msg_omnidirectional_flow.MAVLINK_MSG_ID_OMNIDIRECTIONAL_FLOW: - return new msg_omnidirectional_flow(this); + case msg_optical_flow_rad.MAVLINK_MSG_ID_OPTICAL_FLOW_RAD: + return new msg_optical_flow_rad(this); case msg_hil_sensor.MAVLINK_MSG_ID_HIL_SENSOR: return new msg_hil_sensor(this); case msg_sim_state.MAVLINK_MSG_ID_SIM_STATE: @@ -343,6 +343,8 @@ public MAVLinkMessage unpack() { return new msg_radio_status(this); case msg_file_transfer_protocol.MAVLINK_MSG_ID_FILE_TRANSFER_PROTOCOL: return new msg_file_transfer_protocol(this); + case msg_timesync.MAVLINK_MSG_ID_TIMESYNC: + return new msg_timesync(this); case msg_hil_gps.MAVLINK_MSG_ID_HIL_GPS: return new msg_hil_gps(this); case msg_hil_optical_flow.MAVLINK_MSG_ID_HIL_OPTICAL_FLOW: diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/Parser.java b/dependencyLibs/Mavlink/src/com/MAVLink/Parser.java index 8161994758..cb31512bfc 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/Parser.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/Parser.java @@ -1,5 +1,6 @@ package com.MAVLink; +import com.MAVLink.MAVLinkPacket; import com.MAVLink.Messages.MAVLinkStats; public class Parser { diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/CRC.java b/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/CRC.java index d0eafba187..ce815d97e6 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/CRC.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/CRC.java @@ -7,7 +7,7 @@ * */ public class CRC { - private final int[] MAVLINK_MESSAGE_CRCS = {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 0, 0, 0, 0, 15, 3, 0, 0, 0, 0, 0, 153, 183, 51, 82, 118, 148, 21, 0, 243, 124, 0, 0, 38, 20, 158, 152, 143, 0, 0, 0, 106, 49, 22, 29, 12, 241, 233, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 93, 211, 108, 32, 185, 84, 0, 0, 124, 119, 4, 76, 128, 56, 116, 134, 237, 203, 250, 87, 203, 220, 25, 226, 0, 29, 223, 85, 6, 229, 203, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 49, 0, 134, 219, 208, 188, 84, 22, 19, 21, 134, 0, 78, 68, 189, 127, 154, 21, 21, 144, 1, 234, 73, 181, 22, 83, 167, 138, 234, 240, 47, 189, 52, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 204, 49, 170, 44, 83, 46, 0}; + private final int[] MAVLINK_MESSAGE_CRCS = {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 0, 0, 0, 0, 15, 3, 0, 0, 0, 0, 0, 153, 183, 51, 82, 118, 148, 21, 0, 243, 124, 0, 0, 38, 20, 158, 152, 143, 0, 0, 0, 106, 49, 22, 143, 140, 5, 150, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 93, 138, 108, 32, 185, 84, 34, 0, 124, 237, 4, 76, 128, 56, 116, 134, 237, 203, 250, 87, 203, 220, 25, 226, 0, 29, 223, 85, 6, 229, 203, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 49, 0, 134, 219, 208, 188, 84, 22, 19, 21, 134, 0, 78, 68, 189, 127, 154, 21, 21, 144, 1, 234, 73, 181, 22, 83, 167, 138, 234, 240, 47, 189, 52, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 204, 49, 170, 44, 83, 46, 0}; private static final int CRC_INIT_VALUE = 0xffff; private int CRCvalue; diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/msg_mount_status.java b/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/msg_mount_status.java index 7750cb542f..87e05d8ec5 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/msg_mount_status.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/ardupilotmega/msg_mount_status.java @@ -16,15 +16,15 @@ public class msg_mount_status extends MAVLinkMessage{ /** - * pitch(deg*100) or lat, depending on mount mode + * pitch(deg*100) */ public int pointing_a; /** - * roll(deg*100) or lon depending on mount mode + * roll(deg*100) */ public int pointing_b; /** - * yaw(deg*100) or alt (in cm) depending on mount mode + * yaw(deg*100) */ public int pointing_c; /** diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/CRC.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/CRC.java index 5939e4f494..79c31a97bd 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/CRC.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/CRC.java @@ -7,7 +7,7 @@ * */ public class CRC { - private final int[] MAVLINK_MESSAGE_CRCS = {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 0, 0, 0, 0, 15, 3, 0, 0, 0, 0, 0, 153, 183, 51, 82, 118, 148, 21, 0, 243, 124, 0, 0, 38, 20, 158, 152, 143, 0, 0, 0, 106, 49, 22, 29, 12, 241, 233, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 93, 211, 108, 32, 185, 84, 0, 0, 124, 119, 4, 76, 128, 56, 116, 134, 237, 203, 250, 87, 203, 220, 25, 226, 0, 29, 223, 85, 6, 229, 203, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 204, 49, 170, 44, 83, 46, 0}; + private final int[] MAVLINK_MESSAGE_CRCS = {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 0, 0, 0, 0, 15, 3, 0, 0, 0, 0, 0, 153, 183, 51, 82, 118, 148, 21, 0, 243, 124, 0, 0, 38, 20, 158, 152, 143, 0, 0, 0, 106, 49, 22, 143, 140, 5, 150, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 93, 138, 108, 32, 185, 84, 34, 0, 124, 237, 4, 76, 128, 56, 116, 134, 237, 203, 250, 87, 203, 220, 25, 226, 0, 29, 223, 85, 6, 229, 203, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 154, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 204, 49, 170, 44, 83, 46, 0}; private static final int CRC_INIT_VALUE = 0xffff; private int CRCvalue; diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_battery_status.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_battery_status.java index 3049a0547e..be07e50e32 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_battery_status.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_battery_status.java @@ -42,7 +42,7 @@ public class msg_battery_status extends MAVLinkMessage{ /** * Function of the battery */ - public byte function; + public byte battery_function; /** * Type (chemistry) of the battery */ @@ -71,7 +71,7 @@ public MAVLinkPacket pack(){ } packet.payload.putShort(current_battery); packet.payload.putByte(id); - packet.payload.putByte(function); + packet.payload.putByte(battery_function); packet.payload.putByte(type); packet.payload.putByte(battery_remaining); @@ -93,7 +93,7 @@ public void unpack(MAVLinkPayload payload) { } this.current_battery = payload.getShort(); this.id = payload.getByte(); - this.function = payload.getByte(); + this.battery_function = payload.getByte(); this.type = payload.getByte(); this.battery_remaining = payload.getByte(); @@ -125,7 +125,7 @@ public msg_battery_status(MAVLinkPacket mavLinkPacket){ * Returns a string with the MSG name and data */ public String toString(){ - return "MAVLINK_MSG_ID_BATTERY_STATUS -"+" current_consumed:"+current_consumed+" energy_consumed:"+energy_consumed+" temperature:"+temperature+" voltages:"+voltages+" current_battery:"+current_battery+" id:"+id+" function:"+function+" type:"+type+" battery_remaining:"+battery_remaining+""; + return "MAVLINK_MSG_ID_BATTERY_STATUS -"+" current_consumed:"+current_consumed+" energy_consumed:"+energy_consumed+" temperature:"+temperature+" voltages:"+voltages+" current_battery:"+current_battery+" id:"+id+" battery_function:"+battery_function+" type:"+type+" battery_remaining:"+battery_remaining+""; } } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_global_position_int.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_global_position_int.java index 31515bb7de..db6c4e7a58 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_global_position_int.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_global_position_int.java @@ -29,7 +29,7 @@ public class msg_global_position_int extends MAVLinkMessage{ */ public int lon; /** - * Altitude in meters, expressed as * 1000 (millimeters), above MSL + * Altitude in meters, expressed as * 1000 (millimeters), WGS84 (not AMSL) */ public int alt; /** diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_hil_optical_flow.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_hil_optical_flow.java index 5a01f35188..be2996a022 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_hil_optical_flow.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_hil_optical_flow.java @@ -6,45 +6,61 @@ //import android.util.Log; /** - * Simulated optical flow from a flow sensor (e.g. optical mouse sensor) + * Simulated optical flow from a flow sensor (e.g. PX4FLOW or optical mouse sensor) */ public class msg_hil_optical_flow extends MAVLinkMessage{ public static final int MAVLINK_MSG_ID_HIL_OPTICAL_FLOW = 114; - public static final int MAVLINK_MSG_LENGTH = 26; + public static final int MAVLINK_MSG_LENGTH = 44; private static final long serialVersionUID = MAVLINK_MSG_ID_HIL_OPTICAL_FLOW; /** - * Timestamp (UNIX) + * Timestamp (microseconds, synced to UNIX time or since system boot) */ public long time_usec; /** - * Flow in meters in x-sensor direction, angular-speed compensated + * Integration time in microseconds. Divide integrated_x and integrated_y by the integration time to obtain average flow. The integration time also indicates the. */ - public float flow_comp_m_x; + public int integration_time_us; /** - * Flow in meters in y-sensor direction, angular-speed compensated + * Flow in radians around X axis (Sensor RH rotation about the X axis induces a positive flow. Sensor linear motion along the positive Y axis induces a negative flow.) */ - public float flow_comp_m_y; + public float integrated_x; /** - * Ground distance in meters. Positive value: distance known. Negative value: Unknown distance + * Flow in radians around Y axis (Sensor RH rotation about the Y axis induces a positive flow. Sensor linear motion along the positive X axis induces a positive flow.) */ - public float ground_distance; + public float integrated_y; /** - * Flow in pixels in x-sensor direction + * RH rotation around X axis (rad) */ - public short flow_x; + public float integrated_xgyro; /** - * Flow in pixels in y-sensor direction + * RH rotation around Y axis (rad) */ - public short flow_y; + public float integrated_ygyro; + /** + * RH rotation around Z axis (rad) + */ + public float integrated_zgyro; + /** + * Time in microseconds since the distance was sampled. + */ + public int time_delta_distance_us; + /** + * Distance to the center of the flow field in meters. Positive value (including zero): distance known. Negative value: Unknown distance. + */ + public float distance; + /** + * Temperature * 100 in centi-degrees Celsius + */ + public short temperature; /** * Sensor ID */ public byte sensor_id; /** - * Optical flow quality / confidence. 0: bad, 255: maximum quality + * Optical flow quality / confidence. 0: no valid flow, 255: maximum quality */ public byte quality; @@ -60,11 +76,15 @@ public MAVLinkPacket pack(){ packet.compid = 190; packet.msgid = MAVLINK_MSG_ID_HIL_OPTICAL_FLOW; packet.payload.putLong(time_usec); - packet.payload.putFloat(flow_comp_m_x); - packet.payload.putFloat(flow_comp_m_y); - packet.payload.putFloat(ground_distance); - packet.payload.putShort(flow_x); - packet.payload.putShort(flow_y); + packet.payload.putInt(integration_time_us); + packet.payload.putFloat(integrated_x); + packet.payload.putFloat(integrated_y); + packet.payload.putFloat(integrated_xgyro); + packet.payload.putFloat(integrated_ygyro); + packet.payload.putFloat(integrated_zgyro); + packet.payload.putInt(time_delta_distance_us); + packet.payload.putFloat(distance); + packet.payload.putShort(temperature); packet.payload.putByte(sensor_id); packet.payload.putByte(quality); @@ -79,11 +99,15 @@ public MAVLinkPacket pack(){ public void unpack(MAVLinkPayload payload) { payload.resetIndex(); this.time_usec = payload.getLong(); - this.flow_comp_m_x = payload.getFloat(); - this.flow_comp_m_y = payload.getFloat(); - this.ground_distance = payload.getFloat(); - this.flow_x = payload.getShort(); - this.flow_y = payload.getShort(); + this.integration_time_us = payload.getInt(); + this.integrated_x = payload.getFloat(); + this.integrated_y = payload.getFloat(); + this.integrated_xgyro = payload.getFloat(); + this.integrated_ygyro = payload.getFloat(); + this.integrated_zgyro = payload.getFloat(); + this.time_delta_distance_us = payload.getInt(); + this.distance = payload.getFloat(); + this.temperature = payload.getShort(); this.sensor_id = payload.getByte(); this.quality = payload.getByte(); @@ -110,12 +134,12 @@ public msg_hil_optical_flow(MAVLinkPacket mavLinkPacket){ //Log.d("MAVLINK_MSG_ID_HIL_OPTICAL_FLOW", toString()); } - + /** * Returns a string with the MSG name and data */ public String toString(){ - return "MAVLINK_MSG_ID_HIL_OPTICAL_FLOW -"+" time_usec:"+time_usec+" flow_comp_m_x:"+flow_comp_m_x+" flow_comp_m_y:"+flow_comp_m_y+" ground_distance:"+ground_distance+" flow_x:"+flow_x+" flow_y:"+flow_y+" sensor_id:"+sensor_id+" quality:"+quality+""; + return "MAVLINK_MSG_ID_HIL_OPTICAL_FLOW -"+" time_usec:"+time_usec+" integration_time_us:"+integration_time_us+" integrated_x:"+integrated_x+" integrated_y:"+integrated_y+" integrated_xgyro:"+integrated_xgyro+" integrated_ygyro:"+integrated_ygyro+" integrated_zgyro:"+integrated_zgyro+" time_delta_distance_us:"+time_delta_distance_us+" distance:"+distance+" temperature:"+temperature+" sensor_id:"+sensor_id+" quality:"+quality+""; } } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_ping.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_ping.java index aa649e11bd..b45f1a89dc 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_ping.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_ping.java @@ -16,7 +16,7 @@ public class msg_ping extends MAVLinkMessage{ /** - * Unix timestamp in microseconds + * Unix timestamp in microseconds or since system boot if smaller than MAVLink epoch (1.1.2009) */ public long time_usec; /** diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_global_int.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_global_int.java index 525c4556b7..ced5e0107b 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_global_int.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_global_int.java @@ -11,7 +11,7 @@ public class msg_position_target_global_int extends MAVLinkMessage{ public static final int MAVLINK_MSG_ID_POSITION_TARGET_GLOBAL_INT = 87; - public static final int MAVLINK_MSG_LENGTH = 43; + public static final int MAVLINK_MSG_LENGTH = 51; private static final long serialVersionUID = MAVLINK_MSG_ID_POSITION_TARGET_GLOBAL_INT; @@ -56,7 +56,15 @@ public class msg_position_target_global_int extends MAVLinkMessage{ */ public float afz; /** - * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + * yaw setpoint in rad + */ + public float yaw; + /** + * yaw rate setpoint in rad/s + */ + public float yaw_rate; + /** + * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate */ public short type_mask; /** @@ -85,6 +93,8 @@ public MAVLinkPacket pack(){ packet.payload.putFloat(afx); packet.payload.putFloat(afy); packet.payload.putFloat(afz); + packet.payload.putFloat(yaw); + packet.payload.putFloat(yaw_rate); packet.payload.putShort(type_mask); packet.payload.putByte(coordinate_frame); @@ -108,6 +118,8 @@ public void unpack(MAVLinkPayload payload) { this.afx = payload.getFloat(); this.afy = payload.getFloat(); this.afz = payload.getFloat(); + this.yaw = payload.getFloat(); + this.yaw_rate = payload.getFloat(); this.type_mask = payload.getShort(); this.coordinate_frame = payload.getByte(); @@ -134,12 +146,12 @@ public msg_position_target_global_int(MAVLinkPacket mavLinkPacket){ //Log.d("MAVLINK_MSG_ID_POSITION_TARGET_GLOBAL_INT", toString()); } - + /** * Returns a string with the MSG name and data */ public String toString(){ - return "MAVLINK_MSG_ID_POSITION_TARGET_GLOBAL_INT -"+" time_boot_ms:"+time_boot_ms+" lat_int:"+lat_int+" lon_int:"+lon_int+" alt:"+alt+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" type_mask:"+type_mask+" coordinate_frame:"+coordinate_frame+""; + return "MAVLINK_MSG_ID_POSITION_TARGET_GLOBAL_INT -"+" time_boot_ms:"+time_boot_ms+" lat_int:"+lat_int+" lon_int:"+lon_int+" alt:"+alt+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" yaw:"+yaw+" yaw_rate:"+yaw_rate+" type_mask:"+type_mask+" coordinate_frame:"+coordinate_frame+""; } } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_local_ned.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_local_ned.java index 356e21e529..4399b02989 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_local_ned.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_position_target_local_ned.java @@ -11,7 +11,7 @@ public class msg_position_target_local_ned extends MAVLinkMessage{ public static final int MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED = 85; - public static final int MAVLINK_MSG_LENGTH = 43; + public static final int MAVLINK_MSG_LENGTH = 51; private static final long serialVersionUID = MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED; @@ -56,7 +56,15 @@ public class msg_position_target_local_ned extends MAVLinkMessage{ */ public float afz; /** - * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + * yaw setpoint in rad + */ + public float yaw; + /** + * yaw rate setpoint in rad/s + */ + public float yaw_rate; + /** + * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate */ public short type_mask; /** @@ -85,6 +93,8 @@ public MAVLinkPacket pack(){ packet.payload.putFloat(afx); packet.payload.putFloat(afy); packet.payload.putFloat(afz); + packet.payload.putFloat(yaw); + packet.payload.putFloat(yaw_rate); packet.payload.putShort(type_mask); packet.payload.putByte(coordinate_frame); @@ -108,6 +118,8 @@ public void unpack(MAVLinkPayload payload) { this.afx = payload.getFloat(); this.afy = payload.getFloat(); this.afz = payload.getFloat(); + this.yaw = payload.getFloat(); + this.yaw_rate = payload.getFloat(); this.type_mask = payload.getShort(); this.coordinate_frame = payload.getByte(); @@ -134,12 +146,12 @@ public msg_position_target_local_ned(MAVLinkPacket mavLinkPacket){ //Log.d("MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED", toString()); } - + /** * Returns a string with the MSG name and data */ public String toString(){ - return "MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED -"+" time_boot_ms:"+time_boot_ms+" x:"+x+" y:"+y+" z:"+z+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" type_mask:"+type_mask+" coordinate_frame:"+coordinate_frame+""; + return "MAVLINK_MSG_ID_POSITION_TARGET_LOCAL_NED -"+" time_boot_ms:"+time_boot_ms+" x:"+x+" y:"+y+" z:"+z+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" yaw:"+yaw+" yaw_rate:"+yaw_rate+" type_mask:"+type_mask+" coordinate_frame:"+coordinate_frame+""; } } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_global_int.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_global_int.java index baad8647b0..49ecbfb756 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_global_int.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_global_int.java @@ -11,7 +11,7 @@ public class msg_set_position_target_global_int extends MAVLinkMessage{ public static final int MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT = 86; - public static final int MAVLINK_MSG_LENGTH = 45; + public static final int MAVLINK_MSG_LENGTH = 53; private static final long serialVersionUID = MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT; @@ -56,7 +56,15 @@ public class msg_set_position_target_global_int extends MAVLinkMessage{ */ public float afz; /** - * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + * yaw setpoint in rad + */ + public float yaw; + /** + * yaw rate setpoint in rad/s + */ + public float yaw_rate; + /** + * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate */ public short type_mask; /** @@ -93,6 +101,8 @@ public MAVLinkPacket pack(){ packet.payload.putFloat(afx); packet.payload.putFloat(afy); packet.payload.putFloat(afz); + packet.payload.putFloat(yaw); + packet.payload.putFloat(yaw_rate); packet.payload.putShort(type_mask); packet.payload.putByte(target_system); packet.payload.putByte(target_component); @@ -118,6 +128,8 @@ public void unpack(MAVLinkPayload payload) { this.afx = payload.getFloat(); this.afy = payload.getFloat(); this.afz = payload.getFloat(); + this.yaw = payload.getFloat(); + this.yaw_rate = payload.getFloat(); this.type_mask = payload.getShort(); this.target_system = payload.getByte(); this.target_component = payload.getByte(); @@ -146,12 +158,12 @@ public msg_set_position_target_global_int(MAVLinkPacket mavLinkPacket){ //Log.d("MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT", toString()); } - + /** * Returns a string with the MSG name and data */ public String toString(){ - return "MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT -"+" time_boot_ms:"+time_boot_ms+" lat_int:"+lat_int+" lon_int:"+lon_int+" alt:"+alt+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" type_mask:"+type_mask+" target_system:"+target_system+" target_component:"+target_component+" coordinate_frame:"+coordinate_frame+""; + return "MAVLINK_MSG_ID_SET_POSITION_TARGET_GLOBAL_INT -"+" time_boot_ms:"+time_boot_ms+" lat_int:"+lat_int+" lon_int:"+lon_int+" alt:"+alt+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" yaw:"+yaw+" yaw_rate:"+yaw_rate+" type_mask:"+type_mask+" target_system:"+target_system+" target_component:"+target_component+" coordinate_frame:"+coordinate_frame+""; } } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_local_ned.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_local_ned.java index 0e764ee416..276f2971f2 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_local_ned.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_set_position_target_local_ned.java @@ -11,7 +11,7 @@ public class msg_set_position_target_local_ned extends MAVLinkMessage{ public static final int MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED = 84; - public static final int MAVLINK_MSG_LENGTH = 45; + public static final int MAVLINK_MSG_LENGTH = 53; private static final long serialVersionUID = MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED; @@ -56,7 +56,15 @@ public class msg_set_position_target_local_ned extends MAVLinkMessage{ */ public float afz; /** - * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint + * yaw setpoint in rad + */ + public float yaw; + /** + * yaw rate setpoint in rad/s + */ + public float yaw_rate; + /** + * Bitmask to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 10 is set the floats afx afy afz should be interpreted as force instead of acceleration. Mapping: bit 1: x, bit 2: y, bit 3: z, bit 4: vx, bit 5: vy, bit 6: vz, bit 7: ax, bit 8: ay, bit 9: az, bit 10: is force setpoint, bit 11: yaw, bit 12: yaw rate */ public short type_mask; /** @@ -93,6 +101,8 @@ public MAVLinkPacket pack(){ packet.payload.putFloat(afx); packet.payload.putFloat(afy); packet.payload.putFloat(afz); + packet.payload.putFloat(yaw); + packet.payload.putFloat(yaw_rate); packet.payload.putShort(type_mask); packet.payload.putByte(target_system); packet.payload.putByte(target_component); @@ -118,6 +128,8 @@ public void unpack(MAVLinkPayload payload) { this.afx = payload.getFloat(); this.afy = payload.getFloat(); this.afz = payload.getFloat(); + this.yaw = payload.getFloat(); + this.yaw_rate = payload.getFloat(); this.type_mask = payload.getShort(); this.target_system = payload.getByte(); this.target_component = payload.getByte(); @@ -146,12 +158,12 @@ public msg_set_position_target_local_ned(MAVLinkPacket mavLinkPacket){ //Log.d("MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED", toString()); } - + /** * Returns a string with the MSG name and data */ public String toString(){ - return "MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED -"+" time_boot_ms:"+time_boot_ms+" x:"+x+" y:"+y+" z:"+z+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" type_mask:"+type_mask+" target_system:"+target_system+" target_component:"+target_component+" coordinate_frame:"+coordinate_frame+""; + return "MAVLINK_MSG_ID_SET_POSITION_TARGET_LOCAL_NED -"+" time_boot_ms:"+time_boot_ms+" x:"+x+" y:"+y+" z:"+z+" vx:"+vx+" vy:"+vy+" vz:"+vz+" afx:"+afx+" afy:"+afy+" afz:"+afz+" yaw:"+yaw+" yaw_rate:"+yaw_rate+" type_mask:"+type_mask+" target_system:"+target_system+" target_component:"+target_component+" coordinate_frame:"+coordinate_frame+""; } } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/enums/GRIPPER_ACTIONS.java b/dependencyLibs/Mavlink/src/com/MAVLink/enums/GRIPPER_ACTIONS.java new file mode 100644 index 0000000000..28683e97d6 --- /dev/null +++ b/dependencyLibs/Mavlink/src/com/MAVLink/enums/GRIPPER_ACTIONS.java @@ -0,0 +1,11 @@ + /** Gripper actions. + */ + package com.MAVLink.enums; + + public class GRIPPER_ACTIONS { + public static final int GRIPPER_ACTION_RELEASE = 0; /* gripper release of cargo | */ + public static final int GRIPPER_ACTION_GRAB = 1; /* gripper grabs onto cargo | */ + public static final int GRIPPER_ACTIONS_ENUM_END = 2; /* | */ + + } + \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_AUTOPILOT.java b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_AUTOPILOT.java index 74b46f6ff8..822f1c7df0 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_AUTOPILOT.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_AUTOPILOT.java @@ -20,7 +20,8 @@ public class MAV_AUTOPILOT { public static final int MAV_AUTOPILOT_AUTOQUAD = 14; /* AutoQuad -- http://autoquad.org | */ public static final int MAV_AUTOPILOT_ARMAZILA = 15; /* Armazila -- http://armazila.com | */ public static final int MAV_AUTOPILOT_AEROB = 16; /* Aerob -- http://aerob.ru | */ - public static final int MAV_AUTOPILOT_ENUM_END = 17; /* | */ + public static final int MAV_AUTOPILOT_ASLUAV = 17; /* ASLUAV autopilot -- http://www.asl.ethz.ch | */ + public static final int MAV_AUTOPILOT_ENUM_END = 18; /* | */ } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_CMD.java b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_CMD.java index 35be9ee381..f313bfbdd5 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_CMD.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_CMD.java @@ -10,6 +10,7 @@ public class MAV_CMD { public static final int MAV_CMD_NAV_RETURN_TO_LAUNCH = 20; /* Return to launch location |Empty| Empty| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_NAV_LAND = 21; /* Land at location |Empty| Empty| Empty| Desired yaw angle.| Latitude| Longitude| Altitude| */ public static final int MAV_CMD_NAV_TAKEOFF = 22; /* Takeoff from ground / hand |Minimum pitch (if airspeed sensor present), desired pitch without sensor| Empty| Empty| Yaw angle (if magnetometer present), ignored without magnetometer| Latitude| Longitude| Altitude| */ + public static final int MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT = 30; /* Continue on the current course and climb/descend to specified altitude. When the altitude is reached continue to the next command (i.e., don't proceed to the next command until the desired altitude is reached. |Empty| Empty| Empty| Empty| Empty| Empty| Desired altitude in meters| */ public static final int MAV_CMD_NAV_ROI = 80; /* Sets the region of interest (ROI) for a sensor set or the vehicle itself. This can then be used by the vehicles control system to control the vehicle attitude and the attitude of various sensors such as cameras. |Region of intereset mode. (see MAV_ROI enum)| MISSION index/ target ID. (see MAV_ROI enum)| ROI index (allows a vehicle to manage multiple ROI's)| Empty| x the location of the fixed ROI (see MAV_FRAME)| y| z| */ public static final int MAV_CMD_NAV_PATHPLANNING = 81; /* Control autonomous path planning on the MAV. |0: Disable local obstacle avoidance / local path planning (without resetting map), 1: Enable local path planning, 2: Enable and reset local path planning| 0: Disable full path planning (without resetting map), 1: Enable, 2: Enable and reset map/occupancy grid, 3: Enable and reset planned route, but not occupancy grid| Empty| Yaw angle at goal, in compass degrees, [0..360]| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ public static final int MAV_CMD_NAV_SPLINE_WAYPOINT = 82; /* Navigate to MISSION using a spline path. |Hold time in decimal seconds. (ignored by fixed wing, time to stay at MISSION for rotary wing)| Empty| Empty| Empty| Latitude/X of goal| Longitude/Y of goal| Altitude/Z of goal| */ @@ -30,6 +31,7 @@ public class MAV_CMD { public static final int MAV_CMD_DO_SET_SERVO = 183; /* Set a servo to a desired PWM value. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_REPEAT_SERVO = 184; /* Cycle a between its nominal setting and a desired PWM for a desired number of cycles with a desired period. |Servo number| PWM (microseconds, 1000 to 2000 typical)| Cycle count| Cycle time (seconds)| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_FLIGHTTERMINATION = 185; /* Terminate flight immediately |Flight termination activated if > 0.5| Empty| Empty| Empty| Empty| Empty| Empty| */ + public static final int MAV_CMD_DO_LAND_START = 189; /* Mission command to perform a landing. This is used as a marker in a mission to tell the autopilot where a sequence of mission items that represents a landing starts. It may also be sent via a COMMAND_LONG to trigger a landing, in which case the nearest (geographically) landing sequence in the mission will be used. The Latitude/Longitude is optional, and may be set to 0/0 if not needed. If specified then it will be used to help find the closest landing sequence. |Empty| Empty| Empty| Empty| Latitude| Longitude| Empty| */ public static final int MAV_CMD_DO_RALLY_LAND = 190; /* Mission command to perform a landing from a rally point. |Break altitude (meters)| Landing speed (m/s)| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_GO_AROUND = 191; /* Mission command to safely abort an autonmous landing. |Altitude (meters)| Empty| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_CONTROL_VIDEO = 200; /* Control onboard camera system. |Camera ID (-1 for all)| Transmission: 0: disabled, 1: enabled compressed, 2: enabled raw| Transmission mode: 0: video stream, >0: single images every n seconds (decimal)| Recording: 0: disabled, 1: enabled compressed, 2: enabled raw| Empty| Empty| Empty| */ @@ -43,6 +45,7 @@ public class MAV_CMD { public static final int MAV_CMD_DO_PARACHUTE = 208; /* Mission command to trigger a parachute |action (0=disable, 1=enable, 2=release, for some systems see PARACHUTE_ACTION enum, not in general message set.)| Empty| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_MOTOR_TEST = 209; /* Mission command to perform motor test |motor sequence number (a number from 1 to max number of motors on the vehicle)| throttle type (0=throttle percentage, 1=PWM, 2=pilot throttle channel pass-through. See MOTOR_TEST_THROTTLE_TYPE enum)| throttle| timeout (in seconds)| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_INVERTED_FLIGHT = 210; /* Change to/from inverted flight |inverted (0=normal, 1=inverted)| Empty| Empty| Empty| Empty| Empty| Empty| */ + public static final int MAV_CMD_DO_GRIPPER = 211; /* Mission command to operate EPM gripper |gripper number (a number from 1 to max number of grippers on the vehicle)| gripper action (0=release, 1=grab. See GRIPPER_ACTIONS enum)| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_MOUNT_CONTROL_QUAT = 220; /* Mission command to control a camera or antenna mount, using a quaternion as reference. |q1 - quaternion param #1, w (1 in null-rotation)| q2 - quaternion param #2, x (0 in null-rotation)| q3 - quaternion param #3, y (0 in null-rotation)| q4 - quaternion param #4, z (0 in null-rotation)| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_GUIDED_MASTER = 221; /* set id of master controller |System ID| Component ID| Empty| Empty| Empty| Empty| Empty| */ public static final int MAV_CMD_DO_GUIDED_LIMITS = 222; /* set limits for external control |timeout - maximum time (in seconds) that external controller will be allowed to control vehicle. 0 means no timeout| absolute altitude min (in meters, WGS84) - if vehicle moves below this alt, the command will be aborted and the mission will continue. 0 means no lower altitude limit| absolute altitude max (in meters)- if vehicle moves above this alt, the command will be aborted and the mission will continue. 0 means no upper altitude limit| horizontal move limit (in meters, WGS84) - if vehicle moves more than this distance from it's location at the moment the command was executed, the command will be aborted and the mission will continue. 0 means no horizontal altitude limit| Empty| Empty| Empty| */ @@ -59,7 +62,7 @@ public class MAV_CMD { public static final int MAV_CMD_IMAGE_STOP_CAPTURE = 2001; /* Stop image capture sequence |Reserved| Reserved| */ public static final int MAV_CMD_VIDEO_START_CAPTURE = 2500; /* Starts video capture |Camera ID (0 for all cameras), 1 for first, 2 for second, etc.| Frames per second| Resolution in megapixels (0.3 for 640x480, 1.3 for 1280x720, etc)| */ public static final int MAV_CMD_VIDEO_STOP_CAPTURE = 2501; /* Stop the current video capture |Reserved| Reserved| */ - public static final int MAV_CMD_PANORAMA_CREATE = 2800; /* Create a panorama at the current position |Viewing angle horizontal of the panorama| Viewing angle vertical of panorama| */ + public static final int MAV_CMD_PANORAMA_CREATE = 2800; /* Create a panorama at the current position |Viewing angle horizontal of the panorama (in degrees, +- 0.5 the total angle)| Viewing angle vertical of panorama (in degrees)| Speed of the horizontal rotation (in degrees per second)| Speed of the vertical rotation (in degrees per second)| */ public static final int MAV_CMD_PAYLOAD_PREPARE_DEPLOY = 30001; /* Deploy payload on a Lat / Lon / Alt position. This includes the navigation to reach the required release position and velocity. |Operation mode. 0: prepare single payload deploy (overwriting previous requests), but do not execute it. 1: execute payload deploy immediately (rejecting further deploy commands during execution, but allowing abort). 2: add payload deploy to existing deployment list.| Desired approach vector in degrees compass heading (0..360). A negative value indicates the system can define the approach vector at will.| Desired ground speed at release time. This can be overriden by the airframe in case it needs to meet minimum airspeed. A negative value indicates the system can define the ground speed at will.| Minimum altitude clearance to the release position in meters. A negative value indicates the system can define the clearance at will.| Latitude unscaled for MISSION_ITEM or in 1e7 degrees for MISSION_ITEM_INT| Longitude unscaled for MISSION_ITEM or in 1e7 degrees for MISSION_ITEM_INT| Altitude, in meters WGS84| */ public static final int MAV_CMD_PAYLOAD_CONTROL_DEPLOY = 30002; /* Control the payload deployment. |Operation mode. 0: Abort deployment, continue normal mission. 1: switch to payload deploment mode. 100: delete first payload deployment request. 101: delete all payload deployment requests.| Reserved| Reserved| Reserved| Reserved| Reserved| Reserved| */ public static final int MAV_CMD_ENUM_END = 30003; /* | */ diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_FRAME.java b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_FRAME.java index d867613bc8..b5c8c8552e 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_FRAME.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_FRAME.java @@ -8,11 +8,14 @@ public class MAV_FRAME { public static final int MAV_FRAME_MISSION = 2; /* NOT a coordinate frame, indicates a mission command. | */ public static final int MAV_FRAME_GLOBAL_RELATIVE_ALT = 3; /* Global coordinate frame, WGS84 coordinate system, relative altitude over ground with respect to the home position. First value / x: latitude, second value / y: longitude, third value / z: positive altitude with 0 being at the altitude of the home location. | */ public static final int MAV_FRAME_LOCAL_ENU = 4; /* Local coordinate frame, Z-down (x: east, y: north, z: up) | */ + public static final int MAV_FRAME_GLOBAL_INT = 5; /* Global coordinate frame, WGS84 coordinate system. First value / x: latitude in degrees*1.0e-7, second value / y: longitude in degrees*1.0e-7, third value / z: positive altitude over mean sea level (MSL) | */ + public static final int MAV_FRAME_GLOBAL_RELATIVE_ALT_INT = 6; /* Global coordinate frame, WGS84 coordinate system, relative altitude over ground with respect to the home position. First value / x: latitude in degrees*10e-7, second value / y: longitude in degrees*10e-7, third value / z: positive altitude with 0 being at the altitude of the home location. | */ public static final int MAV_FRAME_LOCAL_OFFSET_NED = 7; /* Offset to the current local frame. Anything expressed in this frame should be added to the current local frame position. | */ public static final int MAV_FRAME_BODY_NED = 8; /* Setpoint in body NED frame. This makes sense if all position control is externalized - e.g. useful to command 2 m/s^2 acceleration to the right. | */ public static final int MAV_FRAME_BODY_OFFSET_NED = 9; /* Offset in body NED frame. This makes sense if adding setpoints to the current flight path, to avoid an obstacle - e.g. useful to command 2 m/s^2 acceleration to the east. | */ public static final int MAV_FRAME_GLOBAL_TERRAIN_ALT = 10; /* Global coordinate frame with above terrain level altitude. WGS84 coordinate system, relative altitude over terrain with respect to the waypoint coordinate. First value / x: latitude in degrees, second value / y: longitude in degrees, third value / z: positive altitude in meters with 0 being at ground level in terrain model. | */ - public static final int MAV_FRAME_ENUM_END = 11; /* | */ + public static final int MAV_FRAME_GLOBAL_TERRAIN_ALT_INT = 11; /* Global coordinate frame with above terrain level altitude. WGS84 coordinate system, relative altitude over terrain with respect to the waypoint coordinate. First value / x: latitude in degrees*10e-7, second value / y: longitude in degrees*10e-7, third value / z: positive altitude in meters with 0 being at ground level in terrain model. | */ + public static final int MAV_FRAME_ENUM_END = 12; /* | */ } \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_TYPE.java b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_TYPE.java index 2e8adf0ab4..82d8f08bfe 100644 --- a/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_TYPE.java +++ b/dependencyLibs/Mavlink/src/com/MAVLink/enums/MAV_TYPE.java @@ -22,7 +22,9 @@ public class MAV_TYPE { public static final int MAV_TYPE_FLAPPING_WING = 16; /* Flapping wing | */ public static final int MAV_TYPE_KITE = 17; /* Flapping wing | */ public static final int MAV_TYPE_ONBOARD_CONTROLLER = 18; /* Onboard companion controller | */ - public static final int MAV_TYPE_ENUM_END = 19; /* | */ + public static final int MAV_TYPE_VTOL_DUOROTOR = 19; /* Two-rotor VTOL using control surfaces in vertical operation in addition. Tailsitter. | */ + public static final int MAV_TYPE_VTOL_QUADROTOR = 20; /* Quad-rotor VTOL using a V-shaped quad config in vertical operation. Tailsitter. | */ + public static final int MAV_TYPE_ENUM_END = 21; /* | */ } \ No newline at end of file From 1dfb4cb0931e7115dfa600c9949e7e88f6c68dc5 Mon Sep 17 00:00:00 2001 From: ne0fhyk Date: Tue, 6 Jan 2015 16:47:14 -0800 Subject: [PATCH 2/4] added camera info file for the gopro hero 3 silver. updated DroidPlannerService to switch to a foreground state when it's running. reduced the min time between gps lock when in follow me mode. --- .../assets/CameraInfo/GoPro_Hero_3_Silver.xml | 8 ++ .../android/api/DroidPlannerService.java | 30 +++++- .../service/UploaderService.java | 3 +- .../android/location/FusedLocation.java | 93 +++++++++---------- .../core/gcs/roi/ROIEstimator.java | 3 +- 5 files changed, 84 insertions(+), 53 deletions(-) create mode 100644 ServiceApp/assets/CameraInfo/GoPro_Hero_3_Silver.xml diff --git a/ServiceApp/assets/CameraInfo/GoPro_Hero_3_Silver.xml b/ServiceApp/assets/CameraInfo/GoPro_Hero_3_Silver.xml new file mode 100644 index 0000000000..f22f6b6c56 --- /dev/null +++ b/ServiceApp/assets/CameraInfo/GoPro_Hero_3_Silver.xml @@ -0,0 +1,8 @@ + + + GoPro Hero 3 Silver (Wide) + 5.76 + 4.29 + 11 + 2.5 + \ No newline at end of file diff --git a/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java b/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java index eb779553a3..2536681c7b 100644 --- a/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java +++ b/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java @@ -1,8 +1,11 @@ package org.droidplanner.services.android.api; +import android.app.Notification; +import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -18,12 +21,14 @@ import org.droidplanner.core.MAVLink.connection.MavLinkConnection; import org.droidplanner.core.MAVLink.connection.MavLinkConnectionListener; +import org.droidplanner.services.android.R; import org.droidplanner.services.android.communication.connection.AndroidMavLinkConnection; import org.droidplanner.services.android.communication.connection.AndroidTcpConnection; import org.droidplanner.services.android.communication.connection.AndroidUdpConnection; import org.droidplanner.services.android.communication.connection.BluetoothConnection; import org.droidplanner.services.android.communication.connection.usb.UsbConnection; import org.droidplanner.services.android.communication.service.UploaderService; +import org.droidplanner.services.android.ui.activity.MainActivity; import org.droidplanner.services.android.utils.analytics.GAUtils; import java.util.ArrayList; @@ -39,6 +44,8 @@ public class DroidPlannerService extends Service { private static final String CLAZZ_NAME = DroidPlannerService.class.getName(); private static final String TAG = DroidPlannerService.class.getSimpleName(); + private static final int FOREGROUND_ID = 101; + public static final String ACTION_DRONE_CREATED = CLAZZ_NAME + ".ACTION_DRONE_CREATED"; public static final String ACTION_DRONE_DESTROYED = CLAZZ_NAME + ".ACTION_DRONE_DESTROYED"; public static final String ACTION_KICK_START_DRONESHARE_UPLOADS = CLAZZ_NAME + ".ACTION_KICK_START_DRONESHARE_UPLOADS"; @@ -180,16 +187,32 @@ public IBinder onBind(Intent intent) { @Override public void onCreate() { super.onCreate(); + Log.d(TAG, "Creating 3DR Services."); + + final Context context = getApplicationContext(); mavlinkApi = new MavLinkServiceApi(this); droneAccess = new DroneAccess(this); dpServices = new DPServices(this); - lbm = LocalBroadcastManager.getInstance(getApplicationContext()); + lbm = LocalBroadcastManager.getInstance(context); + + //Put the service in the foreground + final Notification.Builder notifBuilder = new Notification.Builder(context) + .setContentTitle("3DR Services") + .setSmallIcon(R.drawable.ic_launcher) + .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, + MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0)); + + final Notification notification = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN + ? notifBuilder.build() + : notifBuilder.getNotification(); + startForeground(FOREGROUND_ID, notification); } @Override public void onDestroy() { super.onDestroy(); + Log.d(TAG, "Destroying 3DR Services."); for (DroneApi droneApi : droneApiStore) { droneApi.destroy(); @@ -202,6 +225,8 @@ public void onDestroy() { } mavConnections.clear(); + + stopForeground(true); } @Override @@ -222,7 +247,8 @@ public int onStartCommand(Intent intent, int flags, int startId) { } } - return START_REDELIVER_INTENT; + stopSelf(); + return START_NOT_STICKY; } } diff --git a/ServiceApp/src/org/droidplanner/services/android/communication/service/UploaderService.java b/ServiceApp/src/org/droidplanner/services/android/communication/service/UploaderService.java index 88ec7c1916..b604001a05 100644 --- a/ServiceApp/src/org/droidplanner/services/android/communication/service/UploaderService.java +++ b/ServiceApp/src/org/droidplanner/services/android/communication/service/UploaderService.java @@ -189,8 +189,7 @@ static public Intent createIntent(Context context, DroneSharePrefs droneSharePre } public static void kickStart(Context context, DroneSharePrefs droneSharePrefs){ - if(droneSharePrefs != null && droneSharePrefs.areLoginCredentialsSet() && droneSharePrefs - .isEnabled()) { + if(droneSharePrefs != null && droneSharePrefs.areLoginCredentialsSet() && droneSharePrefs.isEnabled()) { context.startService(UploaderService.createIntent(context, droneSharePrefs)); } } diff --git a/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java b/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java index faf39cb7af..c949a38d93 100644 --- a/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java +++ b/ServiceApp/src/org/droidplanner/services/android/location/FusedLocation.java @@ -1,31 +1,30 @@ package org.droidplanner.services.android.location; -import org.droidplanner.core.helpers.coordinates.Coord3D; -import org.droidplanner.core.helpers.units.Altitude; -import org.droidplanner.services.android.utils.GoogleApiClientManager; -import org.droidplanner.services.android.utils.GoogleApiClientManager.GoogleApiClientTask; -import org.droidplanner.core.gcs.location.Location.LocationFinder; -import org.droidplanner.core.gcs.location.Location.LocationReceiver; -import org.droidplanner.core.helpers.coordinates.Coord2D; - import android.content.Context; import android.location.Location; import android.os.Handler; import android.util.Log; +import android.widget.Toast; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; +import org.droidplanner.core.gcs.location.Location.LocationFinder; +import org.droidplanner.core.gcs.location.Location.LocationReceiver; +import org.droidplanner.core.helpers.coordinates.Coord3D; +import org.droidplanner.core.helpers.units.Altitude; +import org.droidplanner.services.android.utils.GoogleApiClientManager; +import org.droidplanner.services.android.utils.GoogleApiClientManager.GoogleApiClientTask; + /** * Feeds Location Data from Android's FusedLocation LocationProvider - * */ public class FusedLocation implements LocationFinder, com.google.android.gms.location.LocationListener { private static final String TAG = FusedLocation.class.getSimpleName(); - private static final long MIN_TIME_MS = 1000; - private static final float MIN_DISTANCE_M = 0.0f; + private static final long MIN_TIME_MS = 0; + private static final float MIN_DISTANCE_M = 0.0f; private static final float LOCATION_ACCURACY_THRESHOLD = 15.0f; private static final float JUMP_FACTOR = 4.0f; @@ -33,14 +32,14 @@ public class FusedLocation implements LocationFinder, com.google.android.gms.loc private final GoogleApiClientTask requestLocationUpdate; private final GoogleApiClientTask removeLocationUpdate; - private LocationReceiver receiver; + private LocationReceiver receiver; - private Location mLastLocation; + private Location mLastLocation; private float mTotalSpeed; private long mSpeedReadings; - public FusedLocation(Context context, Handler handler) { + public FusedLocation(Context context, Handler handler) { gApiMgr = new GoogleApiClientManager(context, handler, LocationServices.API); requestLocationUpdate = gApiMgr.new GoogleApiClientTask() { @@ -65,38 +64,38 @@ protected void doRun() { }; gApiMgr.start(); - } + } - @Override - public void enableLocationUpdates() { + @Override + public void enableLocationUpdates() { mSpeedReadings = 0; mTotalSpeed = 0f; try { gApiMgr.addTask(requestLocationUpdate); - }catch(IllegalStateException e){ + } catch (IllegalStateException e) { Log.e(TAG, "Unable to request location updates."); } - } + } - @Override - public void disableLocationUpdates() { + @Override + public void disableLocationUpdates() { try { gApiMgr.addTask(removeLocationUpdate); - }catch(IllegalStateException e){ + } catch (IllegalStateException e) { Log.e(TAG, "Unable to disable location updates."); } - } + } - @Override - public void onLocationChanged(Location androidLocation) { - if (receiver != null) { - float distanceToLast = -1.0f; - long timeSinceLast = -1L; + @Override + public void onLocationChanged(Location androidLocation) { + if (receiver != null) { + float distanceToLast = -1.0f; + long timeSinceLast = -1L; - if(mLastLocation != null) { - distanceToLast = androidLocation.distanceTo(mLastLocation); - timeSinceLast = (androidLocation.getTime() - mLastLocation.getTime()) / 1000; - } + if (mLastLocation != null) { + distanceToLast = androidLocation.distanceTo(mLastLocation); + timeSinceLast = (androidLocation.getTime() - mLastLocation.getTime()) / 1000; + } final float currentSpeed = distanceToLast > 0f && timeSinceLast > 0 ? (distanceToLast / timeSinceLast) @@ -104,18 +103,18 @@ public void onLocationChanged(Location androidLocation) { final boolean isLocationAccurate = isLocationAccurate(androidLocation.getAccuracy(), currentSpeed); - org.droidplanner.core.gcs.location.Location location = new org.droidplanner.core.gcs.location.Location( - new Coord3D(androidLocation.getLatitude(), androidLocation.getLongitude(), + org.droidplanner.core.gcs.location.Location location = new org.droidplanner.core.gcs.location.Location( + new Coord3D(androidLocation.getLatitude(), androidLocation.getLongitude(), new Altitude(androidLocation.getAltitude())), androidLocation.getBearing(), androidLocation.getSpeed(), isLocationAccurate, androidLocation.getTime()); - mLastLocation = androidLocation; - receiver.onLocationChanged(location); - } - } + mLastLocation = androidLocation; + receiver.onLocationChanged(location); + } + } - private boolean isLocationAccurate(float accuracy, float currentSpeed){ - if(accuracy >= LOCATION_ACCURACY_THRESHOLD){ + private boolean isLocationAccurate(float accuracy, float currentSpeed) { + if (accuracy >= LOCATION_ACCURACY_THRESHOLD) { Log.d(TAG, "High accuracy: " + accuracy); return false; } @@ -124,11 +123,11 @@ private boolean isLocationAccurate(float accuracy, float currentSpeed){ float avg = (mTotalSpeed / ++mSpeedReadings); //If moving: - if(currentSpeed > 0){ + if (currentSpeed > 0) { //if average indicates some movement - if(avg >= 1.0){ + if (avg >= 1.0) { //Reject unreasonable updates. - if(currentSpeed >= (avg * JUMP_FACTOR)){ + if (currentSpeed >= (avg * JUMP_FACTOR)) { Log.d(TAG, "High current speed: " + currentSpeed); return false; } @@ -138,8 +137,8 @@ private boolean isLocationAccurate(float accuracy, float currentSpeed){ return true; } - @Override - public void setLocationListener(LocationReceiver receiver) { - this.receiver = receiver; - } + @Override + public void setLocationListener(LocationReceiver receiver) { + this.receiver = receiver; + } } diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/roi/ROIEstimator.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/roi/ROIEstimator.java index 16c5f97e1f..1fbce0288a 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/gcs/roi/ROIEstimator.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/roi/ROIEstimator.java @@ -61,8 +61,7 @@ private void updateROI() { Coord2D goCoord = GeoTools.newCoordFromBearingAndDistance(gcsCoord, bearing, distanceTraveledSinceLastPoint); if (distanceTraveledSinceLastPoint > 0.0) { - MavLinkROI.setROI(drone, new Coord3D(goCoord.getLat(), goCoord.getLng(), new Altitude( - 1.0))); + MavLinkROI.setROI(drone, new Coord3D(goCoord.getLat(), goCoord.getLng(), new Altitude(1.0))); } watchdog.postDelayed(watchdogCallback, TIMEOUT); From d6c42b680e8399d0e6e7bdb477efc4e548de6335 Mon Sep 17 00:00:00 2001 From: ne0fhyk Date: Tue, 6 Jan 2015 16:54:57 -0800 Subject: [PATCH 3/4] added missing files to git. --- .../android/api/DroidPlannerService.java | 2 + .../MAVLink/common/msg_optical_flow_rad.java | 145 ++++++++++++++++++ .../src/com/MAVLink/common/msg_timesync.java | 85 ++++++++++ 3 files changed, 232 insertions(+) create mode 100644 dependencyLibs/Mavlink/src/com/MAVLink/common/msg_optical_flow_rad.java create mode 100644 dependencyLibs/Mavlink/src/com/MAVLink/common/msg_timesync.java diff --git a/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java b/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java index 2536681c7b..c692e1fe83 100644 --- a/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java +++ b/ServiceApp/src/org/droidplanner/services/android/api/DroidPlannerService.java @@ -1,5 +1,6 @@ package org.droidplanner.services.android.api; +import android.annotation.SuppressLint; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; @@ -184,6 +185,7 @@ public IBinder onBind(Intent intent) { } } + @SuppressLint("NewApi") @Override public void onCreate() { super.onCreate(); diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_optical_flow_rad.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_optical_flow_rad.java new file mode 100644 index 0000000000..df48519c1a --- /dev/null +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_optical_flow_rad.java @@ -0,0 +1,145 @@ + // MESSAGE OPTICAL_FLOW_RAD PACKING +package com.MAVLink.common; +import com.MAVLink.MAVLinkPacket; +import com.MAVLink.Messages.MAVLinkMessage; +import com.MAVLink.Messages.MAVLinkPayload; + //import android.util.Log; + + /** + * Optical flow from an angular rate flow sensor (e.g. PX4FLOW or mouse sensor) + */ + public class msg_optical_flow_rad extends MAVLinkMessage{ + + public static final int MAVLINK_MSG_ID_OPTICAL_FLOW_RAD = 106; + public static final int MAVLINK_MSG_LENGTH = 44; + private static final long serialVersionUID = MAVLINK_MSG_ID_OPTICAL_FLOW_RAD; + + + /** + * Timestamp (microseconds, synced to UNIX time or since system boot) + */ + public long time_usec; + /** + * Integration time in microseconds. Divide integrated_x and integrated_y by the integration time to obtain average flow. The integration time also indicates the. + */ + public int integration_time_us; + /** + * Flow in radians around X axis (Sensor RH rotation about the X axis induces a positive flow. Sensor linear motion along the positive Y axis induces a negative flow.) + */ + public float integrated_x; + /** + * Flow in radians around Y axis (Sensor RH rotation about the Y axis induces a positive flow. Sensor linear motion along the positive X axis induces a positive flow.) + */ + public float integrated_y; + /** + * RH rotation around X axis (rad) + */ + public float integrated_xgyro; + /** + * RH rotation around Y axis (rad) + */ + public float integrated_ygyro; + /** + * RH rotation around Z axis (rad) + */ + public float integrated_zgyro; + /** + * Time in microseconds since the distance was sampled. + */ + public int time_delta_distance_us; + /** + * Distance to the center of the flow field in meters. Positive value (including zero): distance known. Negative value: Unknown distance. + */ + public float distance; + /** + * Temperature * 100 in centi-degrees Celsius + */ + public short temperature; + /** + * Sensor ID + */ + public byte sensor_id; + /** + * Optical flow quality / confidence. 0: no valid flow, 255: maximum quality + */ + public byte quality; + + + /** + * Generates the payload for a mavlink message for a message of this type + * @return + */ + public MAVLinkPacket pack(){ + MAVLinkPacket packet = new MAVLinkPacket(); + packet.len = MAVLINK_MSG_LENGTH; + packet.sysid = 255; + packet.compid = 190; + packet.msgid = MAVLINK_MSG_ID_OPTICAL_FLOW_RAD; + packet.payload.putLong(time_usec); + packet.payload.putInt(integration_time_us); + packet.payload.putFloat(integrated_x); + packet.payload.putFloat(integrated_y); + packet.payload.putFloat(integrated_xgyro); + packet.payload.putFloat(integrated_ygyro); + packet.payload.putFloat(integrated_zgyro); + packet.payload.putInt(time_delta_distance_us); + packet.payload.putFloat(distance); + packet.payload.putShort(temperature); + packet.payload.putByte(sensor_id); + packet.payload.putByte(quality); + + return packet; + } + + /** + * Decode a optical_flow_rad message into this class fields + * + * @param payload The message to decode + */ + public void unpack(MAVLinkPayload payload) { + payload.resetIndex(); + this.time_usec = payload.getLong(); + this.integration_time_us = payload.getInt(); + this.integrated_x = payload.getFloat(); + this.integrated_y = payload.getFloat(); + this.integrated_xgyro = payload.getFloat(); + this.integrated_ygyro = payload.getFloat(); + this.integrated_zgyro = payload.getFloat(); + this.time_delta_distance_us = payload.getInt(); + this.distance = payload.getFloat(); + this.temperature = payload.getShort(); + this.sensor_id = payload.getByte(); + this.quality = payload.getByte(); + + } + + /** + * Constructor for a new message, just initializes the msgid + */ + public msg_optical_flow_rad(){ + msgid = MAVLINK_MSG_ID_OPTICAL_FLOW_RAD; + } + + /** + * Constructor for a new message, initializes the message with the payload + * from a mavlink packet + * + */ + public msg_optical_flow_rad(MAVLinkPacket mavLinkPacket){ + this.sysid = mavLinkPacket.sysid; + this.compid = mavLinkPacket.compid; + this.msgid = MAVLINK_MSG_ID_OPTICAL_FLOW_RAD; + unpack(mavLinkPacket.payload); + //Log.d("MAVLink", "OPTICAL_FLOW_RAD"); + //Log.d("MAVLINK_MSG_ID_OPTICAL_FLOW_RAD", toString()); + } + + + /** + * Returns a string with the MSG name and data + */ + public String toString(){ + return "MAVLINK_MSG_ID_OPTICAL_FLOW_RAD -"+" time_usec:"+time_usec+" integration_time_us:"+integration_time_us+" integrated_x:"+integrated_x+" integrated_y:"+integrated_y+" integrated_xgyro:"+integrated_xgyro+" integrated_ygyro:"+integrated_ygyro+" integrated_zgyro:"+integrated_zgyro+" time_delta_distance_us:"+time_delta_distance_us+" distance:"+distance+" temperature:"+temperature+" sensor_id:"+sensor_id+" quality:"+quality+""; + } + } + \ No newline at end of file diff --git a/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_timesync.java b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_timesync.java new file mode 100644 index 0000000000..ddeec7b251 --- /dev/null +++ b/dependencyLibs/Mavlink/src/com/MAVLink/common/msg_timesync.java @@ -0,0 +1,85 @@ + // MESSAGE TIMESYNC PACKING +package com.MAVLink.common; +import com.MAVLink.MAVLinkPacket; +import com.MAVLink.Messages.MAVLinkMessage; +import com.MAVLink.Messages.MAVLinkPayload; + //import android.util.Log; + + /** + * Time synchronization message. + */ + public class msg_timesync extends MAVLinkMessage{ + + public static final int MAVLINK_MSG_ID_TIMESYNC = 111; + public static final int MAVLINK_MSG_LENGTH = 16; + private static final long serialVersionUID = MAVLINK_MSG_ID_TIMESYNC; + + + /** + * Time sync timestamp 1 + */ + public long tc1; + /** + * Time sync timestamp 2 + */ + public long ts1; + + + /** + * Generates the payload for a mavlink message for a message of this type + * @return + */ + public MAVLinkPacket pack(){ + MAVLinkPacket packet = new MAVLinkPacket(); + packet.len = MAVLINK_MSG_LENGTH; + packet.sysid = 255; + packet.compid = 190; + packet.msgid = MAVLINK_MSG_ID_TIMESYNC; + packet.payload.putLong(tc1); + packet.payload.putLong(ts1); + + return packet; + } + + /** + * Decode a timesync message into this class fields + * + * @param payload The message to decode + */ + public void unpack(MAVLinkPayload payload) { + payload.resetIndex(); + this.tc1 = payload.getLong(); + this.ts1 = payload.getLong(); + + } + + /** + * Constructor for a new message, just initializes the msgid + */ + public msg_timesync(){ + msgid = MAVLINK_MSG_ID_TIMESYNC; + } + + /** + * Constructor for a new message, initializes the message with the payload + * from a mavlink packet + * + */ + public msg_timesync(MAVLinkPacket mavLinkPacket){ + this.sysid = mavLinkPacket.sysid; + this.compid = mavLinkPacket.compid; + this.msgid = MAVLINK_MSG_ID_TIMESYNC; + unpack(mavLinkPacket.payload); + //Log.d("MAVLink", "TIMESYNC"); + //Log.d("MAVLINK_MSG_ID_TIMESYNC", toString()); + } + + + /** + * Returns a string with the MSG name and data + */ + public String toString(){ + return "MAVLINK_MSG_ID_TIMESYNC -"+" tc1:"+tc1+" ts1:"+ts1+""; + } + } + \ No newline at end of file From cbf02b3bbf4354748f3b64bd4ea5bab9170ea72c Mon Sep 17 00:00:00 2001 From: ne0fhyk Date: Tue, 6 Jan 2015 17:21:36 -0800 Subject: [PATCH 4/4] updated common library version. updated method to retrieve the valid follow types. update client library version. --- AidlLib/build.gradle | 4 +-- .../android/lib/gcs/follow/FollowType.java | 25 +++++++++++++++++++ ClientLib/mobile/build.gradle | 4 +-- .../core/gcs/follow/FollowAlgorithm.java | 10 ++++++-- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/AidlLib/build.gradle b/AidlLib/build.gradle index da9d86edbf..ec45ce3434 100644 --- a/AidlLib/build.gradle +++ b/AidlLib/build.gradle @@ -7,8 +7,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 20024 - versionName '2.0.24' + versionCode 20025 + versionName '2.0.25' } defaultPublishConfig "release" diff --git a/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java b/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java index 29f9a975f0..3033eb602e 100644 --- a/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java +++ b/AidlLib/src/com/o3dr/services/android/lib/gcs/follow/FollowType.java @@ -3,6 +3,9 @@ import android.os.Parcel; import android.os.Parcelable; +import java.util.ArrayList; +import java.util.List; + /** * Created by fhuya on 11/5/14. */ @@ -27,6 +30,11 @@ public String getTypeLabel() { return typeLabel; } + @Override + public String toString(){ + return getTypeLabel(); + } + @Override public int describeContents() { return 0; @@ -37,6 +45,23 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeString(name()); } + public static List getFollowTypes(boolean includeAdvanced){ + List followTypes = new ArrayList<>(); + followTypes.add(LEASH); + followTypes.add(LEAD); + followTypes.add(RIGHT); + followTypes.add(LEFT); + followTypes.add(CIRCLE); + followTypes.add(ABOVE); + + if(includeAdvanced){ + followTypes.add(SPLINE_LEASH); + followTypes.add(SPLINE_ABOVE); + } + + return followTypes; + } + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public FollowType createFromParcel(Parcel source) { return FollowType.valueOf(source.readString()); diff --git a/ClientLib/mobile/build.gradle b/ClientLib/mobile/build.gradle index 75c3fb22ac..88cb6773c5 100644 --- a/ClientLib/mobile/build.gradle +++ b/ClientLib/mobile/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.library' ext { PUBLISH_ARTIFACT_ID = '3dr-services-lib' - PUBLISH_VERSION = '2.1.34' + PUBLISH_VERSION = '2.1.35' PROJECT_DESCRIPTION = "3DR Services Client Library" PROJECT_LABELS = ['3DR', '3DR Services', 'DroneAPI', 'Android'] PROJECT_LICENSES = ['Apache-2.0'] @@ -15,7 +15,7 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 20134 + versionCode 20135 versionName PUBLISH_VERSION } diff --git a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java index d463619aa7..ad2f0a19ba 100644 --- a/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java +++ b/dependencyLibs/Core/src/org/droidplanner/core/gcs/follow/FollowAlgorithm.java @@ -23,8 +23,14 @@ public void changeRadius(Double radius) { } public enum FollowModes { - LEASH("Leash"), LEAD("Lead"), RIGHT("Right"), LEFT("Left"), CIRCLE("Orbit"), ABOVE("Above"), - SPLINE_LEASH("Spline Leash"), SPLINE_ABOVE("Spline Above"); + LEASH("Leash"), + LEAD("Lead"), + RIGHT("Right"), + LEFT("Left"), + CIRCLE("Orbit"), + ABOVE("Above"), + SPLINE_LEASH("Spline Leash"), + SPLINE_ABOVE("Spline Above"); private String name;