基于三轴传感器的计步器代码实现-iOS

原有iOS计步器采用系统框架swift语言调用

    /// 传感器
    ///
    /// - Parameter callbcak: 步数steps+距离distance
    func caculateSensor(callbcak:@escaping(_ steps:Int,_ distance:Float) ->()) {
        if CMPedometer.isStepCountingAvailable() && CMPedometer.isDistanceAvailable() {
            self.sensor.startUpdates(from: Date(), withHandler: { (pedometerData:CMPedometerData?, error:Error?) in
                if pedometerData != nil {
                    if pedometerData?.numberOfSteps != nil && pedometerData?.distance != nil{
                        callbcak(pedometerData?.numberOfSteps as! Int,(pedometerData?.distance?.floatValue)!);
                    }
                }
            })
        }
    }

改为三轴传感器的计步器实现


图片.png

开启陀螺仪采集三轴数据

/**
 *  开启陀螺仪
 */
-(void)startUpdateAccelerometer{
    /* 设置采样的频率,单位是秒 */
    NSTimeInterval updateInterval = 1/30.0; // 每秒采样30次 ()

    /* 判断是否加速度传感器可用,如果可用则继续 */
    if ([self.motionManager isAccelerometerAvailable] == YES) {
        /* 给采样频率赋值,单位是秒 */
          [self.motionManager setAccelerometerUpdateInterval:updateInterval];
        
        /* 加速度传感器开始采样,每次采样结果在block中处理 */
        [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error)
         {
             CGFloat sqrtValue =sqrt(accelerometerData.acceleration.x*accelerometerData.acceleration.x+accelerometerData.acceleration.y*accelerometerData.acceleration.y+accelerometerData.acceleration.z*accelerometerData.acceleration.z);   //采集到的三轴加速度矢量长度
              [self detectorNewStep:sqrtValue];   //输入算法计算
         }];
    }
}

计步核心

/*
 * 检测步子,并开始计步
 * 1.传入sersor中的数据
 * 2.如果检测到了波峰,并且符合时间差以及阈值的条件,则判定为1步
 * 3.符合时间差条件,波峰波谷差值大于initialValue,则将该差值纳入阈值的计算中
 * */
-(void)detectorNewStep:(float) value{
 
    if (gravityOld == 0) {
        gravityOld = value;//第一次记录
    } else {
        //如果是波峰
        if ([self detectorPeak:value OldValue:gravityOld]) {
            
            timeOfNow = [self nowTimeInterverl];//当前时间
            
            //是否修改初始阀值(ThreadValue=2)两个波峰的时间差(一步时间)大于0.22s 
            if (timeOfNow - timeOfLastPeak >= 220
                && (peakOfWave - valleyOfStepMinWave >= initialValue)) {
                ThreadValue = [self peak_Valley_thread:(peakOfWave - valleyOfWave)];//调用阀值计算
            }
            
            //是否步点 波峰-波谷>=动态阀值ThreadValue
            if (timeOfNow - timeOfLastPeak >= 220 && (peakOfWave - valleyOfWave >= ThreadValue)) {

                timeOfLastPeak = timeOfNow;;//记录波峰时间

                /*
                 * 更新界面的处理,不涉及到算法
                 * 一般在通知更新界面之前,增加下面处理,为了处理无效运动:
                 * 1.连续记录10才开始计步
                 * 2.例如记录的9步用户停住超过3秒,则前面的记录失效,下次从头开始
                 * 3.连续记录了9步用户还在运动,之前的数据才有效
                 *  
                 */
                motion_step ++;//步数
                is_motion_step_add = true;//is_motion_step_add 是否步数增加(修改波谷最小值)
                self.stepCallback(motion_step);//刷新页面数据
            }
        }
    }
    gravityOld = value;
}

波峰检测

/*
 * 检测波峰
 * 以下四个条件判断为波峰:
 * 1.目前点为下降的趋势:isDirectionUp为false
 * 2.之前的点为上升的趋势:lastStatus为true
 * 3.到波峰为止,持续上升大于等于2次
 * 4.波峰值大于20
 * 记录波谷值
 * 1.观察波形图,可以发现在出现步子的地方,波谷的下一个就是波峰,有比较明显的特征以及差值
 * 2.所以要记录每次的波谷值,为了和下次的波峰做对比
 * */
-(BOOL) detectorPeak:(float)newValue OldValue:(float)oldValue{
    
    lastStatus = isDirectionUp;
    if (newValue >= oldValue) {// 正在上升
        isDirectionUp = YES;
        continueUpCount++;
    } else {// 下降
        continueUpFormerCount = continueUpCount;
        continueUpCount = 0;
        isDirectionUp = NO;
    }
    // 此时下降,上一个点状态是上升 且 (继续上升的个数 >= 2 或者oldValue > 20)
    if (!isDirectionUp && lastStatus
        && (continueUpFormerCount >= 2 || oldValue >= 20)) {// 波峰
        peakOfWave = oldValue;
        return YES;
    } else if (!lastStatus && isDirectionUp) {// 波谷
        if (valleyOfWave > oldValue || is_motion_step_add) {//选出波峰到来前的最低波谷值
            is_motion_step_add = false;
            valleyOfWave = oldValue;
        }
        return NO;
    } else {
        return NO;
    }
}

阀值的计算

/*
 * 阈值的计算
 * 1.通过波峰波谷的差值计算阈值
 * 2.记录4个值,存入tempValue[]数组中
 * 3.在将数组传入函数averageValue中计算阈值
 */
-(float)peak_Valley_thread:(float)value{
    float tempThread = ThreadValue;
    if (tempValue.count < 4) {
        tempValue[tempCount] = @(value);
        tempCount++;
    } else {
        tempThread = [self averageValue:tempValue Num:4];
        for (int i = 1; i < 4; i++) {
            tempValue[i-1] = tempValue[i];
        }
        tempValue[3] = @(value);
    }
    return tempThread;
}

/* 梯度化阈值
 * 1.计算数组的均值
 * 2.通过均值将阈值梯度化在一个范围里
 * */
-(float)averageValue:(NSMutableArray *)value Num:(int)n{
    
    float ave = 0;
    for (int i = 0; i < n; i++) {
        ave += [value[i] floatValue];
    }
    ave = ave / 4.0;
    if (ave >= 8)
        ave = (float) 4.3;
    else if (ave >= 7 && ave < 8)
        ave = (float) 3.3;
    else if (ave >= 4 && ave < 7)
        ave = (float) 2.28;
    else if (ave >= 3 && ave < 4)
        ave = (float) 1.98;
    else {
        ave = (float) initialValue;//initialValue = 1.1  最低波峰波谷差。
    }
    return ave;
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容