What are the stages for initialising and executing a WayPoint Mission in DJI Windows SDK? - dji-sdk

I am using the following code to try and initialise a Waypoint Mission and load it to the aircraft ( a DJI Mavic Air).
I first check the state of the waypoint handler, then initialise a waypoint, add it to the list, then include the list in the initialised waypoint mission. The method for loading the waypoint mission to the aircraft is then run and the state checked afterwards. The output from the debugs is seen below:
Waypoint state = READY_TO_UPLOAD;
New waypoint location - 55.555549621582,0.555555522441864
Load mission return value - INVALID_REQUEST_IN_CURRENT_STATE
Waypoint state = READY_TO_UPLOAD
The state of READY_TO_UPLOAD suggests that it is in a suitable state to upload the waypoint mission according to the Windows SDK documentation, however clearly the upload fails and the state remains unchanged.
What needs to be changed in order for the waypoint mission to successfully load so it can be run by the aircraft?
//Check the initial state of the waypoint handler
var currentState = DJISDKManager.Instance.WaypointMissionManager.GetWaypointMissionHandler(0).GetCurrentState();
Debug.WriteLine("Waypoint state = {0}", currentState);
//Initialise new location coordinate
randomLocation.X = 55.55555;
randomLocation.Y = 0.55555555;
Debug.WriteLine("New waypoint location - {0},{1}", randomLocation.X, randomLocation.Y);
LocationCoordinate2D waypointLocation = new LocationCoordinate2D { latitude = randomLocation.X, longitude = randomLocation.Y };
// Create a waypoint instance and add to waypoint list
Waypoint waypoint = new Waypoint { location = waypointLocation };
waypointList.Add(waypoint);
//Create new waypoint mission instance and load in the waypoint list
WaypointMission waypointMission = new WaypointMission
{
waypointCount = 1,
autoFlightSpeed = 2.5,
finishedAction = WaypointMissionFinishedAction.NO_ACTION,
headingMode = WaypointMissionHeadingMode.USING_WAYPOINT_HEADING,
flightPathMode = WaypointMissionFlightPathMode.CURVED,
repeatTimes = 0,
waypoints = waypointList,
missionID = 1
};
//load the waypoint mission to the aircraft and check the current state
var load_retval = DJISDKManager.Instance.WaypointMissionManager.GetWaypointMissionHandler(0).LoadMission(waypointMission); ;
Debug.WriteLine("Load mission return value - {0}", load_retval);
currentState = DJISDKManager.Instance.WaypointMissionManager.GetWaypointMissionHandler(0).GetCurrentState();
Debug.WriteLine("Waypoint state = {0}", currentState);

After a long time of trail and error I figured out the steps needed to start a waypoint mission:
Setting the SDK into ground station mode
First you have to set the SDK into ground station mode with the following method:
DJISDKManager.Instance.ComponentManager.GetFlightControllerHandler(0, 0).SetGroundStationModeEnabledAsync(new BoolMsg() { value = true })
Loading the mission
Second you have to load your waypoint mission to the SDK, using the following method:
DJISDKManager.Instance.WaypointMissionManager.GetWaypointMissionHandler(0).
LoadMission(waypointMission)
Where waypointMission could bethe waypoint mission in your question. This waypoit mission have to follow some restrictions. For example the total distance can't be to long(not sure what the exact number is). This methode will return an SDKError if there is something wrong with the mission.
Uploading the waypoint mission to the drone
After the mission is loaded to the SDK it still has to be uploaden to the drone. This is done with the following method:
DJISDKManager.Instance.WaypointMissionManager.GetWaypointMissionHandler(0).
UploadMission()
(optional) Stating the simulator
At this point you could start simulation mode if you don't want your drone to actually take off. This can be done with the following code:
FlightControllerHandler _flightControllerHandler = DJISDKManager.Instance.ComponentManager.GetFlightControllerHandler(0, 0);
var simSettings = new SimulatorInitializationSettings()
{
latitude = 0,
longitude = 0,
satelliteCount = 12
};
await _flightControllerHandler.StartSimulatorAsync(simSettings);
It's important that the satelliteCount is above 10. Else the SDK wil give and error about the GPS signal strength not being good enough.
Starting the mission
Finaly you can start the waypoint mission as follows
DJISDKManager.Instance.WaypointMissionManager.GetWaypointMissionHandler(0).StartMission()
Other things to note:
Most of these calls are async and are best awaited.
Even if you await the calls I noticed uploading the mission would not be finished at the time the method finished. So if you would call StartMission() right after UploadMission() this could result in a INVALID_REQUEST_IN_CURRENT_STATE
I worked around this by having a seperate button for loading and starting the mission.This way I can wait for the mission to be uploaded before I start the mission.
All of the above methods return a SDKError type. If all went well this would be a NO_ERROR it's important to check if this is the case for every call.

Related

OnboardSDK: mission management and HomePoint initialization

I am having Matrice 210 and use OSDK for uploading mission. But the OSDK will not allow uploading if the HomePoint of the aircraft was not initialized.
I got error "WAYPOINT_MISSION_POINTS_TOO_FAR" if turning on the drone only, and I have to turn on RC and connect DJI GO application for the HomePoint being created.
If I understand correctly, the mission manager only accept mission when the drone has strong GPS signal, but the document do not say anything about the HomePoint initializing.
I try to find in the SDK a function to tell the drone get it current GPS as HomePoint, but there is no such thing available in the code. Do I miss something?
Update:
Here is how I setup the mission manager:
void setWaypointInitDefaults(WayPointInitSettings* fdata)
{
fdata->maxVelocity = 10;
fdata->idleVelocity = 5;
fdata->finishAction = 0;
fdata->executiveTimes = 1;
fdata->yawMode = 0;
fdata->traceMode = 0;
fdata->RCLostAction = 1;
fdata->gimbalPitch = 0;
fdata->latitude = 0;
fdata->longitude = 0;
fdata->altitude = 0;
}
...
bool InitWaypointMission(Vehicle* vehicle, int numberWaypoints, double maxSpeed, double turnSpeed, bool usePointsHeading)
{
WayPointInitSettings fdata;
setWaypointInitDefaults(&fdata);
fdata.indexNumber = numberWaypoints;
fdata.maxVelocity = maxSpeed;
fdata.idleVelocity = turnSpeed;
if ( usePointsHeading )
fdata.yawMode = 3;
ACK::ErrorCode initAck = vehicle->missionManager->init(DJI_MISSION_TYPE::WAYPOINT, responseTimeout, &fdata);
if (ACK::getError(initAck))
{
ACK::getErrorCodeMessage(initAck, __func__);
return false;
}
vehicle->missionManager->printInfo();
return true;
}
On DJI drones, the Homepoint is automatically acquired when the drone has visibility of enough GPS satellites. A method that can tell the drone to get its' current position as homepoint will not be useful - if the drone can indeed get a good fix on its' current location in GPS co-ordinates, it has already set it as a homepoint, or will do so in the next few seconds.
There may be many reasons why you are getting the WAYPOINT_MISSION_POINTS_TOO_FAR error, but you will need to provide more context to help us narrow it down. Some things that are useful to report:
After powering on the drone, how long are you letting it sit in clear
skies before trying to upload the mission?
When you initialize your waypoint mission through the MissionManager, have you made sure to set the RCLostAction to Keep Going?
Is the behavior reproducible in simulation?

GPS accuracy Issues

I am developing a windows phone sports tracker app, that uses gps sensors to calculate the distance travelled by the runner, I am using geocoordinatewatcher class for the same, setting the movement threshold to 100. But, I find my app giving distance values even when the device is kept stationary. My app should give distance only when the device changes its position. I found the same bug in othere apps that are on the marketplace, please tell me where am I doing wrong?
My Code.
watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
watcher.MovementThreshold = 150;
watcher.PositionChanged += watcher_PositionChanged;
watcher.Start();
{
latitudeCurrent = e.Position.Location.Latitude;
longitudeCurrent = e.Position.Location.Longitude;
if (stepCounter == 0)
{
latitudePrevious = latitudeCurrent;
longitudePrevious = longitudeCurrent;
distanceTravelled += Math.Round(Calculate(latitudePrevious,longitudePrevious,latitudeCurrent,longitudeCurrent),2);
txbDistanceTravelled.Text = distanceTravelled.ToString();
txbCalories.Text=string.Format("{0:f0}", distanceTravelled * 65);
stepCounter++;
var millisPerKilometer = (distanceTravelled) * (System.Environment.TickCount - _previousPositionChangeTick);
txbPace.Text = TimeSpan.FromMilliseconds(millisPerKilometer).ToString(#"mm\:ss");
double hrs = counterTick / 3600;
if (!double.IsNaN((distanceTravelled / hrs)))
{
txbSpeed.Text = (distanceTravelled / hrs).ToString();
}
else
{
txbSpeed.Text = "0";
}
}
}
You are developing your app for Windows Phone 7 or Windows Phone 8? IF you are developing for the later, you need to use the new Geolocator class and not GeoCoordinateWatcher.
Also, as LewisBenge said, if you are testing This indoor you can get WiFi positions or even cellular data. It could be better to test outdoor.
Your GPS signal might be weak in the place where you are testing. Try it in the outdoor location.

Geolocator and accuracy in Windows Phone 8

I have a few questions about Geolocator and property DesiredAccuracy.
I have the method GetMyPosition:
public async Task<Geoposition> GetMyPosition()
{
Geoposition myGeoposition = null;
Geolocator myGeolocator = new Geolocator();
myGeolocator.DesiredAccuracy = PositionAccuracy.High;
try
{
myGeoposition = await myGeolocator.GetGeopositionAsync();
return myGeoposition;
}
catch (Exception ex)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Can't get the position");
});
return null;
}
}
1) Why
Geolocator.DesiredAccuracy = PositionAccuracy.High;
Geolocator.GetGeopositionAsync();
always return Geoposition.Coordinate.PositionSource = Cellular with accuracy 400 - 1600 m (on device Nokia Lumia 520)?
2) Under what settings I can get a high accuracy (50 - 100 m) and PositionSource = Satellite?
3) If I have the loaded maps on my device and I activated the airplane mode on the device, then code
Geolocator myGeolocator = new Geolocator();
myGeolocator.DesiredAccuracy = PositionAccuracy.High;
try
{
myGeoposition = await myGeolocator.GetGeopositionAsync();
return myGeoposition;
}
will work? Without a celluar, only a satellite?
4) How strong is the precision of coordinates depends on the device?
Thanks in advance!
Taken from MSDN
Although the Location Service uses multiple sources of location information, and any of the sources may not be available at any given time (for example, no GPS satellites or cell phone towers may be accessible), the native code layer handles the work of evaluating the available data and choosing the best set of sources. All your application needs to do is to choose between high accuracy or the default, power-optimized setting. You can set this value when you initialize the main Location Service class, GeoCoordinateWatcher.
C#
GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
So it seems like you can't control which source is used but rather the available source will be used based on the specified position accuracy on GeoCoordinateWatcher. Try initializing a GeoCoordinateWatcher with high accuracy and see what happens
var geoWatcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
You can use
Geolocator myGeolocator = new Geolocator();
myGeolocator.DesiredAccuracyInMeters = 20;
...
to explicitly state how accurate you want the location to be which would allow the device to manage its power a little better but whether you get close to that accuracy with your result depends on the quality of the location the device can get. If you're inside a building for example you're not going to get something that accurate without connecting to WIFI

Map tap event / mouse down event in windows phone 8?

I am using the windows phone emulator. I wrote a very simple program: draw a marker on the map when the user tap the map once.
Then I used map_tap event, and get the tapped location as follows,
private void map_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
Point p = e.GetPosition(null);
GeoCoordinate s = map.ConvertViewportPointToGeoCoordinate(p);
Ellipse myCircle = new Ellipse();
myCircle.Fill = new SolidColorBrush(Colors.Blue);
myCircle.Height = 20;
myCircle.Width = 20;
myCircle.Opacity = 50;
MapOverlay myLocationOverlay = new MapOverlay();
myLocationOverlay.Content = myCircle;
myLocationOverlay.PositionOrigin = new Point(0, 0);
myLocationOverlay.GeoCoordinate = s;
MapLayer myLocationLayer = new MapLayer();
myLocationLayer.Add(myLocationOverlay);
map.Layers.Add(myLocationLayer);
}
The problem is that, the point I get is not the point where the mouse (in the emulator it is a mouse but not a finger) clicked. It is some distance lower (about 50 pixels lower) than where I clicked.
So wherever I click in the emulator, the circle is drawn below where I clicked, it's some kind of weird.
Is there anything wrong with my code?
Thank you very much.
The GestureEventArgs.GetPosition() method takes a parameter specifying what UIElement to get the coordinate relative to (see the MSDN documentation). So, try doing
Point p = e.GetPosition(map);
instead.

How to Monitor If my current Location is getting close to a preset Location

say, I have setUp a location I wanted to go for example Time Square ( LatLon :40.760586,-73.984852) in my WP App. Suppose, I want to travel in a taxi to go to Time Square and with my app turn on. How do I keep tracking my current GPS is getting closer to that place?? How to determine I am withing the range?? The below code is for current GPS.
GeoCoordinateWatcher tracker;
void tracker_PositionChanged(object sender, GeoPositionChangedEventArgs e)
{
textLatitude.Text = e.Position.Location.Latitude.ToString("0.000");
textLongitude.Text = e.Position.Location.Longitude.ToString("0.000");
}
Thank in advance. Appreciate your help.
The GeoCoordinate class already has GetDistanceTo() method
It can be used as follows:
GeoCoordinate start = new GeoCoordinate(startLatitude, startLongitude);
GeoCoordinate end = new GeoCoordinate(endLatitude, endLongitude);
double distance = start.GetDistanceTo(end);
You can set this to be calculated every time the GeoCoordinateWatcher class fires the "PositionChanged" event

Resources