Convert acceleration with gravity to pure acceleration? - javascript

By using event.accelerationIncludingGravity on Android, it returns a value of
x: -0.2
y: +0.1
z: +9.1
when resting on a flat surface. However, I want to get acceleration without gravity but event.acceleration is not supported. Is there a way to convert it by Math? In HTML5Rocks there is an example removing the gravity factor, but it doesn't seem to work.
// Convert the value from acceleration to degrees acceleration. x|y is the
// acceleration according to gravity, we'll assume we're on Earth and divide
// by 9.81 (earth gravity) to get a percentage value, and then multiply that
// by 90 to convert to degrees.
var tiltLR = Math.round(((acceleration.x) / 9.81) * -90);
var tiltFB = Math.round(((acceleration.y + 9.81) / 9.81) * 90 * facingUp);
Example script graphing acceleration values (not from HTML5Rocks)

I see. You got numbers for the x and y axis that are essentially 0, keep taking the measurement of the device resting on a flat surface and average all of your x and y values respectively and you will get your degree of error in each direction. The acceleration is measured in m/s^2. (meters per second squared). The gravitational acceleration at the earth's surface is 9.86m/s^2. In an ideal physics problem all you would have to do is subtract this number and you would get your answer. If you were trying to calculate speed then this would be a more complex problem, but the earth's gravitational acceleration does not accelerate. You do have a larger degree of error in the z-axis, but not if you calculate the degree of error as a percentage of the actual value. Or you are about 300km above sea level.

Related

React Native: How to compute x, y and z axis rotation angles based on gyroscope sensor outputs?

I was able to achieve a 2D rotation on X-Axis using x and y values but would like to compute Y-Axis and Z-Axis rotation angles.
Below is the formula that I have used for computing xAngle rotaion.
var xAngle = Math.atan2(x, y)/(Math.PI/180)
where x and y are the gravitational values on x and y-axis provided by the gyroscope sensor respectively.
Can someone help me by sharing a similar set of formulae for yAngle and zAngle computations?
Thanks in Advance!
Homework
Having just done the maths on this myself, there are some caveats you might want to be aware of.
Lets start by taking a quick look at the axis and using the correct names. Pitch, roll, and yaw describe the rotation around each of the axis. See https://sidvind.com/wiki/Yaw,_pitch,_roll_camera for more information.
Also, everything is relative. The sensors might be relative to one way of thinking, whilst the desired way of thinking might be relative to another.
My solution
In my case, the relative aspect is the tablet in landscape (landscape-left: rotated 90° counter-clockwise) then laid flat on its back (upright has a pitch of 90°).
The accelerometer readings (that I use) are relative to portrait upright.
Relative to gravity, the rotation around the y-axis can't be calculated from accelerometer information. This means:
Pitch can't be calculated when portrait and upright
Roll can't be calculated when flat on a desk
Yaw can't be calculated when landscape and upright
pitch = Math.atan2(-x, -z) * 180 / Math.PI;// In degrees
roll = Math.atan2(-y, -x) * 180 / Math.PI;// In degrees
yaw = Math.atan2(y, -z) * 180 / Math.PI;// In degrees
Assuming the sensors and the desired way of thinking match
Pitch can't be calculated when landscape and upright
Roll can't be calculated when flat on a desk
Yaw can't be calculated when portrait and upright
pitch = Math.atan2(z, -y) * 180 / Math.PI;// In degrees
roll = Math.atan2(x, -y) * 180 / Math.PI;// In degrees
yaw = Math.atan2(-x, -z) * 180 / Math.PI;// In degrees
Your solution
Your x-axis rotation matches the pitch on neither of these (nor gets close, negating the symbols), which suggests you're not calculating the rotation around the x-axis, but rotation of the x-axis around another, most likely the z-axis rotation (roll).

Calculate evenly distributed points along a curve

I'm using this equation to calculate a series of points along a quadratic curve:
// Returns a point on a quadratic bezier curve with Robert Penner's optimization of the standard equation
result.x = sx + t * (2 * (1 - t) * (cx - sx) + t * (ex - sx));
result.y = sy + t * (2 * (1 - t) * (cy - sy) + t * (ey - sy));
Sadly the points are unevenly distributed, as you can see in the dashed-line rendering below. The points are denser in the middle of the curve, and are further spaced apart near the edges. How can I calculate a evenly distributed set of points along a quadratic bezier curve?
Please note that I'm using this for rendering a dashed line, so a slow solution in MATLAB or something will not do. I need a fast solution that will fit inside a renderer. This is not for research or a one-off calculation!
Edit: I'm not asking how to accomplish the above. The above is MY RENDERING! I already know how to estimate the length of a bezier, calculate the number of points, etc, etc. What I need is a better bezier point interpolation algorithm since the one I have calculates points unevenly distributed along the curve!
You want to generate equidistant (by arc length) subdivision of quadratic Bezier curves.
So you need subdivision procedure and function for calculation of curve length.
Find length of the whole curve (L), estimate desired number of segments (N), then generate subdivision points, adjusting t parameters to get Bezier segments with length about L/N
Example: you find L=100 and want N=4 segments. Get t=1/2, subdivide curve by two parts and get length of the first part. If length > 50, diminish t and subdivide curve again. Repeat (use binary search) until length value becomes near 50. Remember t value and do the same procedure to get segments with length=25 for the first and for the second halves of the curve.
This approach uses the THREE.js library, which is not in the OP's question, but may be useful if only to look at how they approach it:
var curve = new THREE.QuadraticBezierCurve(
new THREE.Vector2( -10, 0 ),
new THREE.Vector2( 20, 15 ),
new THREE.Vector2( 10, 0 )
);
var points = curve.getSpacedPoints(numPoints);

Formula to Mimic 3D Distance in 2D Space?

I'm working on a simple 2D game, and am trying to mimic a 3D perspective (similar to many early games like Monkey Island). I've searched SO for awhile now and everything seems to be dealing with 3D. Does anyone happen to know the formula I would use to scale a DIV down as it moves up (away) from the camera?
Thanks!
In Monkey Island the backgrounds are 2D images with varying degrees of perspective. How a character is scaled depends on the perspective of the background. In some scenes the character only moves across the screen and so no change of scale is needed for the character. In some the character may move down a street and there is a high level of perspective. In some the character may move within a room and there is a small level of perspective.
Calculations regarding the scaling of the character needs to be calculated for each background scene. Perspective lines need to be drawn on the background and lengths measured.
The two examples below show how the scale for the character could be calculated.
In each case the scaling is based on the character as it is currently positioned on the screen. The variable y is a measure of how far the character is from its SMALLEST size position in the vertical direction. The variable h is a measure of the change in height of the character depending of y.
In the room scene the scale is > 1 since the character is currently at the back of the scene.
In the street scene the scale is < 1 since the character is currently at the from of the scene.
Triangular diagrams NOT to scale
I'm not sure what a DIV (I have no JavaScript experience) is but these links may help.
Perspective Projection
Walks you through the math used in perspective projections and includes some sample code (not JavaScript however).
3D Perspective Projection
Another page on perspective projection, with example code in C++.
I would do it like this:
// equation for objects appearing the same size
h=d*tan(α)
// now the scaling the size for arbitrary object
scale d h
1.0 d0 h0 // object with no scaling
0.5 2.0*d0 h0 // half size
0.25 4.0*d0 h0 // quoter size
0.5 d0 0.5 *h0
0.25 d0 0.25*h0
// so scale is:
scale = (d0/d)*(h/h0) // or
scale = (d0*h)/(d*h0)
set d0,h0 constants according to your view
d0 controls the magnification and h0=d0*tan(α)
If your camera has different view angle between axises then you have to apply two scaling factors
one for x axis and one for y axis
computed in the same way, but different angle used
d0 would be the same for both
Usual camera view angles in 3D are 60 or 90 degrees but in this case I would use 30 degrees
if you also view the underground then 60 with camera axis on the ground
In a true perspective projection, the scaling factor is given by S(D) = Df / D, where Df is the depth from the viewer to the full-size object and D the current depth.
For example, if a character is 40 pixels high and 16 large when seen in the foreground (assume 3m from the viewer), it will be 20 by 8 pixels at a depth of 6m and 10 by 4 at 12m.
Closer than the reference distance will result in magnification (80 by 32 at 1.5m).
[If your objects are located with (X, Y, Z) coordinates, X horizontal, Y vertical, Z perpendicular to the screen, pointing to the back, and is 0 at the depth of the screen, you have D = Z + Df and S(D) = Df / (Df + Z).]
Since you are talking about transforming a DIV then you should see CSS transforms. There are 2D transforms and 3D transforms. Keep in mind about the perspective attribute too ;)
Here you can find some examples:
http://desandro.github.io/3dtransforms/docs/perspective.html
http://24ways.org/2010/intro-to-css-3d-transforms/
http://dev.opera.com/articles/understanding-3d-transforms/
http://css-tricks.com/almanac/properties/t/transform/
http://css-tricks.com/almanac/properties/p/perspective/
http://css-tricks.com/almanac/properties/p/perspective-origin/

How to divide an ellipse to equal segments?

This calculates vertex coordinates on ellipse:
function calculateEllipse(a, b, angle)
{
var alpha = angle * (Math.PI / 180) ;
var sinalpha = Math.sin(alpha);
var cosalpha = Math.cos(alpha);
var X = a * cosalpha - b * sinalpha;
var Y = a * cosalpha + b * sinalpha;
}
But how can I calculate the "angle" to get equal or roughly equal circumference segments?
So from what Jozi's said in the OP's comments, what's needed isn't how to subdivide an ellipse into equal segments (which would require a whole bunch of horrible integrals), it's to construct an ellipse from line segments of roughly equal length.
There are a whole pile of ways to do that, but I think the best suited for the OP's purposes would be the concentric circle method, listed on the page as 'the draftman's method'. If you don't mind installing the Mathematica player, there's a neat lil' app here which illustrates it interactively.
The problem with those methods is that the segment lengths are only roughly equal at low eccentricities. If you're dealing in extreme eccentricities, things get a lot more complicated. The simplest solution I can think of is to linearly approximate the length of a line segment within each quadrant, and then solve for the positions of the endpoints in that quadrant exactly.
In detail: this is an ellipse quadrant with parameters a = 5, b = 1:
And this is a plot of the length of the arc subtended by an infinitesimal change in the angle, at each angle:
The x axis is the angle, in radians, and the y axis is the length of the arc that would be subtended by a change in angle of 1 radian. The formula, which can be derived using the equations in the Wikipedia article I just linked, is y = Sqrt(a^2 Sin^2(x) + b^2 Cos^2(x)). The important thing to note though is that the integral of this function - the area under this curve - is the length of the arc in the whole quadrant.
Now, we can approximate it by a straight line:
which has gradient m = (a-b) / (Pi/2) and y intercept c = b. Using simple geometry, we can deduce that the area under the red curve is A = (a+b)*Pi/4.
Using this knowledge, and the knowledge that the area under the curve is the total length of the curve, the problem of constructing an approximation to the ellipse reduces to finding say a midpoint-rule quadrature (other quadratures would work too, but this is the simplest) of the red line such that each rectangle has equal area.
Converting that sentence to an equation, and representing the position of a rectangle in a quadrature by it's left hand boundary x and its width w, we get that:
(v*m)*w^2 + (m*x+c)*w - A/k == 0
where k is the number of pieces we want to use to approximate the quadrant, and v is a weighting function I'll come to shortly. This can be used to construct the quadrature by first setting x0 = 0 and solving for w0, which is then used to set x1 = w0 and solve for w1. Then set x2 = w1, etc etc until you've got all k left-hand boundary points. The k+1th boundary point is obviously Pi/2.
The weighting function v effectively represents where the rectangle crosses the red line. A constant v = 0.5 is equivalent to it crossing in the middle, and gets you this with 10 points:
but you can play around with it to see what better balances the points. Ideally it should stay in the range [0, 1] and the sum of the values you use should be k/2.
If you want an even better approximation without messing around with weighting functions, you could try least-squares fitting a line rather than just fitting it to the endpoints, or you could try fitting a cubic polynomial to the blue curve instead of a linear polynomial. It'll entail solving quartics but if you've a maths package on hand that shouldn't be a problem.
Too long for a comment, so I suppose this has to be an answer ...
Here's a mathematically simple approach to forming a first order approximation. Pick one quadrant. You can generate the data for the other quadrants by reflection in the X and Y axis. Calculate (x,y) for the angle = 0 degrees, 1 degree, ... 90 degrees. Now you want the little lengths joining consecutive points. If (x_n, y_n) are the coordinates at angle = n, then Pythagoras tells us the distance D between points (x_n, y_n) and (x_n+1, y_n+1) is D = sqrt((x_n+1 - x_n)^2 + (y_n+1 - y_n)^2). Use this formula to produce a table of cumulative distances around the ellipse for angles from 0 degrees to 90 degrees. This is the inverse of the function you seek. Of course, you don't have to pick a stepsize of 1 degree; you could use any angle which exactly divides 90 degrees.
If you want to find the angle which corresponds to a perimeter step size of x, find the largest angle n in your table producing a partial perimeter less than or equal to x. The partial perimeter of angle n+1 will be larger than x. Use linear interpolation to find the fractional angle which corresponds to x.
All we are doing is approximating the ellipse with straight line segments and using them instead of the original curve; its a first order approximation. You could do somewhat better by using Simpson's rule or similar instead of linear interpolation.
Yes, you have to calculate the table in advance. But once you have the table, the calculations are easy. If you don't need too much accuracy, this is pretty simple both mathematically and coding-wise.

How to calculate depth coordinate of the 3D rectangle?

I have 3D rectangle, as shown in the image.
Here I know depth distance and x and y coordinates of the one end. Based on these two values I would like calculate coordinates at the other end.
For clear view, I have attached a screen.
If you don't know the relation between 2D and 3D (i.e. the projection formulas used) then you can't apply the depth.
That said, if you make the following assumptions:
the projection type is orthographic
a depth line is projected as a 45 degrees line
the length of a 45 degrees line is the same as if it was a normal line
... then you could calculate it with Pythagoras' theorem as follows:
The red lines are equal (in case of a 45 degree line), so:
x1 = 100 + 50 * (1 / sqrt(2))
y1 = 50 - 50 * (1 / sqrt(2))

Categories

Resources