Apo*_*llo 19 objective-c ios core-motion apple-m7
我正在尝试检测三种动作:当用户开始步行,慢跑或跑步时.然后我想知道何时停止.我成功地检测到有人在走路,慢跑或跑步时使用以下代码:
- (void)update:(CMAccelerometerData *)accelData {
[(id) self setAcceleration:accelData.acceleration];
NSTimeInterval secondsSinceLastUpdate = -([self.lastUpdateTime timeIntervalSinceNow]);
if (labs(_acceleration.x) >= 0.10000) {
NSLog(@"walking: %f",_acceleration.x);
}
else if (labs(_acceleration.x) > 2.0) {
NSLog(@"jogging: %f",_acceleration.x);
}
else if (labs(_acceleration.x) > 4.0) {
NSLog(@"sprinting: %f",_acceleration.x);
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是双重的:
1)每次有动作时都会多次调用更新,这可能是因为它经常检查当用户开始行走时(即_acceleration.x> = .1000)它再次调用更新时仍然> = .1000.
示例日志:
2014-02-22 12:14:20.728 myApp[5039:60b] walking: 1.029846
2014-02-22 12:14:20.748 myApp[5039:60b] walking: 1.071777
2014-02-22 12:14:20.768 myApp[5039:60b] walking: 1.067749
Run Code Online (Sandbox Code Playgroud)
2)我很难弄清楚如何检测用户何时停止.有没有人就如何实施"停止检测"提出建议
vok*_*lam 23
根据你的日志,accelerometerUpdateInterval
是关于0.02
.如果更改上面提到的属性,更新可能会更少CMMotionManager
.
仅检查x加速度不是很准确.我可以用这样的方式将一个设备放在桌子上(比如说在左边缘),x加速度将等于1,或倾斜一点.这将导致程序处于步行模式(x> 0.1)而不是空闲.
这是一个链接到基于智能手机的基于活动跟踪的ADVANCED PEDOMETER出版物.它们跟踪加速度矢量方向的变化.这是两个连续加速度矢量读数之间角度的余弦值.
显然,没有任何运动,两个矢量之间的角度接近于零cos(0) = 1
.在其他活动中,d <1.为了滤除噪声,他们使用d的最后10个值的加权移动平均值.
实现之后,您的值将如下所示(红色 - 行走,蓝色 - 运行):
现在,您可以为每个活动设置阈值以将它们分开.请注意,平均步进频率为2-4Hz.您应该期望当前值在一秒钟内超过阈值至少几次以识别操作.
其他有用的出版物
UPDATE
_acceleration.x
,_accelaration.y
,_acceleration.z
是相同的加速度矢量的坐标.您可以在d公式中使用这些坐标中的每一个.为了计算d,您还需要存储先前更新的加速度矢量(在公式中使用i-1索引).
WMA只考虑具有不同权重的10个最后d值.最近的d值具有更大的权重,因此对结果值的影响更大.您需要存储9个先前的d值才能计算当前的值.您应该将WMA值与相应的阈值进行比较.
Kha*_*azi 16
如果你使用的是iOS7和iPhone5S,我建议你研究一下因为M7芯片而在iPhone5S中可用的CMMotionActivityManager.它还可以在其他几种设备中使用:
这是我在学习的时候整理的代码片段.
#import <CoreMotion/CoreMotion.h>
@property (nonatomic,strong) CMMotionActivityManager *motionActivityManager;
-(void) inSomeMethod
{
self.motionActivityManager=[[CMMotionActivityManager alloc]init];
//register for Coremotion notifications
[self.motionActivityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMMotionActivity *activity)
{
NSLog(@"Got a core motion update");
NSLog(@"Current activity date is %f",activity.timestamp);
NSLog(@"Current activity confidence from a scale of 0 to 2 - 2 being best- is: %ld",activity.confidence);
NSLog(@"Current activity type is unknown: %i",activity.unknown);
NSLog(@"Current activity type is stationary: %i",activity.stationary);
NSLog(@"Current activity type is walking: %i",activity.walking);
NSLog(@"Current activity type is running: %i",activity.running);
NSLog(@"Current activity type is automotive: %i",activity.automotive);
}];
}
Run Code Online (Sandbox Code Playgroud)
我测试了它,它似乎非常准确.唯一的缺点是,一旦你开始行动(例如走路)它就不会给你确认.一些黑盒算法等待确保您真正走路或跑步.但是你知道你已经确认了行动.
这加速了加速度计.Apple负责这个细节!
您可以使用此简单库来检测用户是在步行,跑步,在车上还是不在移动.适用于所有iOS设备,无需M7芯片.
https://github.com/SocialObjects-Software/SOMotionDetector
在回购中,您可以找到演示项目
我正在我的室内导航项目中关注这篇论文(PDF通过RG),仅通过加速度计数据来确定用户动态(静态,慢行,快走),以帮助确定位置.
这是项目中提出的算法:
这是我在Swift 2.0中的实现:
import CoreMotion
let motionManager = CMMotionManager()
motionManager.accelerometerUpdateInterval = 0.1
motionManager.startAccelerometerUpdatesToQueue(NSOperationQueue.mainQueue()) { (accelerometerData: CMAccelerometerData?, error: NSError?) -> Void in
if((error) != nil) {
print(error)
} else {
self.estimatePedestrianStatus((accelerometerData?.acceleration)!)
}
}
Run Code Online (Sandbox Code Playgroud)
在启动CoreMotion的所有经典Swifty iOS代码之后,这里是处理数字和确定状态的方法:
func estimatePedestrianStatus(acceleration: CMAcceleration) {
// Obtain the Euclidian Norm of the accelerometer data
accelerometerDataInEuclidianNorm = sqrt((acceleration.x.roundTo(roundingPrecision) * acceleration.x.roundTo(roundingPrecision)) + (acceleration.y.roundTo(roundingPrecision) * acceleration.y.roundTo(roundingPrecision)) + (acceleration.z.roundTo(roundingPrecision) * acceleration.z.roundTo(roundingPrecision)))
// Significant figure setting
accelerometerDataInEuclidianNorm = accelerometerDataInEuclidianNorm.roundTo(roundingPrecision)
// record 10 values
// meaning values in a second
// accUpdateInterval(0.1s) * 10 = 1s
while accelerometerDataCount < 1 {
accelerometerDataCount += 0.1
accelerometerDataInASecond.append(accelerometerDataInEuclidianNorm)
totalAcceleration += accelerometerDataInEuclidianNorm
break // required since we want to obtain data every acc cycle
}
// when acc values recorded
// interpret them
if accelerometerDataCount >= 1 {
accelerometerDataCount = 0 // reset for the next round
// Calculating the variance of the Euclidian Norm of the accelerometer data
let accelerationMean = (totalAcceleration / 10).roundTo(roundingPrecision)
var total: Double = 0.0
for data in accelerometerDataInASecond {
total += ((data-accelerationMean) * (data-accelerationMean)).roundTo(roundingPrecision)
}
total = total.roundTo(roundingPrecision)
let result = (total / 10).roundTo(roundingPrecision)
print("Result: \(result)")
if (result < staticThreshold) {
pedestrianStatus = "Static"
} else if ((staticThreshold < result) && (result <= slowWalkingThreshold)) {
pedestrianStatus = "Slow Walking"
} else if (slowWalkingThreshold < result) {
pedestrianStatus = "Fast Walking"
}
print("Pedestrian Status: \(pedestrianStatus)\n---\n\n")
// reset for the next round
accelerometerDataInASecond = []
totalAcceleration = 0.0
}
}
Run Code Online (Sandbox Code Playgroud)
我还使用了以下扩展来简化有意义的图形设置:
extension Double {
func roundTo(precision: Int) -> Double {
let divisor = pow(10.0, Double(precision))
return round(self * divisor) / divisor
}
}
Run Code Online (Sandbox Code Playgroud)
使用CoreMotion的原始值,算法是乱七八糟的.
希望这有助于某人.
编辑(4/3/16)
我忘了提供我的roundingPrecision
价值.我把它定义为3.只是简单的数学,这个非常重要的价值就足够了.如果您愿意,可以提供更多.
还有一点要提的是,目前,这种算法要求iPhone在行走时随身携带.见下图.对不起,这是我能找到的唯一一个.
归档时间: |
|
查看次数: |
19506 次 |
最近记录: |