I am trying to calibrate an accelerometer, but I can't obtain the 6 sample values at 6 different acceleration readings required for the calibration. PreliminaryW is a double[6][3] array made to fill those sample values. It is 6 by 3 because each acceleration reading has an x, y, and a z component.
I am planning to sample them by pressing a button at the 6 different acceleration readings. This button makes "calibrate" true.
I ofcourse, first make "calibrating" true to start this thread.
For some unfathomable reason, preliminaryW[i] = currentAcc seems to be filling up from 0 to i with the same value instead of just i. I made sure that the currentAcc is different every time I press the "calibrate" button.
What is wrong with my code?
public synchronized void run() {
Log.d(TAG, "+ in Calibrator thread +");
int i = -1;
while (calibrating) {
if (calibrate) {
i = i + 1;
calibrate = false;
preliminaryW[i] = currentAcc;
if (i == 5) {
calibrating = false;
}
}
}
}
I'm not very familiar with the inner-workings of the accelerometer, and it's hard to decide why it's not working without seeing more of the code. For example, can you be sure that there's only one instance of the Thread, or are you creating multiple instances?
Why does this need to be in a Thread?
Looping like that is not good practice either, you should use wait/notify if you absolutely need a Thread. (more info at http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)
I've drafted a class that does approximately what you want, but doesn't use threading. You could create a Calibrator and then call performCalibration() with each new value:
class Calibrator{
int count = 0;
double[][] preliminaryW = new double[6][3];
public void performCalibration(double[] currentAcc){
preliminaryW[count] = currentAcc;
count++;
}
}
without the Thread and "busy loop", you might be able to omit those flags for 'calibrate' and 'calibrating' which would certainly help debugging as well.
Good Luck!
Related
I need to perform Dynamic Time Wrapping(DTW) algorithm with some previously stored data and Accelerometer data. But I am unable to handle the huge amount of data coming from accelerometer. I need to determine a step. In order to do that I have stored a number of data previously and trying to match with the current data.
ArrayList<Double> test=new ArrayList<Double>();
public void onSensorChanged(SensorEvent event) {
double x=event.value[0];
double y=event.value[1];
double z=event.value[2];
double a=Math.sqrt(x*x+y*y+z*z);
test.add(a);
new ProgressRunner().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,x);
private class ProgressRunner extends AsyncTask<Double, Integer, Boolean>
{
#Override
protected Boolean doInBackground(Double... params) {
new Thread(new Runnable() {
#Override
public void run() {
double r=DTWDistance(StepSamples.sample1, standTest);
if(r<700) /* "Step Detected */
}
}).start();
return null;
}
But I am getting huge data coming from the sensor. My question is how do I handle this data and match with a sample data continuously. Also I have tested with a Log.d, I'm sure the problem is related to how I handle this Live data but I can't find a way out. Any suggestion would be helpful.
I have also tried this by doing it an interval of 2 sec but an OutOfMemeoryBoundsException throws
if((System.currentTimeMillis()-sTime)/1000>2){
new ProgressRunner().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,x);
}
One of the solution to address this problem is keeping a threshold for the change in the sensor values. If the change in deltaX, deltaY, deltaZ are greater then you can start the AsyncTask else dont.
Since u are not keeping any threshold values the number of threads u create is very huge in number.
EDIT 1:
Here is a link to a small tutorial that will help you to kick start... in this link he has used a time interval and a threshold for shaking the device... i bet this is a perfect solution for your requirement
Tutorial Link
Do you need to process every single value or are you fine processing every x (e.g. 0.1) seconds? I call a method that checks "now - lastProcessedTime". If that value is > 100ms, I will handle the data and update lastProcessedTime = now. If not, I will throw away the sensor value.
I am a beginner and I want a complete example in LibGDX how to limit the framerate to 50 or 60. Also how to mangae interpolation between game state with simple example code
e.g. deWiTTERS Game Loop:
#Override
public void render()
{
float deltaTime = Gdx.graphics.getDeltaTime();
Update(deltaTime);
Render(deltaTime);
}
There is a Gdx.graphics.setVsync() method (generic = backend-independant), but it is not present in 0.9.1, only in the Nightlies.
"Relying on vsync for fixed time steps is a REALLY bad idea. It will break on almost all hardware out there.
See LwjglApplicationConfiguration, there's a flag in there that let s use toggle gpu/software vsynching. Play around with it." (Mario)
NOTE that none of these limit the framerate to a specific value... if you REALLY need to limit the framerate for some reason, you'll have to handle it yourself by returning from render calls if xxx ms haven't passed since the last render call.
As a complete game engine that LibGDX is, it handles things like this itself. You can configure this at the start of your game, at least with the latest nightlies.
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "Example";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
cfg.vSyncEnabled = true;
cfg.foregroundFPS = 60;
new LwjglApplication(new ExampleGame(), cfg);
}
Now your render loop will be limited to 60 calls per second. As to the actual implementation, you should use a Game and Screens. The Screen interface already has a render method which might look like this:
public void render(deltaTime )
{
...
updateAllEntities(deltaTime);
...
renderAllEntities(deltaTime);
...
}
There is only the render method being called by LibGDX, but you can split up your game logic update and the rendering yourself like in the example above.
So, I have one problem, which I can't solve. My app used over 45% of cpu samsung SII. I think the main reason is postDelayed.
Here is part of my code:
Handler a=new Handler();
a.post(new Runnable(){
#Override
public void run() {
Calendar cal = Calendar.getInstance(Locale.US);
cal.setTime(curr);
Format formatter = new SimpleDateFormat("\r EE \n d");
int currentDOW = cal.get(Calendar.DAY_OF_WEEK);
cal.add(Calendar.DAY_OF_YEAR,(currentDOW*-1)+i+2);
den.setText(formatter.format(cal.getTime()));
}
a.postDelayed(this,400);
});
So, this is part of my code, it is work, but I think, it is the main reason of high CPU usage. Please help me! Thank you!
you could optimize the code a bit , but i suspect that you simply don't stop the updating when you don't need to , so more and more updates are being accumulated .
as an example , if you change the orientation , it will add more events of the previous activitiy (which was destroyed) and you end up with double the rate of updating .
I had this problem. My app was using around 60% CPU time until I added the following code to my run() method in my worker thread:
#Override
public void run()
{
while( _running )
{
// do usual stuff
// ...
// ** add the following to the end of your loop **
try
{
Thread.sleep( 5 );
}
catch( InterruptedException e )
{
_running = false;
/* at least we tried */
}
}
}
It now uses ~8% CPU with no noticeable difference.
Experiment with the value '5'. I've added an app setting to allow the user to balance better graphics (i.e. number lower than 5) with better battery usage (number higher than 5).
I'm making a game that displays some numbers on a canvas (score, time, etc).
The way that I currently do this is with the drawtext command on a canvas
// score is some int
draw(Canvas c) {
c.drawText(score+"", x, y, paintSyle);
}
I hear that object creation and garbage collection are expensive operations, and I think this is creating a new string every time it is called.
Right now my game with all bitmap drawing and everything jumps around from 25 to 60 fps. I'd like it to stay closer to the higher number and I'm trying to find ways to speed it up.
Would it be faster/better to make(or find?) some mutable subclass of string and work around this problem? Is there another way to solve this issue? Or is this just how it is?
Introduce two new private member variables String renderedScoreString and int rederedScore and rewrite your draw()-method like that:
draw(Canvas c) {
if (this.score != this.renderedScore || this.renderedScoreString == null) {
this.renderedScore = this.score;
this.renderedScoreString = Integer.toString(this.renderedScore);
}
c.drawText(this.renderedScore, x, y, paintStyle);
}
that should save you a lot! of object creations. You could also hide the boilerplate code behind a getter method, e.g. String getScoreString() which does the same, so you don't have it in the draw()-method.
A friend of mine tipped me in on a solution to this problem. When you want to draw something over time, one of the best (and simplest) mechanisms to do so is to split up what you need to do into two completely separate processes.
ie. Only use the draw command exclusively for drawing stuff, keep logic/assignment in Draw() to an absolute minimum.
private final long TIMER_PERIOD = 500;
private String timeString;
private Runnable updateRunnable;
private Handler updateHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
updateRunnable = new Runnable() {
#Override
public void run() {
timeString = GetTimeString();
updateHandler.postDelayed(updateRunnable, TIMER_PERIOD);
}
}
}
Draw(Canvas c) {
c.drawText(timeString, x, y, paintStyle);
}
In this example the Draw command simply takes timeString in its current state and draws it to the screen. This is highly efficient use of the draw function as it does not require any object creation, and no logic is present that is not immediately required for any drawing to occur. . In the background a Runnable is executing the run() function every 500 miliseconds (approximately). Simply update the Run() function with whatever logic you need to calculate the time (example has a dummy function GetTimeString())
I hope this is helpful.
I know I'm resurrecting a dead thread, but there is one extra optimisation you can add to this which restricts String creation to a one-time thing and thus only triggers the GC once at the start and not during the game (which is quite important for an android game).
Somewhere during the start of your game (onCreate, onResume, as part of a singleton during application startup, etc) create a large String[] which can hold the maximum score (my game fills an array of 10000, so the max score would be 9999). Then loop over it with a for loop, filling each index with a String.valueOf(i).
for (int i = 0; i <scoreStrings.length; i++)
{
scoreStrings[i] = String.valueOf(i);
}
Now, when you need to draw the score, just use the int you use to store the score in as an index to that array, and "hey, presto!", you get the correct string for your score.
canvas.drawText(scoreStrings[score], x, y, paint);
I've been asking a series of evolving questions regarding my Android project that continually plots Bluetooth data in real-time. And I haven't done a very good job of asking questions.
So what I need to do is edit this question, clean it up, add important detail, and most importantly I need to add code fragments of relevant sections of code, especially sections I've hacked on quite a bit, and provide explanation about these sections of code. That way maybe I might get an answer to my question/concerns which are: Is my current solution an OK one? Is it going to hold up as I add new features?
Basically what I've already done is create a first version of my app by cobbling together some open source code Blueterm and OrientationSensor.
It's been suggested that I add a thread, a handler, a Service, or use Async Task, or AIDL, etc. But I have decided I don't want to modify or replace my existing solution unless I really should. Mainly I want to know if it's good enough to move forward and extend it to add other features.
By the way what I have previously referred to as BluetoothData is just bluetooth data: it's 16 bit data received from a remote Bluetooth device at the rate of 2 to 10 samples/second. My app is basically a data acquisition system that acquires/receives bluetooth data and plots it.
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.
Here's how I did this. In onOptionsItemSelected() I added a case to launch the Plot activity as follows:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.connect:
if (getConnectionState() == BluetoothSerialService.STATE_NONE) {
// Launch the DeviceListActivity to see devices and do scan
Intent serverIntent = new Intent(this, DeviceListActivity.class);
startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
else
if (getConnectionState() == BluetoothSerialService.STATE_CONNECTED) {
mSerialService.stop();
mSerialService.start();
}
return true;
case R.id.preferences:
doPreferences();
return true;
case R.id.menu_special_keys:
doDocumentKeys();
return true;
case R.id.plot_data:
doPlotData();
return true;
}
return false;
}
private void doPlotData() {
Intent plot_data = new Intent(this, com.vtrandal.bluesentry.Plot.class);
startActivity(plot_data);
}
Then in the bluetooth background thread I added a call to update() to call plotData() 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
//OrientationSensor orientationSensor = new OrientationSensor();
Plot.plotData(mReceiveBuffer, 0, bytesRead);
} catch (InterruptedException e) {
//VTR OMG their swallowing this exception
}
}
Then in the Plot activity I basically cleaned house, removed "implements SensorEventListener" and some related methods and variables, and wrote plotData() to be called as shown above. Here's what plotData() and it's helper methods splitData() and nowPlotData() currently look like:
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();
}
Time for a summary: I basically found the update() method in the background thread that was created by the Blueterm activity. The update() method essentially appends newly received bluetooth data to the screen buffer using the append() method. So, the background thread's update() method looked like a good place to call plotPlot(). So I designed plotData() to plot the data being passed to append(). This works as long plotData() is a static method. I would appreciate an explanation as to why plotData() seemingly must be static in order to work.
And again my overall question/concerns: Is my current solution an OK one? Is it going to hold up as I add new features?
I found the method in the background thread that writes BluetoothData to the Logcat. So I am leveraging this method to call a static method, plotData(BluetoothData), in the Plotting Activity. It works nicely plotting the incoming BluetoothData in real-time.
This story does not add up, or BluetoothData is misnamed.
In Android, to plot to the screen, you need an Activity instance, with whatever widget(s) you are plotting on. A plotData() method that does the plotting can be static, but somehow it needs the Activity instance. So, one of the following must be true:
BluetoothData contains an Activity instance (and hence is misnamed), or
plotData() takes more than the one parameter you have indicated, or
you are holding onto an Activity instance in a static data member (BAD BAD BAD BAD BAD), or
plotData() is not a static method, so you are actually calling it on an Activity instance
But, since you repeatedly decline to provide the source code, despite having asked several questions about the code, it is impossible for us to say which of these is really your problem.
Is it not thread safe? Do I have a deadlock issue? Is my solution a fragile one? Am I circumventing the Android OS? Am I lucky that it's working at all? Or is there a proper way to extend the existing design?
The first five of these have different answers depending upon which of the four bullets above reflects reality, and I really do not feel like writing out a 20-cell grid of answers. Your last question assumes that you have actually explained your "design", which you have not.
UPDATE
Some comments based upon the substantial revision to the question:
I would appreciate an explanation as to why plotData() seemingly must be static in order to work.
It probably doesn't have to be static.
Is my current solution an OK one?
Probably not.
Static methods are rarely a problem on their own. Static data is frequently a problem, due to lack of thread safety, memory leaks, and the like. Hence, your objective is to minimize or eliminate all static data members.
There are at least four static data members at play here, perhaps more. One is strData. This isn't too bad, in that you reset the static data member to a fresh StringBuffer on each plotData() call, so your memory leak is modest. However, if plotData() somehow were to be called on multiple threads simultaneously -- and, since I don't know your threading model, that's at least possible -- you will have problems, since you have no synchronization.
However, the far bigger problem is represented by the plotHistory, plotHistorySeries, and plotHistoryPlot static data members are. I have no idea what these objects are. However, by their name and your overall objective, it would appear that redraw() actually draws to the screen, which means that plotHistoryPlot is or holds some subclass of View that is the thing being plotted upon. This means you violated a cardinal rule of Android development:
Never put something that references a transient Context in a static data member
Here, an Activity represents a transient Context, "transient" because activities do go away, Context because it inherits from Context. Your statically-referenced View holds a reference back to its Activity. Hence, this Activity can never be garbage collected, which is bad for business, let alone any possible thread-safety issues.
Again, this is an educated guess, since I don't know what those static data members really are.