1
votes

I am building a tilt-based Arduino device that needs to detect the "fall-line" vector of the device once it is tilted in a particular orientation. By "fall-line" I'll use the following example:

Imagine a frictionless plane with a point mass in the the middle of it and a 3-axis accelerometer mounted in the plane so that the x and y axes of the accelerometer are parallel to the plane. At rest, the plane is flat and the point mass does not move. Once the plane is tilted, the point mass will move in a particular direction at a given acceleration due to gravity. I need to calculate the angle in the x-y plane that the mass will move toward and a magnitude measure corresponding to the acceleration in that direction.

I realise this is probably simple Newtonian mechanics, but I have no idea how to work this out.

1
I've come up with a solution for this now which is fit for purpose, simply using arctan and pythagoras -- it was much easier than I thought once I could visualise the 3-d-ness of things. But I'll leave the question here to see if anyone else has any good ideas.Brad
Maybe you want to post it as an answer and accept it?angelatlarge
Maybe you should ponder if you really need the angle in the first place. Usually it is much simpler to deal with vectors / normalized vectors and norms.Udo Klein

1 Answers

1
votes

The direction of the "fall-line" and the magnitude of the acceleration are both determined by the projection of the gravitational pull vector onto the plane. If the plane has a normal vector n, then the projector operator is P( n ) = 1 - nn, where 1 is the identity operator and nn is the outer (tensor) product of the normal vector with itself. The projection of the gravitational pull vector g is simply g' = P( n ).g = (1 - nn) g = g - (n . g) n, where the dot denotes inner (dot) product. Now you only have to choose a suitable orthonormal reference frame (ex, ey, ez), where ei is a unit vector along direction i. In this reference frame:

n = nx ex + ny ey + nz ez
g = gx ex + gy ey + gz ez

The dot product n . g is then:

n . g = nx * gx + ny * gy + nz * gz

A very suitable choice of a reference frame is one where ez is collinear with n. Then nx = 0 and ny = 0 and nz = ||n|| = 1, because normal vectors are of unit length. In this frame n . g is simply gz. The components of the projection of g are then:

g'x = gx
g'y = gy
g'z = 0

The direction of g' in the XY plane can be determined by the fact that for the dot product in orthonormal reference frames a . b = ||a|| ||b|| cos(a, b), where ||a|| denotes the norm (length) of a and cos(a, b) is the cosine of the angle between a and b. If you measure the angle from the X direction, then:

g' . ex = (gx ex + gy ey) . ex = gx = ||g'|| ||ex|| cos(g', ex) = g' cos(g', ex)

where g' = ||g'|| = sqrt(gx^2 + gy^2). The angle is simply arccos(gx/g'), i.e. arc-cosine of the ratio between the X component of the gravity pull vector and the magnitude of its projection onto the XY plane:

angle = arccos[gx / sqrt(gx^2 + gy^2)]

The magnitude of the acceleration is proportional to the magnitude of g', which is (once again):

g' = ||g'|| = sqrt(gx^2 + gy^2)

Now the nice thing is that all accelerometers measure the components of the gravity field in a reference frame that usually have ex aligned with the height (or the width) of the device, the ex aligned with the width (or the height) of the device and ez is perpendicular to the surface of the device, which matches exactly the reference frame, where ez is collinear with the plane normal. If this is not the case with your Arduino device, simply rotate the accelerometer and align it as needed.