[原创] 虚拟架子鼓------落棒检测算法

littleshrimp   2017-4-18 11:08 楼主

上一篇贴子已经知道怎么通过osxMFX_output数据分析鼓棒的落点

https://bbs.eeworld.com.cn/thread-527695-1-1.html

 

下一步是落棒检测,通过鼓棒动作判断是否敲了下去,我让SensorTile输出osxMFX_outputrotation_9X[2](俯仰数据)到上位机

通过C#写了一个程序能够把数据用拆线的方式显示出来

截取一段数据如下图显示,图中的红点是我每次落棒时的样子

image001.png

分析发现落棒的数据有点像心电图或加速度计步的数据,找个心率检测的代码看了下没看懂,发贴求助后得到一些帮助

https://bbs.eeworld.com.cn/thread-523626-1-1.html

最后决定 自己写这个检测算法

 

再次采集一次模拟敲鼓的数据,用图形显示

 

image002.png

 

截取728~897的数据通过EXCEL分析如下,蓝色是每一次抬棒时的最小值,红色是每一次落棒时的最大值

index

val

D = val[index] - val[index - 1]

if(D > 100
 COUNTER = +1
else if(D < -100
 COUNTER = -1
else
 COUNTER = 0

[980]

-1256

 

 

[981]

-1295

-39

0

[982]

-1025

270

1

[983]

-623

402

1

[984]

-190

433

1

[985]

270

460

1

[986]

734

464

1

[987]

1174

440

1

[988]

1560

386

1

[989]

1888

328

1

[990]

2151

263

1

[991]

2351

200

1

[992]

2437

86

0

[993]

2552

115

1

[994]

2580

28

0

[995]

2598

18

0

[996]

2618

20

0

[997]

2662

44

0

[998]

2728

66

0

[999]

2818

90

0

[1000]

2933

115

1

[1001]

3072

139

1

[1002]

3226

154

1

[1003]

3407

181

1

[1004]

3617

210

1

[1005]

3851

234

1

[1006]

4116

265

1

[1007]

4402

286

1

[1008]

4703

301

1

[1009]

4988

285

1

[1010]

5196

208

1

[1011]

5379

183

1

[1012]

5514

135

1

[1013]

5576

62

0

[1014]

5577

1

0

[1015]

5560

-17

0

[1016]

5503

-57

0

[1017]

5390

-113

-1

[1018]

5223

-167

-1

[1019]

5001

-222

-1

[1020]

4728

-273

-1

[1021]

4397

-331

-1

[1022]

3983

-414

-1

[1023]

3472

-511

-1

[1024]

2873

-599

-1

[1025]

2207

-666

-1

[1026]

1496

-711

-1

[1027]

747

-749

-1

[1028]

12

-735

-1

[1029]

-520

-532

-1

[1030]

-843

-323

-1

[1031]

-1024

-181

-1

[1032]

-923

101

1

[1033]

-597

326

1

[1034]

-52

545

1

[1035]

574

626

1

[1036]

1284

710

1

[1037]

2019

735

1

[1038]

2719

700

1

[1039]

3370

651

1

[1040]

3859

489

1

[1041]

4192

333

1

[1042]

4382

190

1

[1043]

4387

5

0

[1044]

4224

-163

-1

[1045]

3878

-346

-1

[1046]

3378

-500

-1

[1047]

2737

-641

-1

[1048]

1944

-793

-1

[1049]

1037

-907

-1

[1050]

78

-959

-1

[1051]

-759

-837

-1

[1052]

-1398

-639

-1

[1053]

-1862

-464

-1

[1054]

-2051

-189

-1

[1055]

-1926

125

1

[1056]

-1611

315

1

[1057]

-1135

476

1

[1058]

-557

578

1

[1059]

77

634

1

[1060]

727

650

1

[1061]

1363

636

1

[1062]

1945

582

1

[1063]

2469

524

1

[1064]

2932

463

1

[1065]

3331

399

1

[1066]

3673

342

1

[1067]

3961

288

1

[1068]

4173

212

1

[1069]

4184

11

0

[1070]

4010

-174

-1

[1071]

3607

-403

-1

[1072]

2973

-634

-1

[1073]

2131

-842

-1

[1074]

1113

-1018

-1

[1075]

332

-781

-1

[1076]

-286

-618

-1

[1077]

-674

-388

-1

[1078]

-774

-100

0

[1079]

-610

164

1

[1080]

-227

383

1

[1081]

214

441

1

[1082]

684

470

1

[1083]

1178

494

1

[1084]

1635

457

1

[1085]

2041

406

1

[1086]

2371

330

1

[1087]

2612

241

1

[1088]

2773

161

1

[1089]

2865

92

0

[1090]

2912

47

0

[1091]

2937

25

0

[1092]

2950

13

0

[1093]

2951

1

0

[1094]

2945

-6

0

[1095]

2931

-14

0

[1096]

2915

-16

0

[1097]

2920

5

0

[1098]

2936

16

0

[1099]

2975

39

0

[1100]

3036

61

0

[1101]

3137

101

1

[1102]

3276

139

1

[1103]

3461

185

1

[1104]

3670

209

1

[1105]

3917

247

1

[1106]

4197

280

1

[1107]

4488

291

1

[1108]

4747

259

1

[1109]

4946

199

1

[1110]

5132

186

1

[1111]

5266

134

1

[1112]

5331

65

0

[1113]

5358

27

0

[1114]

5381

23

0

[1115]

5382

1

0

[1116]

5355

-27

0

[1117]

5300

-55

0

[1118]

5143

-157

-1

[1119]

4823

-320

-1

[1120]

4380

-443

-1

[1121]

3752

-628

-1

[1122]

2909

-843

-1

[1123]

1925

-984

-1

[1124]

881

-1044

-1

[1125]

41

-840

-1

[1126]

-512

-553

-1

[1127]

-904

-392

-1

[1128]

-996

-92

0

[1129]

-795

201

1

 

通过2点差值的大小来判断提棒和落棒速度

设差值参考值Dref100

D = val[index] - val[index - 1]大于100时认为是高速上升

val[index] - val[index - 1]小于-100时认为是高速下降

其它情况为非高速上升和下降,无变化

得到每一个波谷到波峰的计数

和每一个波峰到波谷的计数

计算最大为+24,最小为-8

考虑到可能会有更短或更长的波形,将计数最大值Cmax定为30 ~ 最小值Cmin6

上升和下降少于6为上升下降时间不足

排除干扰

 

一个带有干扰的波形如下图

干扰分为上升干扰B,b1

下降干扰c1,D

image003.png

D=val[index] – val[index-1];

max=0;

counter = 0;

rCounter = 0;

fCounter = 0;

 

每得到一个数据counter++;

Counter > 60时重置所有变量 max,counter,rCounter,fCounter

 

D > 100时且val > max时开始上升计数rCounter++;fCounter=0; max = val;(A~B)

D < -100时开始下降计数fCounter++(B~b1)

当再次D > 100时继续上升计数rCounter++;fCounter  =  0(b1~C)

D<-100时开始下降计数(C~c1) fCounter ++;

D > 100val < max时忽略(c1~D)

D < -100时继续下降计数(D~E) fCounter++;

fCounter > 8 时判断 rCounter是否大于8,满足视为一次完整的峰波

否则重置所有变量 max,counter,rCounter,fCounter

写成C函数就是下边的样子

 

//保存数据最大值(在一次谷~~谷数据内)

int32_t max = 0;

//数据计数,一次谷~~谷必需在指定样本数量内完成

uint32_t counter = 0;

uint32_t rCounter = 0;

uint32_t fCounter = 0;

uint32_t oldSample = 0;

//sample当前样本

//minD = 两点间的最小差值,d值越大要求上升下降速度越快

//minCount 当两点差值大于dcounter++,如果counter少于minCount说明上升和下降时间不够

//maxSampleCount一次谷~~谷允许的最大样本数量

uint8_t PeakCounter(int32_t sample,uint32_t minD,uint32_t minCount,uint32_t maxSampleCount)

{

    int32_t d = sample - oldSample;

    //在指定样本数量内(maxSampleCount)没有检测到谷峰谷

    if(counter++ > maxSampleCount)

    {

                max = 0;

        counter = 0;

        rCounter = 0;

        fCounter = 0;

    }

    //上升

    if(> minD && sample > max)

    {

        //保存最大值

        max = sample;

        //上升计数

        rCounter++;

        //清除下降计数

        fCounter = 0;

    }else if(< -100)//下降

    {

        fCounter++;

        //如果下降满足条件判断上升是否满足条件,如果下降不满足条件还可能会继续上升

        //所以下降不满足条件前不判断上升

        if(fCounter >= minCount)

        {

            //判断如果上升满足条件

            if(rCounter >= minCount)

            {

                                max = 0;

                counter = 0;

                rCounter = 0;

                fCounter = 0;

                //返回计数

                return 1;

            }else

            {   //上升不满足条件,重头开始 

                                max = 0;

                counter = 0;

                rCounter = 0;

                fCounter = 0;

            }

        }

        //下降不满足条件时不处理

        //如果一直不满足条件最后由if(counter++ > maxSampleCount)重置

    }

        else

        {

         

        }

        oldSample = sample;

    //不满足条件时返回0

    return 0;

}

 

 

 

虾扯蛋,蛋扯虾,虾扯蛋扯虾

回复评论 (6)

虾哥,rotation_9X[2]是俯仰数据这个是测试的结论还是有什么说明啊?我记得官方文件里只有一句注释啊

float rotation_9X[NUM_AXES];            /* 9 axes yaw, pitch and roll */
点赞  2017-4-19 13:58
引用: alberthink 发表于 2017-4-19 13:58 虾哥,rotation_9X[2]是俯仰数据这个是测试的结论还是有什么说明啊?我记得官方文件里只有一句注释啊 fl ...
这个是我没说清楚我没细看官方提供的手册 我想如果ST没有规定SensorTile哪个轴代表什么 这些数据代表什么取应该决于SensorTile这个板子是如何安装在“飞机”上的 比如我是这样安装的 QQ图片20170419142806.png 还有一点是rotation_9X[0] ~ rotation_9X[2]这三个数据的范围会有不同 rotation_9X[0] 范围是 0~360rotation_9X[1] 范围是-180~180 rotation_9X[2] 范围是-90~+90 因为是第一次接触姿态相关技术 我看到两篇文章 一篇是CSDN上的 另外值得注意的是,pitch值是不能超过90度,这里牵扯到了万向锁的知识,不再多说,网上很多讨论。” 另一篇是关于游戏开发的文章 a) 偏航角(heading):控制观察方向,是与正北方向的夹角,顺时针一周为360度 b) 俯仰角(pitch):简单的说就是抬头或低头的角度,水平为0度,低头为0至90度,抬头为0至-90度, 所以我觉得rotation_9X[2] 应该是俯仰 本帖最后由 littleshrimp 于 2017-4-19 14:41 编辑
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2017-4-19 14:40
相当给力的说明啊!

根据输出范围来推断算法的输出含义,受教了。

点赞  2017-4-19 15:49


有些东西可能看看手册就能了解
但是英文不好 肯不动啊
点赞  2017-4-19 16:49
顶顶顶,谢谢版主分享!
点赞  2017-4-19 19:15
非常好的过程,值得学习
点赞  2017-4-20 20:59
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复