DJI Mobile SDK 3.0 - android

When getting the mission manager, either by DJIMissionManager.getInstance() or djiAircraftInstance.getMissionManager(), the mission manager instance is never connected, ie missionManagerInstance.isConnected() always returns false, and proceeding without the isConnected check causes a crash. Am I missing a step in setting up or retreiving the mission manager?
A minute ago I asked the same question on their forums here.
Any help would be appreciated. I have been over their examples a thousand times but it seems all of the examples are using an older version of the sdk.
EDIT: More information that you could figure out but I'll add in for the heck of it.
Mission manager instance is not null because calling isConnected() returns false, and the drone is connected as well.

I just test the isMissionReadyToExecute and MissionManager.isConnected, i found that no matter when I call them, they always return true. So I consider that it should be the bugs inside the SDK.
And I found a walk around solution for this problem.
Initialize the mission.
// Step 1: create mission
DJIWaypointMission waypointMission = new DJIWaypointMission();
waypointMission.maxFlightSpeed = 14;
waypointMission.autoFlightSpeed = 4;
List<DJIWaypoint> waypointsList = new LinkedList<>();
// Step 2: create waypoints and prepare coordinates
DJIWaypoint northPoint = new DJIWaypoint(mHomeLatitude + 10 * Utils.ONE_METER_OFFSET, mHomeLongitude, 10f);
DJIWaypoint eastPoint = new DJIWaypoint(mHomeLatitude, mHomeLongitude + 10 * Utils.calcLongitudeOffset(mHomeLatitude), 20f);
DJIWaypoint southPoint = new DJIWaypoint(mHomeLatitude - 10 * Utils.ONE_METER_OFFSET, mHomeLongitude, 30f);
DJIWaypoint westPoint = new DJIWaypoint(mHomeLatitude, mHomeLongitude - 10 * Utils.calcLongitudeOffset(mHomeLatitude), 40f);
//Step 3: add actions
northPoint.addAction(new DJIWaypoint.DJIWaypointAction(DJIWaypoint.DJIWaypointActionType.GimbalPitch, -60));
northPoint.addAction(new DJIWaypoint.DJIWaypointAction(DJIWaypoint.DJIWaypointActionType.StartTakePhoto, 0));
eastPoint.addAction(new DJIWaypoint.DJIWaypointAction(DJIWaypoint.DJIWaypointActionType.StartTakePhoto, 0));
southPoint.addAction(new DJIWaypoint.DJIWaypointAction(DJIWaypoint.DJIWaypointActionType.RotateAircraft, 60));
southPoint.addAction(new DJIWaypoint.DJIWaypointAction(DJIWaypoint.DJIWaypointActionType.StartRecord, 0));
westPoint.addAction(new DJIWaypoint.DJIWaypointAction(DJIWaypoint.DJIWaypointActionType.StopRecord, 0));
//Step 4: add waypoints into the mission
waypointsList.add(northPoint);
waypointsList.add(eastPoint);
waypointsList.add(southPoint);
waypointsList.add(westPoint);
waypointMission.addWaypoints(waypointsList);
mDJIMission = waypointMission;
prepare the mission.
mMissionManager.prepareMission(mDJIMission, new DJIMission.DJIMissionProgressHandler() {
#Override
public void onProgress(DJIMission.DJIProgressType type, float progress) {
setProgressBar((int)(progress * 100f));
}
}, new DJICompletionCallback() {
#Override
public void onResult(DJIError error) {
if (error == null) {
Utils.setResultToToast(mContext, "Success!");
} else {
Utils.setResultToToast(mContext, "Prepare: " + error.getDescription());
}
}
});

Related

Digital persona SDK - native problems

I am using in my app Digital Persona SDK for fingerprint identification.
When i use the identify function on less then 250 fmds it works fine.
Engine.Candidate candidates[] = m_engine.Identify(searchedFmd, 0, fmdArray, DEFAULT_THRESHOLD, 1); //fmdArray < 250
But with fmdArray > 250 it gives me a native runtime error:
A/art: art/runtime/indirect_reference_table.cc:132] JNI ERROR (app bug): local reference table overflow (max=512)
Now i runned this app on couple of android devices and came to conclusion that my app crushes with fmdArray > 250 when its running on android 7. But android 8 works fine. In 8 i can preform a check on even 4000 fmds and it works fine.
But i need to run this code in a specific device, that running android 7.
I tried to run it in couple of threads of 250 fmds only. But after single run there is another problem with the SDK. On the second run it doesnt works.
This is what i do:
First i get a fingerprint capture that i want to identify:
Reader.CaptureResult capture = m_reader.Capture(fidFormat, UrUSDK.DefaultImageProcessing, m_DPI, timeout);
// In second run, code after this line is not executed.
// My guees its not coming back from native. No exeptions. No errors.
...
Fmd scannedFmd = m_engine.CreateFmd(capture.image, fmdFormat);
...
int index = identifyFinger(fmds, scannedFmd);
...
private int identifyFinger(List<Fmd> fmdSearchArray, Fmd scannedFmd) {
List<List<Fmd>> lists = splitToChunks(fmdSearchArray);
AtomicInteger index = new AtomicInteger(-1);
List<Callable<Void>> threads = new ArrayList<>(lists.size());
AtomicInteger iteratorIndex = new AtomicInteger(0);
for (int i = 0; i < lists.size(); i++) {
int currentChunk = i;
Callable<Void> thread = () -> {
System.out.println(Thread.currentThread().getName() + " with chunk: " + iteratorIndex.getAndIncrement());
Fmd[] fmds = lists.get(currentChunk).toArray(new Fmd[IDENTIFY_BOUNDARY]);
try {
Engine.Candidate[] candidates = m_engine.Identify(scannedFmd, 0, fmds, threshold, 1);
if (candidates.length > 0) {
index.set(candidates[0].fmd_index + (currentChunk * IDENTIFY_BOUNDARY));
}
} catch (UareUException e) {
}
System.out.println(Thread.currentThread().getName() + " with chunk: " + currentChunk + " finished!");
return null;
};
threads.add(thread);
}
try {
List<Future<Void>> futures = executorService.invokeAll(threads);
System.out.println("All threads finished: " + index.get());
return index.get();
} catch (InterruptedException e) {
e.printStackTrace();
return -1;
}
}
...
private List<List<Fmd>> splitToChunks(List<Fmd> fmdSearchArray) {
int size = fmdSearchArray.size();
List<List<Fmd>> lists;
if (size > IDENTIFY_BOUNDARY) {
int chunks = size / IDENTIFY_BOUNDARY;
if (size % IDENTIFY_BOUNDARY > 0) {
chunks++;
}
lists = new ArrayList<>(chunks);
for (int i = 0; i < chunks; i++) {
if (i + 1 == chunks) {
lists.add(new ArrayList<>(fmdSearchArray.subList(i * IDENTIFY_BOUNDARY, size)));
break;
}
lists.add(new ArrayList<>(fmdSearchArray.subList(i * IDENTIFY_BOUNDARY, (i + 1) * IDENTIFY_BOUNDARY)));
}
} else {
lists = new ArrayList<>(1);
lists.add(fmdSearchArray);
}
return lists;
}
The problem with this code is that it runs once. But at another try it doesnt come back from the native code of Caprture call.
So my question is:
How i can overcome this and make it work from my java code?
Or at least what is the direction of the solution?
The root cause is that this Identify function holds on to at least two references per returned Candidate after pushing it to the result array. It should instead release the references after pushing, so its use of the (limited) local reference table remain constant. You should file a bug about that.
The simplest workaround for now is to cut your fmdArray into 250-sized chunks and call Identify for each chunk.

Set winner after turn based game Google API Android

I'm creating a turn based game on the Android platform using the API provided by Google.
At the end of the latest turn (in my case the third one), I'd like to set the winner but I have not found any API that permits this. Naturally I have all the data at the end of the game to set it.
I've not read something in the documentation - does this feature exist or should I handle it myself?
String playerId = Games.Players.getCurrentPlayerId(getApiClient());
String myOponentId = mMatch.getParticipantId(playerId);
opponentResult = new ParticipantResult(myOponentId,
ParticipantResult.MATCH_RESULT_WIN, 1);
creatorResult = new ParticipantResult(playerId,
ParticipantResult.MATCH_RESULT_LOSS, 2);
Games.TurnBasedMultiplayer.finishMatch(getApiClient(), mMatch.getMatchId(),mMatch.getData(), creatorResult,opponentResult )
.setResultCallback(new ResultCallback<TurnBasedMultiplayer.UpdateMatchResult>() {
#Override
public void onResult(TurnBasedMultiplayer.UpdateMatchResult result) {
processResult(result);
}
});

Android TrafficStats - Oversized value is a bug?

I am investigating about traffic measuring in android. I am developing on a Galaxy S4 and I programmed a service that catches TrafficStats API one time per minute, saves in SharedPreference the accumulated traffic (AKA BaseTraffic) and saves in database the difference between the current traffic minus BaseTraffic.
The problem is that in short periods (15 min) TrafficStats return an oversized value (1.6 GB per minute) and ever the same value. Someone know if this is a bug or other issue.
My code is the next for get the traffic:
public class TrafficTracker {
public static long getCurrentTraffic() {
long traff = 0;
traff = (TrafficStats.getTotalRxBytes() + TrafficStats.getTotalTxBytes());
if (traff > 0) {
return traff;
} else {
throw new UnsupportedOperationException("TrafficStats not supported");
}
}
public static long getTrafficWithOutBase(long baseTraffic) {
return TrafficStats.getTotalTxBytes() + TrafficStats.getTotalRxBytes() - baseTraffic;
}
}
And call this code here:
if (preferences.getBaseTraffic() != null) {
if (TrafficTracker.getCurrentTraffic() > preferences.getBaseTraffic().getByteTraffic()) {
TrafficObject trafficObject = new TrafficObject(new Date(calendar.getTimeInMillis()), TrafficTracker.getTrafficWithOutBase(preferences.getBaseTraffic().getByteTraffic()));
daoTraffic.create(trafficObject);
preferences.setBaseTraffic(new TrafficObject(new Date(System.currentTimeMillis()), preferences.getBaseTraffic().getByteTraffic() + trafficObject.getByteTraffic()));
} else {//when stats are reseted
TrafficObject trafficObject = new TrafficObject(new Date(calendar.getTimeInMillis()), TrafficTracker.getCurrentTraffic());
daoTraffic.create(trafficObject);
preferences.setBaseTraffic(trafficObject);
}
}
** UPDATE **
I found my error :). I replace >= instead of >. Now works properly when it is disconnected from data or wifi.
if (TrafficTracker.getCurrentTraffic() >= preferences.getBaseTraffic().getByteTraffic())
I found my error :). I replace >= instead of >. Now works properly when it is disconnected from data or wifi.
if (TrafficTracker.getCurrentTraffic() >= preferences.getBaseTraffic().getByteTraffic())

How to navigate in sygic maps

I have integrated sygic in my android application using a surface view. I want to navigate in that sygic application . I have used this code :
SWayPoint wp = new SWayPoint();
wp.Location = new LONGPOSITION(34, 35);
ApplicationAPI.StartNavigation(err, wp, 0, true, false, MAX);
But it is not working. Any ideas ?
I have once implemented Sygic in an app and this is basically how my code looks like (after hours of debug because the documentation was very poor...):
// surfaceView for displaying the "map"
SurfaceView mSygicSurface = (SurfaceView) findViewById(R.id.sygic_surface); // surface
// api status
int mSygicAPIStatus = -2;
// start the drive
ApplicationAPI.startDrive(new ApiCallback() {
public void onRunDrive() {
mSygicSurface.post(new Runnable() {
public void run() {
runDrive(mSygicSurface, getPackageName());
}
});
}
public void onInitApi() // gets called after runDrive();
{
mSygicAPIStatus = ApplicationAPI.InitApi(getPackageName(), true, new ApplicationHandler() { /* nothing relevant here */ }); // api initialization
if (mSygicAPIStatus != 1) {
// error
return;
}
}
});
Once you want to navigate somewhere:
GeoPoint point = new GeoPoint(/* ... */, /* ... */);
final SWayPoint wayPoint = new SWayPoint("", point.getLongitudeE6(), point.getLatitudeE6());
SError error = new SError();
final int returnCode = ApplicationAPI.StartNavigation(error, point, NavigationParams.NpMessageAvoidTollRoadsUnable, true, true, 0);
Carefully note that Sygic uses E6 coordinates.
This is not an answer on the question, but for whose who searching for weird sygic exmaples in 2017 I put it here
ApiMaps.showCoordinatesOnMap(new Position((int)(-84.41949*100000.0),(int)(33.7455*100000.0)),1000,0);
//LONGITUDE first!!
//and multiply on 100 000
//https://developers.sygic.com/reference/java3d/html/classcom_1_1sygic_1_1sdk_1_1remoteapi_1_1_api_maps.html
p.s. this is for standalone apk

Android app uses static method to transfer and plot data

I've been asking questions regarding my Android project that continually plots Bluetooth data in real-time.
Basically what I've already done is create a first version of my app by cobbling together some open source code Blueterm and OrientationSensorExample
It's been suggested that I add a thread, a handler, a Service, or use Async Task, or AIDL, etc. But I don't know how to use any of these and would appreciate an explanation.
Here's a description of the Blueterm open source code I started with (see link above). Blueterm is basically a terminal emulator program that communicates over Bluetooth. It consists of several activities with Blueterm being the most important. It discovers, pairs, and connects with a remote Bluetooth device that supports SPP/RfComm. When connected I can use Blueterm to configure the remote device by sending it commands to turn on sampling, change the number of channels to sample (to one channel), change to format of the incoming data (I like comma separated data), etc
Here's a description of the OrientationSensorExample open source code I started with (see link above). It's basically an example application of the AnroidPlot library. The OrientationSensor activity implements SensorEventListener. This includes overriding onSenorChanged() which is called whenever new orientation sensor data is taken, and it redraws the graph.
Having cobbled together these two open source projects (Blueterm and OrientationSensorExample) into one application (Blueterm) here's a description of how the overall application (Blueterm) works. When I start Blueterm the whole screen emulates a nice blue terminal. From the Options Menu I discover, pair with, connect to, and configure a remote bluetooth device as described above. Once I have configured the remote device, I go again to the Options Menu and select "Plot data" which launches the Plot activity. The terminal emulator goes away, and a nice scrolling real-time plot from the Plot activity shows up.
As far as I can tell there is a background thread that calls an update() method as follows:
/**
* Look for new input from the ptty, send it to the terminal emulator.
*/
private void update() {
int bytesAvailable = mByteQueue.getBytesAvailable();
int bytesToRead = Math.min(bytesAvailable, mReceiveBuffer.length);
try {
int bytesRead = mByteQueue.read(mReceiveBuffer, 0, bytesToRead);
append(mReceiveBuffer, 0, bytesRead);
//VTR use existing handler that calls update() to get data into plotting activity
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
In the update() method I found it convenient to call my Plot.plotData() method and pass it the same date that is passed to the append() method to plot the data. NOTE: This only works if plotData() is a static method. No one has been able to explain why.
Anyway plotData() is a static method and here's how it and it's helper methods look now:
private static StringBuffer strData = new StringBuffer("");
public static void plotData(byte[] buffer, int base, int length) {
Log.i("Entering: ", "plotData()");
/*
byte[] buffer = (byte[]) msg.obj;
int base = msg.arg1;
int length = msg.arg2;
*/
for (int i = 0; i < length; i++) {
byte b = buffer[base + i];
try {
if (true) {
char printableB = (char) b;
if (b < 32 || b > 126) {
printableB = ' ';
}
Log.w("Log_plotData", "'" + Character.toString(printableB)
+ "' (" + Integer.toString(b) + ")");
strData.append(Character.toString(printableB));
if (b == 10)
{
Log.i("End of line: ", "processBlueData()");
Log.i("strData", strData.toString());
splitData(strData);
strData = new StringBuffer("");
}
}
} catch (Exception e) {
Log.e("Log_plotData_exception", "Exception while processing character "
+ Integer.toString(i) + " code "
+ Integer.toString(b), e);
}
}
Log.i("Leaving: ", "plotData()");
}
private static void splitData(StringBuffer strBuf) {
String strDash = strBuf.toString().trim();
String[] strDashSplit = strDash.split("-");
for (int ndx = 0; ndx < strDashSplit.length; ndx++)
{
if (strDashSplit[ndx].length() > 0)
Log.i("strDashSplit", ndx + ":" + strDashSplit[ndx]);
String strComma = strDashSplit[ndx].trim();
String[] strCommaSplit = strComma.split(",");
for (int mdx = 0; mdx < strCommaSplit.length; mdx++)
{
if (strCommaSplit[mdx].length() > 0)
Log.i("strCommaSplit", mdx + ":" + strCommaSplit[mdx]);
if (mdx == 1)
{
int raw = Integer.parseInt(strCommaSplit[1],16);
Log.i("raw", Integer.toString(raw));
float rawFloat = raw;
Log.i("rawFloat", Float.toString(rawFloat));
float ratio = (float) (rawFloat/65535.0);
Log.i("ratio", Float.toString(ratio));
float voltage = (float) (5.0*ratio);
Log.i("voltage", Float.toString(voltage));
nowPlotData(voltage);
}
}
}
}
public static void nowPlotData(float data) {
// get rid the oldest sample in history:
if (plotHistory.size() > HISTORY_SIZE) {
plotHistory.removeFirst();
}
// add the latest history sample:
plotHistory.addLast(data);
// update the plot with the updated history Lists:
plotHistorySeries.setModel(plotHistory, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
//VTR null pointer exception?
if (plotHistoryPlot == null)
Log.i("aprHistoryPlot", "null pointer exception");
// redraw the Plots:
plotHistoryPlot.redraw();
}
If it is strongly recommended that plotData() not be a static method and that I should do something else please explain here and how. Thanks!
This might be a question much better suited for Code Review, rather than here. Perhaps you can reformulate to post it there, or trim it a lot to repost it here.
Furthermore, to answer: "It's been suggested that I add a thread, a handler, a Service, or use Async Task, or AIDL, etc. But I don't know how to use any of these and would appreciate an explanation.", the best advise would be to link you to a book about android, such as: http://commonsware.com/Android/ . Chapters 35 and 36 deal with services, while chapter 20 is about threads. You will never get an answer as complete as those chapters here.

Categories

Resources