[作品提交] 【环境专家之智能手表】Part9:活动状态识别

w494143467   2021-6-21 22:06 楼主

1.介绍

活动状态有很多种,主要有站立、坐、走路、浅睡、深睡、跑步、未佩戴,当然这里的每一个状态的识别都是需要有算法的,对原始数据进行分析,然后去编写算法,当然还有机器学习,刚开始算法根据人的身高和体重(用户自行输入),进行算法匹配,而后面通过采集该用户的各种状态的数据并分析,给出最合适的算法,同时还可以像另一个选手的作品【跑步姿势训练鞋】识别用户走路的姿态,给用户建议,不过这个有一定的难度,这次作品就不做了。

2.状态识别

这次作品主要识别三种姿态,未活动,走路和工作。【未活动】是这个是最好检测,的只要检测三轴的方向是否长时间未改变,那么就可以知道佩戴者处于未活动。如果要识别是睡眠还是未活动,这个需要有进一步的算法,暂时略过。

走路的话,其实也是比较好识别的,人在走路过程中,手是晃动的,那么三轴的方向是变化的,就如同下图1一样,戴着【RSL10-SENSE-GEVK】设备时走出分骚的步伐时的三轴角度变化。

1_0.gif

图1

加速度驱动就不过多的分析了,拿到三轴的方向数据之后,模拟走路输出的波形如下图2所示。

2.png

图2

其中蓝色是X轴,红色是Y轴,绿色是Z轴。可以看到红色数据变化最大。

那么正常走路的情况下分析X轴就可以了,其中一个波峰或一个波谷就是一步,那么就可以通过这个特性编写计步检测算法,为了预防晃动导致的计步,会有一个前十步的统计,当走了十步之后才会真正开始计步,当然也会加上这十步,如果一次走路未满十步,则会被判断为晃动,具体的实现的代码如下:

int16_t last_y_org = 0;
int16_t last_y_peak = 0;
uint8_t walk_status = 0;	//0未走路,1走路中
uint32_t step_cnt = 0;		//当前步数
uint8_t step_after = 0;		//前十步统计
uint8_t stap_dif_cnt = 0;	//数值不同
//检测走路
uint8_t activity_walk_detect(int16_t y_org)
{
	if(last_y_org == y_org)
	{
		stap_dif_cnt++;	//数值一直相同
		if(stap_dif_cnt >= 10)
		{
			stap_dif_cnt = 0;
			walk_status = 0;//当前未走路
			step_after = 0;	//前十步清零
		}
		return walk_status;
	}

	last_y_org = y_org;
	if(last_y_peak > 0)		//峰值大于0
	{
		if(last_y_org < 0)		//小于0
		{
			if(walk_status == 0)
			{
				step_after++;
				if(step_after >= 10)
				{
					step_after = 0;
					step_cnt += 10;
					walk_status = 1;
				}
			}
			else
			{
				step_cnt++;//步数+1
			}
			stap_dif_cnt = 0;
		}
		else
		{
			stap_dif_cnt++;	//数值一直相同
			if(stap_dif_cnt >= 10)
			{
				stap_dif_cnt = 0;
				walk_status = 0;//当前未走路
				step_after = 0;	//前十步清零
			}
		}
	}
	else
	{
		if(last_y_org > 0)		//小于0
		{
			if(walk_status == 0)
			{
				step_after++;
				if(step_after >= 10)
				{
					step_after = 0;
					step_cnt += 10;
					walk_status = 1;
				}
			}
			else
			{
				step_cnt++;//步数+1
			}
			stap_dif_cnt = 0;
		}
		else
		{
			stap_dif_cnt++;	//数值一直相同
			if(stap_dif_cnt >= 10)
			{
				stap_dif_cnt = 0;
				walk_status = 0;//当前未走路
				step_after = 0;	//前十步清零
			}
		}
	}
	last_y_peak = last_y_org;
	return walk_status;
}

通过上面的算法,对应着刚才的波形数据,实际得出的步数波形如下图3所示:

3.png

图3

其中蓝色为前十步统计,红色为实际步数,绿色为计步状态,可以看到十步之后,实际步数开始直接加上10步,然后就在稳步增长,可以对比图2和图3查看。

接下来就是工作状态了,由于只有三个状态,所以除了未活动和走路就是工作状态了,这里写的比较简单,当不是走路时且三轴方向有变化,就被当作为工作状态,具体代码如下:

//检测工作
int16_t global_x_org = 0;
int16_t global_y_org = 0;
int16_t global_z_org = 0;
uint8_t no_work_cnt = 10;
//检测工作,只要动就是工作
uint8_t activity_work_detect(int16_t x_org, int16_t y_org, int16_t z_org)
{
	if(abs(global_x_org - x_org) > 100  || abs(global_y_org - y_org) > 100 || abs(global_z_org - z_org) > 100)
	{
		global_x_org = x_org;
		global_y_org = y_org;
		global_z_org = z_org;
		no_work_cnt = 10;
		return 1;
	}
	else
	{
		if(no_work_cnt > 0)
			no_work_cnt--;
		if(no_work_cnt == 0)
			return 0;
	}
	return 1;
}

最后就是这代码的整合,然后通过广播发送给矿井外设备了,整合的代码如下:

//传入数据
void activity_update_data(bhy_data_vector_t act_data)
{
	uint8_t ret_value = 0;
	ret_value = activity_walk_detect(act_data.y);
	printf("walk:%d,%d,%d\n", step_after, step_cnt, ret_value);
	if(ret_value > 0)	//在走路中,不检测是否在工作
	{
		now_status = WALK;
		return;
	}
	ret_value = activity_work_detect(act_data.x, act_data.y, act_data.z);
	printf("work:%d,%d\n", no_work_cnt, ret_value);
	if(ret_value > 0)
	{
		now_status = WORK;
		return;
	}
	else
	{
		now_status = NO_ACTIVITY;
	}
}

//获取当前状态
ACTIVITY_STATUS activity_get_status(void)
{
	return now_status;
}

3.总结

活动状态检测其实还有很多状态要识别的,由于时间问题暂时就写了这三个状态,能够简单的识别走路,工作和未活动对于这个作品来说够用了,下一篇写状态灯和模式相关的内容。

本帖最后由 w494143467 于 2021-6-27 13:23 编辑

回复评论 (6)

赞,学习了

点赞  2021-6-23 09:10

厉害

那个动画的走姿太骚包啦,哈哈哈

点赞  2021-6-23 16:21
引用: sipower 发表于 2021-6-23 16:21 厉害 那个动画的走姿太骚包啦,哈哈哈

哈哈,突然想到的,娱乐一下哈。

点赞  2021-6-23 21:00

我也觉得是,走路的小人屌屌的。

加油!在电子行业默默贡献自己的力量!:)
点赞  2021-6-24 09:02

给你贡献个小点,人跑步和走路的最大区别 是加速度是不是会出现0值

点赞  2021-6-24 22:33

点赞  2021-6-26 15:22
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复