Smooth movement with the accelerometer? - Like a labyrinth game.

Apprentice
Posts: 5
Joined: 2010.02
Post: #1
I want to be able to make image move realistically with the accelerometer controlling it, like any labyrinth. Below shows what I have so far but it seems very jittery and isnt realistic at all

Code:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {

deviceTilt.x = acceleration.x
deviceTilt.y = -acceleration.y

}

-(void)onTimer {

    ballImage.center = CGPointMake(ballImage.center.x + (deviceTilt.x * 50), ballImage.center.y + (deviceTilt.y  * 50));

    if (ballImage.center.x > 279) {
    
        ballImage.center = CGPointMake(279, ballImage.center.y);
    }
    if (ballImage.center.x < 42) {
    
        ballImage.center = CGPointMake(42, ballImage.center.y);
    }
    if (ballImage.center.y > 419) {
        
        ballImage.center = CGPointMake(ballImage.center.x, 419);
    }
    if (ballImage.center.y < 181) {
        
        ballImage.center = CGPointMake(ballImage.center.x, 181);
    }


any help? I have looked at high pass filters and low pass filters but it doesnt really do what I want :/

Thanks
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #2
You might need to refine the accelerometer values more. Perhaps try using a moving average to filter out spikes in acceleration. Also, you won't want to directly tie the accelerometer to the position of the ball, but rather use the accelerometer as a force input to your ball's physics.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2010.02
Post: #3
AnotherJake Wrote:You might need to refine the accelerometer values more. Perhaps try using a moving average to filter out spikes in acceleration. Also, you won't want to directly tie the accelerometer to the position of the ball, but rather use the accelerometer as a force input to your ball's physics.

do you mean something like this:

Code:
deviceTilt.x = 0.01 * deviceTilt.x + (1.0 - 0.01) * acceleration.x;
    deviceTilt.y = 0.01 * deviceTilt.y + (1.0 - 0.01) * acceleration.y;

device tilt is a CGPoint
.....
if so that is still really jittery, it moves a lot smoother but when the movements are very little its jittering around everywhere, is there any simple way of maybe letting the object stop when the device is level because it seems to be moving a very small amount around on both x and y
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #4
No, more like:

Code:
static int index = 0;
static int valuesX[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static int valuesY[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

valuesX[index] = accelerometerValueX;
valuesY[index] = accelerometerValueY;
index++;
if (index >= 10)
    index = 0;

int i;
float forceX = 0.0f;
for (i = 0; i < 10; i++)
    forceX += valuesX[i];
forceX = forceX / 10;

float forceY = 0.0f;
for (i = 0; i < 10; i++)
    forceY += valuesY[i];
forceY = forceY / 10;

ballX += forceX * deltaTime
ballY += forceY * deltaTime

Then you'll probably also want to add a little friction, but get the moving average working first.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2010.02
Post: #5
thanks alot Smile I did this into my app and it is alot smoother but it still doesnt like stop or anything or get much slower when the phone is level it is still quite jittery in small accurate movements of the phone. The object never stops and if i was making a labyrinth type game this physics wouldnt work because i just simply dont have enough control of the object.

I dont know if it is clear on this video but it shows that my application using the code below has smooth movements but its impossible to stay still, this is comparing it to labyrinth which is very sensitive to small movements of the phone and you can hold the ball still if the phone is level

[url="http://visialsoft.co.uk/uploads/acclDemo.MOV"]video is linked here http://visialsoft.co.uk/uploads/acclDemo.MOV
[/url]
Code:
    static int index = 0;
    static float valuesX[10] = {0,0,0,0,0,0,0,0,0,0};
    static float valuesY[10] = {0,0,0,0,0,0,0,0,0,0};

    valuesX[index] = acceleration.x;
    valuesY[index] = acceleration.y;
    index++;
    if (index >= 10) {
        index = 0;
    }

    int i;
    float forceX = 0.0f;
    for (i = 0; i < 10; i++) {
        forceX += valuesX[i];
    }
    forceX = forceX / 10;
    
    float forceY = 0.0f;
    for (i = 0; i < 10; i++) {
        forceY += valuesY[i];
    }
    forceY = forceY / 10;


    deviceTilt.x = forceX;
    deviceTilt.y = forceY;
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #6
Looks like you should try adding some friction.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2010.02
Post: #7
Blush cant figure out how to do that, do you have any formulas or examples i could start from?
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #8
Hmm... I wish I had a straight answer for you. The way I do physics is impulse-based (actually, that's not entirely true since I generally use third-party physics libs most of the time because collision detection turns out to be really hard to do well), so I subtract a little velocity off of every integration, something like:

velocity *= powf(friction, deltaTime);

Where friction of 1.0 would be no friction, and 0.9 would be slight friction, etc.

Glancing at your code again, it appears that you might still have the ball tied directly to the tilt of the device. Again, what you should do instead is have the ball be its own physics object and use the tilt of the device only as a force input to the ball's physics. You'll never get this to work for you if you do it any other way.

What I would recommend is one of two things:
1) Read up on basic 2D physics. This should be fairly approachable for a labyrinth-type simulation where you don't need to worry about rotated collision bodies. Unfortunately, I don't have any links handy.
2) Figure out how to use Chipmunk physics, which will handle all the physics and collision detection for you. You should be able to make a very realistic looking labyrinth simulation with that.

If it were me, I'd choose option #2.
Quote this message in a reply
Apprentice
Posts: 5
Joined: 2010.02
Post: #9
Smile thanks alot, i will look into that!
Quote this message in a reply
Member
Posts: 43
Joined: 2009.10
Post: #10
If you really want the labyrinth example, you can just implement straights physics on a particle on an incline.

You could say its overkill, but they're not going to be computationally demanding, so might as well go out and make it look right Smile

Basically then what you do is use the accelerometer values to determine the incline of the of the *board*. Then you use standard physics equations on your ball. This entails keeping tracking of the balls position and current velocity. Determine the force on the ball using the current incline of the board. Then do a single update for the amount of time that will elapse to the next update.

The force that you calculate on the ball will include the friction force. In physics you usually have a "static" friction force as well as one for in motion. So when the ball velocity is below some threshold and you can force it to 0, and then switch to the static friction force.

Some tutorial on determining force of an object on an incline:

http://www.sparknotes.com/testprep/books...ion3.rhtml

That will need to be generalized to the 3D components.

Once you have the force vector on the 3D components you just do standard update rules to your position and velocity (component wise):

p = p_0 + v*t + .5at^2
v = v_0 + a*t

then repeat on the next iteration.

You may also still want to smooth the accelerometer values for determining the board incline, though I think with this model it might not matter as much.



Oh and if its a ball you might consider using rolling resistance instead of normal friction (or some combination of both!):
http://en.wikipedia.org/wiki/Rolling_resistance
Quote this message in a reply
Member
Posts: 43
Joined: 2009.10
Post: #11
Rereading my post I think I should refine it. I don't think you need calculate the board angle, I think you can use the straight accelerometer to get the force acting on the ball from gravity. But you do still want to basically add to that force vector a friction vector based on its current movement direction to get the overall net force (again using static or kinetic friction when appropriate) and then make sure when you do your updates that you're compounding the velocity gathered and using normal physics equations to get new position and velocity info.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #12
That average thing is a bit heavy for smoothing, you can achieve a similar effect much more succinctly with a low-pass filter.

Code:
float filteringFactor = 0.1;
filteredValueX = [accel x] * filteringFactor + filteredValueX * (1.0 - filteringFactor);

where you keep filteredValueX as an ivar to use in the next accelerometer update.
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #13
(Jul 13, 2010 10:51 PM)garlantinapple Wrote:  is there any simple way of maybe letting the object stop when the device is level because it seems to be moving a very small amount around on both x and y

It should be fairly trivial to implement a small dead zone where values below a certain threshold are treated as 0.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Smooth acceleration in every direction. Honey Sharma 1 4,429 Aug 16, 2011 01:37 AM
Last Post: PoseMotion
  glutWarpPointer lag and fps movement Ropeburn 3 6,722 Jan 18, 2011 09:47 PM
Last Post: OneSadCookie
  6DOF using accelerometer and gyroscope cbroaddus 1 3,408 Oct 14, 2010 09:25 AM
Last Post: Skorche
  Requesting Help: Smooth keyframe interpolation algorithm whogben 4 4,719 Jan 5, 2009 11:15 PM
Last Post: whogben
  AI/Movement wonza 6 3,962 Nov 26, 2008 10:23 AM
Last Post: wonza