Introduction
Features
Waypoint
How Does The Drone Fly Autonomously Using Virtual Stick
Prerequisites
How To Run
Simulation
Welcome to the Mini Drone Simulation project, this repository is dedicated to the development and simulation of an autonomous mini drone. The primary goal of this project is to create a comprehensive environment where the drone can navigate autonomously using a variety of control algorithms.
The project is applied on
Mavic Mini 1, which originally does not support autonomous flights.
✔️ Autonomously navigating the drone towards destinations that are given before taking off, respectively.
✔️ Freely choose which destination to navigate to - among all existing destinations.
✔️ Dynamically set an existing destination (by dragging) to a new one during the drone's flight and navigates to it.
-
The algorithmic logic behind this feature is as follows:
onMarkerDragStart(@NonNull Marker marker)
Once dragging starts, it pauses the drone's current mission.
onMarkerDrag(@NonNull Marker marker)
Continuously updates the current coordinate as long as the location marker (in Waypoint) is being dragged.
onMarkerDragEnd(@NonNull Marker marker)
Once there is no longer dragging, updates the coordinate to be the new marker's coordinate after dragging and resumes mission.
-
Where all 3 methods are integrated in the following
MoveMarkerInRealTime():private void MoveMarkerInRealTime(){ Mymap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() { @Override public void onMarkerDragStart(@NonNull Marker marker) { getWaypointMissionOperator().PauseMission(); } @Override public void onMarkerDrag(@NonNull Marker marker) { LocationCoordinate2D newCoordinate=new LocationCoordinate2D(marker.getPosition().latitude,marker.getPosition().longitude); getWaypointMissionOperator().updateWaypoint(newCoordinate); } @Override public void onMarkerDragEnd(@NonNull Marker marker) { LocationCoordinate2D newCoordinate = new LocationCoordinate2D(marker.getPosition().latitude, marker.getPosition().longitude); getWaypointMissionOperator().updateWaypoint(newCoordinate); getWaypointMissionOperator().resumeMission(); } }); }
Waypoint is an application that sets up the drone's flight before taking off, using various buttons where each one serves its own purpose. Essentially, the feature where you can dynamically set a new destination, is highly relied on the Waypoint.
How buttons work:
-
LOCATEZooms in towards the red airplane displayed in the app (which is the drone' current position). -
ADDAdds a new destination by just clicking - in order to perform the click, the 'Add' button must be clicked -
CLEARClears all currently existing destinations. -
ADD POINTAdds a new destination by providing latitude, longtitude and altitude. -
CONFIGConfigures/initializes the needed specifications for the flight, such as: speed, altitude, where-to-land... etc. -
UPLOADUploads all filled settings for the Waypoint's mission so it can be ready to take off. -
STARTStarts the mission, after uploading all needed settings.Please note that only after starting your mission, you will be able to dynamically set a new destination.
-
STOPStops the mission.
Visit
MavicMiniWaypoint.javafor implementation details.
Essentially, MavicMiniMissionOperator.java is responsible to provide the autonomous algorithm, in particular, its relation with the observer:
private Observer<LocationCoordinate3D> locationObserver = new Observer<LocationCoordinate3D>() {
@Override
public void onChanged(LocationCoordinate3D currentLocation) {
// Observing changes to the drone's location coordinates
state = WaypointMissionState.EXECUTING;
distanceToWaypoint = distanceInMeters(
new LocationCoordinate2D(currentWaypoint.coordinate.getLatitude(), currentWaypoint.coordinate.getLongitude()),
new LocationCoordinate2D(currentLocation.getLatitude(), currentLocation.getLongitude())
);
double longitudeDiff = currentWaypoint.coordinate.getLongitude() - currentLocation.getLongitude();
double latitudeDiff = currentWaypoint.coordinate.getLatitude() - currentLocation.getLatitude();
if(!isPausedForUpdate){
pauseMission();
}
if (Math.abs(latitudeDiff) > originalLatitudeDiff) {
originalLatitudeDiff = Math.abs(latitudeDiff);
}
if (Math.abs(longitudeDiff) > originalLongitudeDiff) {
originalLongitudeDiff = Math.abs(longitudeDiff);
}
// Terminating the sendDataTimer and creating a new one
sendDataTimer.cancel();
sendDataTimer = new Timer();
if (!travelledLongitude) {
float speed = Math.max(
(float) (mission.getAutoFlightSpeed() * (Math.abs(longitudeDiff) / originalLongitudeDiff)),
0.5f
);
directions.pitch = longitudeDiff > 0 ? speed : -speed;
}
if (!travelledLatitude) {
float speed = Math.max(
(float) (mission.getAutoFlightSpeed() * (Math.abs(latitudeDiff) / originalLatitudeDiff)),
0.5f
);
directions.roll = latitudeDiff > 0 ? speed : -speed;
}
// When the longitude difference becomes insignificant
if (Math.abs(longitudeDiff) < 0.000002) {
checkLong++;
if(checkLong==1) {
textAppenderOper.appendTextAndScroll("finished travelling LONGITUDE");
Log.d(TAG, "finished travelling LONGITUDE");
}
directions.pitch = 0f;
travelledLongitude = true;
}
if (Math.abs(latitudeDiff) < 0.000002) {
CheckLat++;
if(CheckLat==1) {
textAppenderOper.appendTextAndScroll("finished travelling LATITUDE");
Log.d(TAG, "finished travelling LATITUDE");
}
directions.roll = 0f;
travelledLatitude = true;
}
// When the latitude difference becomes insignificant and there is no longitude difference
if (travelledLatitude && travelledLongitude) {
waypointTracker++;
if (waypointTracker < waypoints.size()) {
currentWaypoint = waypoints.get(waypointTracker);
originalLatitudeDiff = -1.0;
originalLongitudeDiff = -1.0;
travelledLongitude = false;
travelledLatitude = false;
directions = new Direction(); // Assuming Direction is a class with an appropriate constructor
} else {
state = WaypointMissionState.EXECUTION_STOPPING;
if (operatorListener != null) {
operatorListener.onExecutionFinish(null);
}
stopMission(null);
isLanding = true;
sendDataTimer.cancel();
if (isLanding && currentLocation.getAltitude() == 0f && !isLanded) {
sendDataTimer.cancel();
isLanded = true;
}
removeObserver();
}
sendDataTimer.cancel(); // Cancel all scheduled data tasks
} else {
if (state == WaypointMissionState.EXECUTING) {
directions.altitude = currentWaypoint.altitude;
} else if (state == WaypointMissionState.EXECUTION_PAUSED) {
directions = new Direction(0f, 0f, 0f, currentWaypoint.altitude);
}
move(directions);
}
if(isPausedForUpdate){
resumeMission();
}
}
};The methodology explained:
- The drone's current location is continuously monitored, and based on the difference between its current position and the target waypoint, the drone adjusts its speed and direction.
- The algorithm calculates how far the drone is from the waypoint in terms of latitude and longitude. It then adjusts the drone's pitch (forward/backward movement) and roll (side-to-side movement) to minimize these differences.
- When the drone is close enough to the target coordinates, it stops moving in that direction.
- Once both latitude and longitude adjustments are complete, the drone moves to the next waypoint.
- If all waypoints are visited, the mission stops, and the drone prepares to land.
Always executed in
executeMission().
DJI SDK MOBILE 4.16.4Google Maps.
-
Open a new project in Android Studio.
-
Perform the following command line in your terminal:
git clone https://github.com/osamaghaliah/Mini-Drone-Simulation.git
-
Connect your phone to the Android Studio.
-
Run the code.
Enjoy watching our autonomous by clicking the link below:




