【问题标题】:How to calculate correct velocity values from accerometer如何从加速度计计算正确的速度值
【发布时间】:2012-05-21 16:22:08
【问题描述】:

我需要计算 iphone 在太空中的速度,例如打孔速度。
我的第一个问题是:加速度值accelerometer:didAccelerate是否具有此过滤操作:

gravity_x = acceleration.x * kFilteringFactor + gravity_x * (1.0 - kFilteringFactor);
gravity_y = acceleration.y * kFilteringFactor + gravity_y * (1.0 - kFilteringFactor);
gravity_z = acceleration.z * kFilteringFactor + gravity_z * (1.0 - kFilteringFactor);
float gravityNorm = sqrt(gravity_x * gravity_x + gravity_y * gravity_y + gravity_z * gravity_z);
accelX = acceleration.x - gravity_x / gravityNorm;
accelY = acceleration.y - gravity_y / gravityNorm;
accelZ = acceleration.z - gravity_z / gravityNorm;

和使用CoreMotion的一样
motionManager.deviceMotion.userAcceleration.x; motionManager.deviceMotion.userAcceleration.y; motionManager.deviceMotion.userAcceleration.z; ?

接下来,根据相同的问题,我执行以下操作

    const float accuracy=10;
    float accx = (float) ((int)  (accelX * accuracy))/ accuracy;
    float accy=  (float) ((int)  (accelY * accuracy))/ accuracy;
    float accz=  (float) ((int)  (accelZ * accuracy))/ accuracy;

对于舍入值,然后,我认为,我获得当前速度

float dx = accx*9.81+prevX*9.81;
float dy = accy*9.81+prevY*9.81;
float dz = accz*9.81+prevZ*9.81;

speed_after_x = dx/2*myAccelerometer.updateInterval+speed_before_x;
speed_after_y = dy/2*myAccelerometer.updateInterval+speed_before_y;
speed_after_z = dz/2*myAccelerometer.updateInterval+speed_before_z;

根据iphone accelerometer speed and distance
那么

    prevX=accx;
    prevY=accy;
    prevZ=accz;

    speed_before_x=speed_after_x;
    speed_before_y=speed_after_y;
    speed_before_z=speed_after_z;

最后将速度计算为向量的长度

    float speed = sqrt(speed_after_x*speed_after_x+speed_after_y*speed_after_y+speed_after_z*speed_after_z);
    if (max_speed<speed)  max_speed = speed;

但是标签中包含的速度值总是在增加。我的意思是如果我移动设备然后停止,速度值不会变为 0。加速度不会在 0 处自我补偿吗?

【问题讨论】:

  • 这不会自行取消:((int) (accelX * accuracy))/ accuracy;。就像 ((10 * 100) / 100 == 10。如果您的意图是对数字进行四舍五入,然后将其转换回浮点数,则有更好的方法。
  • 精度为 10,以避免在设备握持时快速改变加速度值。
  • 是的,但是将一个数相乘然后除以同一个数就等于什么都不做。 (A * B) / B = A。
  • 我不认为这就是为什么速度不会变成0的原因,无论如何,我必须使用acceleration.timestamps delta,不完全是updateInterval
  • 哦,我知道,这就是为什么它是评论而不是答案。

标签: iphone ios core-motion acceleration


【解决方案1】:

这是我设法散列的示例代码。我暂时把它放在这里:

//
//  ViewController.m
//  Acce
//
//  Created by Diziet on 14/05/2012.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "ViewController.h"

@interface ViewController () {
    UIAccelerationValue gravX;
    UIAccelerationValue gravY;
    UIAccelerationValue gravZ;
    UIAccelerationValue prevVelocity;
    UIAccelerationValue prevAcce;
}

@property (strong) UIAccelerometer *sharedAcc;

@end

@implementation ViewController

@synthesize sharedAcc = _sharedAcc;

#define kAccelerometerFrequency        50.0 //Hz
#define kFilteringFactor 0.1

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.sharedAcc = [UIAccelerometer sharedAccelerometer];
    self.sharedAcc.delegate = self;
    self.sharedAcc.updateInterval = 1 / kAccelerometerFrequency; 

    gravX = gravY = gravZ = prevVelocity = prevAcce = 0.f;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (UIAccelerationValue)tendToZero:(UIAccelerationValue)value {
    if (value < 0) {
        return ceil(value);
    } else {
        return floor(value);
    }
}

#define kAccelerometerFrequency        50.0 //Hz
#define kFilteringFactor 0.1
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
    gravX = (acceleration.x * kFilteringFactor) + (gravX * (1.0 - kFilteringFactor));
    gravY = (acceleration.y * kFilteringFactor) + (gravY * (1.0 - kFilteringFactor));
    gravZ = (acceleration.z * kFilteringFactor) + (gravZ * (1.0 - kFilteringFactor));

    UIAccelerationValue accelX = acceleration.x - ( (acceleration.x * kFilteringFactor) + (gravX * (1.0 - kFilteringFactor)) );

    UIAccelerationValue accelY = acceleration.y - ( (acceleration.y * kFilteringFactor) + (gravY * (1.0 - kFilteringFactor)) );
    UIAccelerationValue accelZ = acceleration.z - ( (acceleration.z * kFilteringFactor) + (gravZ * (1.0 - kFilteringFactor)) );
    accelX *= 9.81f;
    accelY *= 9.81f;
    accelZ *= 9.81f;
    accelX = [self tendToZero:accelX];
    accelY = [self tendToZero:accelY];
    accelZ = [self tendToZero:accelZ];

    UIAccelerationValue vector = sqrt(pow(accelX,2)+pow(accelY,2)+pow(accelZ, 2));
    UIAccelerationValue acce = vector - prevVelocity;
    UIAccelerationValue velocity = (((acce - prevAcce)/2) * (1/kAccelerometerFrequency)) + prevVelocity;

    NSLog(@"X %g Y %g Z %g, Vector %g, Velocity %g",accelX,accelY,accelZ,vector,velocity);

    prevAcce = acce;
    prevVelocity = velocity;
}

@end

它需要根据您的需要进行修改,特别是因为我只是在之后丢弃这些值。记录为“速度”的结果值“速度”在加速事件停止后趋向于极小的负值,例如*10^-17。所以,是的,这在我的书中几乎为零。你会想在那里做一些四舍五入,甚至可能扩大值。我认为我不能让它高于 0.2 或 0.3,但我又不想把手机扔到房间的另一边(还)。

【讨论】:

  • 我不这么认为,因为我在发现问题后添加了这个乘数,它用于将G-measures转换为每秒m
  • 这不是我想知道的 * 9.81,那是一个“也”/旁白。这是您将 accx 添加到 prevX 的事实。如果 prevX 不能为负,根据您的数学判断,我认为不可能,那么您将获得不断增加的加速度值。您需要对现有值进行一些乘积,这样如果特定轴上的当前力矩加速度为零,则您记录的加速度将为零。我会把这个放在答案中。
  • 为什么 prevX 不能为负数?prevX=accx; prevY=accy; prevZ=accz;accx 可以为负数。我根据velocity[i] = (acceleration[i] + acceleration[i-1])/2 * interval + velocity[i-1] 将 accx 添加到 prevX
  • 更新间隔为 0.01,我尝试了 0.05。此过滤器用于忽略围绕其自身轴的旋转。您需要了解哪些价值观?
  • 因为不能发表评论,所以在这里发帖:我认为加速度的单位是m/s^2。 > A G 是与地球引力场 (9.81 m s−2) 施加的引力相等的引力单位。 developer.apple.com/library/prerelease/ios/documentation/… 但它是用 CMMotionManager 的方法来获得加速...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多