How to fix the limit of x axis with GraphView - java

I want to develop an app which communicates with BLE sensors at 100 Hz and to plot real time data using GraphView. I want to plot data in an "ECG way of doing", by having always the same fixed x axis and the curve which plots during time and come back on the left of the graph if the plot has reached the right end of the graph. I managed to receive data and to plot it but I have two concerns:
Sometimes, it became a bit laggy for like half a second, and I do not know if it comes from my app, or my phone (which is an OnePlus 6, having so quite great performances).
I am not able to "fix" the x axis limits... To try to explain it, the width of the x axis is fixed, but the curve starts plotting on the right part of the graph and fills the graph in the left direction until the curve has touched the left border of the graph. However, this is not what I wanted to do.
Here is some code snippets to help you understand what I have done wrong.
LineGraphSeries<DataPoint> series;
private int time = 0;
private int maxDataPoints = 200;
In OnCreate function
mDataGraph = (GraphView) findViewById(R.id.graph_data);
mDataGraph.getGridLabelRenderer().setHorizontalLabelsVisible(false);
mDataGraph.getGridLabelRenderer().setVerticalLabelsVisible(false);
mDataGraph.getGridLabelRenderer().setHighlightZeroLines(true);
mDataGraph.getGridLabelRenderer().setGridStyle(GridLabelRenderer.GridStyle.NONE);
mDataGraph.getViewport().setDrawBorder(true);
mDataGraph.setKeepScreenOn(true);
series = new LineGraphSeries<DataPoint>();
mDataGraph.addSeries(series);
// customize a little bit viewport
Viewport viewport = mDataGraph.getViewport();
viewport.setXAxisBoundsManual(true);
viewport.setMinX(0);
viewport.setMaxX(maxDataPoints);
viewport.setScalable(true);
viewport.setScrollable(true);
My function to handle data texts and plots
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
int dataNumber = Integer.parseInt(data);
// Reset graph
if (time == maxDataPoints){
mDataGraph.removeAllSeries();
series = new LineGraphSeries<DataPoint>();
mDataGraph.addSeries(series);
time = 0;
}
series.appendData(new DataPoint(time, dataNumber), true, maxDataPoints);
time ++;
}
}
Note that my template is the Bluetooth Le Gatt one.
It is the first time I use this forum and I code in android studio (and even in java), so I hope that my explanations are clear and that someone can help me.
Thanks to take time to read this.
Regards,
Arthur.

I was able to fix it by setting scrollToEnd to false in the appendData function...
Was so easy.
Regards,
Arthur.

Related

How to get the distance that a body has moved during a box2D world step?

I'm trying to implement linear interpolation and a fixed time step for my game loop. I'm using the libGDX engine and box2D. I'm attempting to find the amount the simulation moves my character's body during a world step like this:
old_pos = guyBody.getPosition();
world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
new_pos = guyBody.getPosition();
printLog(new_pos.x-old_pos.x);
This returns 0 each time. The simulation works fine, and the body definitely moves each step.
Additional code:
#Override
public void render(float delta) {
accumulator+=delta;
while (accumulator>=STEP_TIME){
accumulator-=STEP_TIME;
stepWorld();
}
alpha = accumulator/STEP_TIME;
update(delta);
//RENDER
}
private void stepWorld() {
old_pos = guyBody.getPosition();
old_angle = guyBody.getAngle() * MathUtils.radiansToDegrees;
world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
new_angle = guyBody.getAngle() * MathUtils.radiansToDegrees;
new_pos = guyBody.getPosition();
}
I'm attempting to use alpha to check how far I am in between physics steps so I can interpolate a Sprite's position.
Thanks!
Body's getPosition method is returning Vector reference - that means that you not copying it by value but only assign "pointer" on position object to old_pos/new_pos. However you are assigning it once before step and then after step all in all both variables keeps the same object with state after step already.
What you need to do is to copy position vector by value - to do this you can use Vector's cpy() method.
Your code should looks like
old_pos = guyBody.getPosition().cpy();
world.step(STEP_TIME, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
new_pos = guyBody.getPosition().cpy();
printLog(new_pos.x-old_pos.x);
If you do not use y coordinate you should also consider keeping only x in float type variable to not copy whole object (however it should not really impact your performance).
While the accepted response does answer my question, I wanted to add some information I figured out while trying to get this to work that I wish I knew at the beginning of this.
If you're going to use a fixed timestep for your physics calculations (which you should), you should also interpolate(or extrapolate) a Sprite's position between physics steps. In my code, the screen is being rendered more often than the world is being stepped:
#Override
public void render(float delta) {
accumulator+=delta;
while (accumulator>=STEP_TIME){
accumulator-=STEP_TIME;
stepWorld();
}
alpha = accumulator/STEP_TIME;
update(delta);
//RENDER using alpha
}
To avoid a jittery rendering of moving objects, render Sprites or Textures at their positions, modified by alpha. Since alpha is the ratio of your accumulator to the step time, it will always be between 0 and 1.
You then need to find how much your body is moving during one step. This can be done with the accepted answer or using the body velocity:
newPos = oldPos + body.getLinearVelocity()*STEP_TIME*alpha
Then just render Sprite at the new position and you should see smooth movement with your fixed timestep at most frame rates.

MPAndroidChart Display Label Over Horizontal Line on Graph

Is it possible to display custom text centered between 2 points on the graph?
I've got MPAndroidChart setup to display a step function type graph (representing hours spent doing a specific task) with horizontal and vertical lines only. What I would like to be able to do is show a label over the horizontal sections indicating the size of the section (aka the time spent calculated by taking the difference between the x values). Is there a way to do this? I've been look into modifying the library but I can't seem to figure out where would be the correct place to do so.
My best guess would be some changes in BarLineChartBase onDraw() method or maybe in the LineChartRenderer drawLinear() method.
Here is what I am able to produce:
Here is an example of what I am trying to produce:
Figured it out! Just add a new method drawTime() to the LineChart class at the end of onDraw() right after drawDescription(). Since each horizontal line is described by 2 Entry points I simply loop through 2 entries at a time for my single data set and calculate the difference:
protected void drawTime(Canvas c)
{
Paint timePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
timePaint.setTextSize(Utils.convertDpToPixel(16));
timePaint.setColor(Color.BLUE);
timePaint.setTextAlign(Paint.Align.CENTER);
MPPointD position;
LineData data = this.getLineData();
ILineDataSet dataSet = data.getDataSetByIndex(0);
for (int i = 1; i < dataSet.getEntryCount(); i+=2)
{
Entry e1 = dataSet.getEntryForIndex(i-1);
Entry e2 = dataSet.getEntryForIndex(i);
float time = e2.getX() - e1.getX();
position = getPixelForValues(e1.getX() + time/2, e1.getY() - 0.05f, YAxis.AxisDependency.LEFT);
c.drawText(String.valueOf(time), (float)position.x, (float)position.y, timePaint);
}
}
The resulting graph looks like this

Sprites flicker in Andengine

I want to move some sprites from left to right with a constant slow speed. I have first tried RatioResolutionPolicy but I saw sprites were flickering a lot. Then I have changed resolutionpolicy to FixedResolutionPolicy, defined sprite textures as bitmap, scaled them and made sprites by these textures (for more detail: click here). This is better than first method but not completely good. I use setx() for moving sprites. When I change x positon for example by 2 pixels for each frame there is no problem. But for different devices that have different resolutions I must multiply 2 by a ratio. In this case sprites are flickering again, not much but it is annoying for me.
code for camera is below
#Override
public EngineOptions onCreateEngineOptions() {
WindowManager w = getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
Point size = new Point();
w.getDefaultDisplay().getSize(size);
V.CAMERA_WIDTH = size.x;
V.CAMERA_HEIGHT = size.y;
} else {
Display d = w.getDefaultDisplay();
V.CAMERA_WIDTH = d.getWidth();
V.CAMERA_HEIGHT = d.getHeight();
}
if (V.CAMERA_HEIGHT/V.CAMERA_WIDTH>480f/860f){
V.CAMERA_HEIGHT=V.CAMERA_WIDTH*480f/860f;
}
else {
V.CAMERA_WIDTH=V.CAMERA_HEIGHT*860f/480f;
}
V.ratio=V.CAMERA_HEIGHT/480f;
this.mCamera = new Camera(0, 0, V.CAMERA_WIDTH, V.CAMERA_HEIGHT);
final EngineOptions engineOptions = new EngineOptions(true,
ScreenOrientation.LANDSCAPE_FIXED, new FixedResolutionPolicy((int)V.CAMERA_WIDTH, (int)V.CAMERA_HEIGHT),
this.mCamera);
return engineOptions;
}
for moving sprites:
this.wallPosX -= this.speed;
this.setX(Math.round(this.wallPosX));
speed is a floating point varibale and it gets 4.4651165 for 1280x720 screen resolution. If I set it as an integer than there is no flickering, but this time sprite speed differs from device to device.
There are too many screen sizes and screen ratio's for android phones.
Use the Cropped Resolution Policy created by jgibbs. Follow Martin Varga's tutorial to get an understanding on how it works and how to implement it.
It works wonders.
Original from jgibbs
I recommend Martin's Tutorial
You shouldn't be worried about micro managing entities positional co-ordinates to suit every and any possible screen size.
I'm not sure this will fix the flickering though, that may be some other problem not related to your camera
I have noticed that this wasn't about Andengine, it was about opengl. Solution for this problem is this wonderful tool:
https://github.com/gemserk/imageprocessing

libgdx check model is clicked

I am using libgdx for easy 3D game, I need check model is clicked.
It is my code:
public int getObject (int screenX, int screenY) {
Ray ray = cam.getPickRay(screenX, screenY);
int result = -1;
float distance = -1;
for (int i = 0; i < rooms.size; ++i) {
final GameObject instance = rooms.get(i);
instance.transform.getTranslation(position);
position.add(instance.center);
final float len = ray.direction.dot(position.x-ray.origin.x, position.y-ray.origin.y, position.z-ray.origin.z);
if (len < 0f)
continue;
float dist2 = position.dst2(ray.origin.x+ray.direction.x*len, ray.origin.y+ray.direction.y*len, ray.origin.z+ray.direction.z*len);
if (distance >= 0f && dist2 > distance)
continue;
if (dist2 <= instance.radius * instance.radius ) {
result = i;
distance = dist2;
}
}
return result;
}
It it sometimes work.
Is is my model:
http://www6.zippyshare.com/v/97501566/file.html
What do I wrong?
Any help for me?
I am new with libgdx.
When was I press 1 it lights, but when I waas press 2, 1 lights too (instead 2)...
I didn't fully analyze your code nor do I know what It it sometimes work. actually means (e.g. in which circumstances doesn't it work?) but you're using a bounding sphere for detecting whether the object has been clicked or not.
Assuming your calculations are correct (as I said, I didn't check them in depth) you still can have false positives or negatives since the only shape which is perfectly represented by a bounding sphere is ... well... a sphere.
That might be the source for click detection to work "sometimes".
If that is the case and you want more accurate detection you should either use different bound volumes, bounding volumne hierarchies or a rendering based approach (i.e. render the object id into some buffer, which would allow for pixel perfect selection).
UPDATE:
From your post update it seems that bounding spheres are not the problem here, since they should not overlap, unless your data is wrong - which you should check/debug.
So the problem might actually lie in your calculations. From the documentation it looks like the ray you get is projected into the scene (i.e. into world space) so you'd need to transform your objects' center into worldspace as well.
You're currently only applying the position but ignore rotation and scale thus the resulting position might be wrong. I'm sure there's some built-in transform code, so instead of transforming manually you should use that. Please check the docs on how to do that.

Computer Vision - filtering convex hulls and convexity defects with OpenCV

I have the problem with processing digital signals. I am trying to detect fingertips, similar to the solution that is presented here: Hand and finger detection using JavaCV.
However, I am not using JavaCV but OpenCV for android which is slightly different.
I have managed to do all the steps presented in the tutorial, but filtering of convex hulls and convexity defects. This is how my image looks like:
Here is an image in another resolution:
As you can clearly see, There is to many yellow points (convex hulls) and also to many red points (convexity deffects). Sometimes between 2 yellow points there is no red point, which is quite strange (how are convex hulls calculated?)
What I need is to create simillar filtering function like in the link provided before, but using data structures of OpenCV.
Convex Hulls are type of MatOfInt ...
Convexity defects are type of MatOfInt4 ...
I created also some additional data structures, because stupid OpenCV uses different types of data containing same data, in different methods...
convexHullMatOfInt = new MatOfInt();
convexHullPointArrayList = new ArrayList<Point>();
convexHullMatOfPoint = new MatOfPoint();
convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();
Here is what I did so far but it is not working good. The problem is probably with converting data in a wrong way:
Creating convex hulls and convexity defects:
public void calculateConvexHulls()
{
convexHullMatOfInt = new MatOfInt();
convexHullPointArrayList = new ArrayList<Point>();
convexHullMatOfPoint = new MatOfPoint();
convexHullMatOfPointArrayList = new ArrayList<MatOfPoint>();
try {
//Calculate convex hulls
if(aproximatedContours.size() > 0)
{
Imgproc.convexHull( aproximatedContours.get(0), convexHullMatOfInt, false);
for(int j=0; j < convexHullMatOfInt.toList().size(); j++)
convexHullPointArrayList.add(aproximatedContours.get(0).toList().get(convexHullMatOfInt.toList().get(j)));
convexHullMatOfPoint.fromList(convexHullPointArrayList);
convexHullMatOfPointArrayList.add(convexHullMatOfPoint);
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e("Calculate convex hulls failed.", "Details below");
e.printStackTrace();
}
}
public void calculateConvexityDefects()
{
mConvexityDefectsMatOfInt4 = new MatOfInt4();
try {
Imgproc.convexityDefects(aproximatedContours.get(0), convexHullMatOfInt, mConvexityDefectsMatOfInt4);
if(!mConvexityDefectsMatOfInt4.empty())
{
mConvexityDefectsIntArrayList = new int[mConvexityDefectsMatOfInt4.toArray().length];
mConvexityDefectsIntArrayList = mConvexityDefectsMatOfInt4.toArray();
}
} catch (Exception e) {
Log.e("Calculate convex hulls failed.", "Details below");
e.printStackTrace();
}
}
Filtering:
public void filterCalculatedPoints()
{
ArrayList<Point> tipPts = new ArrayList<Point>();
ArrayList<Point> foldPts = new ArrayList<Point>();
ArrayList<Integer> depths = new ArrayList<Integer>();
fingerTips = new ArrayList<Point>();
for (int i = 0; i < mConvexityDefectsIntArrayList.length/4; i++)
{
tipPts.add(contours.get(0).toList().get(mConvexityDefectsIntArrayList[4*i]));
tipPts.add(contours.get(0).toList().get(mConvexityDefectsIntArrayList[4*i+1]));
foldPts.add(contours.get(0).toList().get(mConvexityDefectsIntArrayList[4*i+2]));
depths.add(mConvexityDefectsIntArrayList[4*i+3]);
}
int numPoints = foldPts.size();
for (int i=0; i < numPoints; i++) {
if ((depths.get(i).intValue()) < MIN_FINGER_DEPTH)
continue;
// look at fold points on either side of a tip
int pdx = (i == 0) ? (numPoints-1) : (i - 1);
int sdx = (i == numPoints-1) ? 0 : (i + 1);
int angle = angleBetween(tipPts.get(i), foldPts.get(pdx), foldPts.get(sdx));
if (angle >= MAX_FINGER_ANGLE) // angle between finger and folds too wide
continue;
// this point is probably a fingertip, so add to list
fingerTips.add(tipPts.get(i));
}
}
Results (white points - fingertips after filtering):
Could you help me to write proper function for filtering?
UPDATE 14.08.2013
I use standard openCV function for contour approximation. I have to change approximation value with resolution change, and hand-to-camera distance, which is quite hard to do. If the resolution is smaller, then finger consist of less pixel, thus approximation value should be lover. Same with the distance. Keeping it high will result in completely losing the finger. So I think approximation is not good approach to resolving the problem, however small value could be useful to speed up calculations:
Imgproc.approxPolyDP(frame, frame, 2 , true);
If I use high values, then the result is like on the image below, which would be good only if distance and resolution wouldn't change. Also, I am quite surprised that default methods for hulls points and defects points doesn't have useful arguments to pass (min angle, distance etc)...
Image below presents the effect that I would like to achieve always, independently from resolution or hand-to-camera distance. Also I don't want to see any yellow points when I close my palm...
To sum everything up, I would like to know:
how to filter the points
how can I make resolution and distance independent approximation which will always work
if someone knows or have some materials (graphical representation, explanation) about those data structures used in OpenCV, I would be happy to read it. (Mat, MatOfInt, MatOfPoint, MatOfPoint2, MatOfPoint4 etc.)
The convex hull at low res can be used to identify the position of the hand as a whole, it is not useful for fingers but does provide a region of interest and appropriate scale.
The higher resolution analysis should then be applied to your approximated contour, it is easy to skip any points that do not pass the "length and angle" criteria from the last two, though you may wish to "average in" instead of "skip entirely".
Your code example is a single pass of calculating convexity defects and then removing them .. that is a logic error .. you need to remove points as you go .. (a) it is faster and simpler to do everything in one-pass (b) it avoids removing points at a first pass and having to add them back later because any removal changes previous calcs.
This basic technique is very simple and so works for a basic open palm. It doesn't intrinsically understand a hand or a gesture though, so tuning the scale, angle and length parameters is only ever going to get you "so far".
References to Techniques:
filter length and angle "Convexity defect"
Simen Andresen blog http://simena86.github.io/blog/2013/08/12/hand-tracking-and-recognition-with-opencv/
Kinect SDK based C# Library with added finger direction detection
http://candescentnui.codeplex.com/
http://blog.candescent.ch/2011/11/improving-finger-detection.html
"Self-growing and organized neural gas" (SGONG)
Prof Nikos Papamarkos http://www.papamarkos.gr/uploaded-files/Hand%20gesture%20recognition%20using%20a%20neural%20network%20shape%20fitting%20technique.pdf
Commercial product
David Holz & Michael Buckwald founders of "Leap Motion" http://www.engadget.com/2013/03/11/leap-motion-michael-buckwald-interview/
I think you missed that point:
Hull creation and defect analysis are speeded up by utilizing a low-polygon approximation of the contour rather than the original.

Categories

Resources