Roupas são inteligentes, mas nós somos mais inteligentes: como fizemos uma camiseta com controle de postura

Olá! No segundo semestre, todos os alunos do primeiro ano do programa de Matemática Aplicada e Informática em São Petersburgo HSE fazem projetos de equipe em C ++ . Estamos desenvolvendo uma camiseta inteligente.



Leia sobre o que é e o que conseguimos fazer durante o trabalho no projeto neste artigo.





Nós, Denis Tarasov e Denis Filippov, já somos alunos do segundo ano de graduação em Matemática Aplicada e Informática no HSE de São Petersburgo. Trabalhamos no projeto junto com Yan Freidkin e Ivan Chunarev. Estudamos com eles na mesma escola: São Petersburgo GFML nº 30.



No 11º ano, Yan e Ivan fizeram um projeto de robótica ー "Smart T-shirt" (está na primeira foto). A ideia é a seguinte: tira-se uma camiseta, vários sensores são acoplados a ela (acelerômetro, giroscópio e outros). Alguns indicadores podem ser determinados a partir dos dados lidos, por exemplo, a postura correta. Os caras conseguiram participar de várias conferências e iriam continuar trabalhando no projeto após a formatura, mas perceberam que precisavam de programadores. Na verdade, aqui estamos.



A camiseta de Jan e Ivan podiam ler o ECG e rastrear a postura correta. Para isso, foi utilizado o Arduino UNO - uma plataforma de desenvolvimento com microcontroladores AVR desatualizados. Logo, eles ficaram sem memória de código. Em uma nova etapa de trabalho do projeto, percebemos que era necessário impor requisitos mais rígidos ao microcontrolador: 



  • para conectar mais sensores, era necessário um processador com uma frequência mais alta, mais periféricos e periféricos mais rápidos;
  • mais memória flash, RAM;
  • custo mais baixo;
  • estabilidade do microcontrolador.


Decidimos que precisávamos trocar o microcontrolador. Tínhamos duas opções: usar um microcontrolador da série AVR mais potente (no nosso caso, Arduino) ou mudar para outra série de microcontroladores, nomeadamente ARM (no nosso caso STM32). Apesar da grande comunidade do Arduino e da facilidade de uso desse microcontrolador, decidimos fazer o upgrade para o STM32 porque ele tem melhor desempenho e mais memória. No momento, estamos usando um microcontrolador STM32f4 *.





No semestre passado, estabelecemos como meta realizar o recebimento de informações sobre a postura de uma pessoa e seu processamento. O esquema do projeto é o seguinte: temos uma camiseta com acelerômetros e giroscópios presos a ela, com a ajuda dos quais obtemos os ângulos de torção. Os dados recebidos dos sensores são enviados ao microcontrolador. Lá eles são processados ​​e, se necessário, é aplicada tensão ao motor de vibração, que estimula a pessoa a se endireitar. Usando o aplicativo Android, o processamento da postura é ligado e desligado, e a camiseta é vinculada ao usuário. Mas, em geral, uma camiseta pode funcionar sem acesso a um smartphone: você pode ativar o processamento postural no aplicativo, deixar o celular em casa e dar um passeio de camiseta. Neste caso, os dados serão processados ​​no microcontrolador e o motor de vibração ligará se a posição estiver incorreta.





Os primeiros passos. LED aceso



Não tínhamos experiência em programar microcontroladores e lemos que inicializar e declarar sensores e pinos em um STM é longo e difícil. Portanto, usamos um alto nível de abstração usando a biblioteca HAL e STM32CubeMX . STM32CubeMX é uma ferramenta que configura portas de microcontroladores usando uma interface gráfica e gera o código apropriado usando a biblioteca HAL. Primeiro, decidimos fazer a coisa mais básica na programação do microcontrolador (no nível “Hello world”) acender o LED.





Interface STM32CubeMX



Após uma longa busca por um IDE que fosse multiplataforma, gratuito e fácil de desenvolver, optamos pelo STM32CubeIDE







A tarefa de acender o LED acabou não sendo das mais fáceis, já que existem muitas informações sobre a programação do STM32 na Internet (principalmente em comparação com o Arduino). No futuro, esse fator também complicou o trabalho no projeto.



Firmware de microcontrolador



Depois que aprendemos como acender o LED e como programar o microcontrolador em geral, começamos a escrever a base do firmware do microcontrolador, com base na qual várias funcionalidades poderiam ser adicionadas no futuro. Para começar, foi necessário aprender a inicializar os sensores e receber informações deles. Dos sensores, conseguimos chegar apenas aos sensores IMU: o giroscópio e o acelerômetro. Tínhamos sensores MPU-6050. 





A comunicação com o microcontrolador é realizada através do barramento I2C. Graças à biblioteca HAL, a transferência de dados é fácil: você precisa chamar uma função para ler / escrever. Um exemplo de leitura de dados de um acelerômetro do código:



HAL_I2C_Mem_Read(i2c_handle, addres, ACCEL_XOUT_H_REG, 1, buffer, 6, 1000)


A função recebe o manipulador do barramento desejado, o endereço do sensor nele, o registro do qual é necessário ler (os registros são escritos na documentação do sensor), o tamanho do registro, o buffer para gravação, o tamanho do buffer e o tempo limite (o tempo gasto esperando por uma resposta) em milissegundos. A função de gravação tem uma assinatura semelhante. Exemplo de configuração da faixa de medição de um giroscópio:



HAL_I2C_Mem_Write(i2c_handle, addres, GYRO_CONFIG_RE	G, 1, &Data, 1, 1000)


Também tínhamos um módulo Bluetooth (HC-05 e HC-06), mas não exigia nenhuma manipulação especial para funcionar. Depois de conectá-lo, você pode simplesmente enviar dados através do transceptor assíncrono universal (UART) - um dispositivo especial dentro do microcontrolador que permite a comunicação com outros dispositivos. Para isso, o HAL oferece funções semelhantes às do I2C. Acabamos de escrever um pequeno invólucro sobre eles para facilitar a exibição de mensagens durante a depuração.





HC-06



Em seguida, criamos uma classe Controller que inicializa os sensores, inicia o loop principal do programa e processa as solicitações vindas do aplicativo. As solicitações são armazenadas em uma fila, recebidas via Bluetooth e recebidas usando um mecanismo de interrupção. Uma interrupção é um sinal de software ou hardware que informa o processador sobre a ocorrência de um evento que requer atenção imediata. O mecanismo de interrupção é necessário, entre outras coisas, para a resposta rápida do sistema a eventos importantes. 



O Controlador também mantém uma lista de funções de camisetas usando a classe base BaseFunc. No momento, só temos processamento postural, mas no futuro, ao adicionar novas funcionalidades, bastará apenas criar uma classe descendente e adicioná-la à lista de funções. O controlador é parecido com isto:



class Controller {
std::vector<std::unique_ptr<IMU>> IMUSensors;  //  
std::queue<Request> reqQueue; //  
std::vector<std::pair<std::unique_ptr<BaseFunc>, bool>> mithrilFuncs; //   
//< ,   >
Controller();
void Run(); //   
};


Além disso, para obter os ângulos de torção dos sensores IMU, tivemos que adicionar um filtro especial que, de acordo com os dados do acelerômetro e do giroscópio, fornece os ângulos de deflexão corretos. Decidimos usar um filtro complementar porque é bastante eficiente e fácil de implementar. Ao implementar esse filtro, escrevemos a matemática para quatérnios. Era possível sobreviver com vetores, mas quatérnions eram necessários em outro filtro que testamos, então agora estamos usando quatérnios.



O que há no protótipo



Depois de descobrir a programação do microcontrolador e escrever o básico de seu firmware, precisávamos de um protótipo de camiseta, com a qual poderíamos começar a fazer o processamento de postura. E então o coronavírus interveio ... 



Devido à pandemia, não pudemos mais nos encontrar e trabalhar em uma camiseta com nós quatro, e na verdade não tivemos a oportunidade de ir até o Jan e o Ivan para que em caso de problemas com protótipos, pudéssemos resolvê-los rapidamente. Jan e Ivan desenvolveram um protótipo de camiseta em que os sensores podiam ser colocados puxando os fios para que não afetassem as leituras com seu peso e tensão. Os caras enviaram a Denis e a mim uma cópia de uma camiseta, bem como fita isolante, fios etc., para que nós mesmos pudéssemos eliminar possíveis avarias. 



App Android



Propusemo-nos a criar uma aplicação Android com a capacidade de comunicar via Bluetooth com um microcontrolador. Como no caso da programação de microcontroladores, não tínhamos experiência em escrever aplicativos para Android, mas acabou sendo muito mais fácil encontrar informações sobre o Android do que sobre o STM32. Aprendemos o básico com o  curso em Stepik.org (o curso é muito bom), onde primeiro você analisa o básico da linguagem Kotlin e depois fala sobre programação para Android. 



A primeira versão do aplicativo permitia conectar-se ao microcontrolador via Bluetooth e enviar mensagens para ele. A última versão não difere muito da primeira (escrever um aplicativo não era uma prioridade para nós): agora ela tem widgets para iniciar a calibração e ligar / desligar a função de rastrear a postura correta. 



Demorou cerca de 6 horas para escrever a primeira versão funcional do aplicativo - passamos mais tempo estudando a teoria. O código para um aplicativo tão simples ocupava cerca de 400 linhas, o que foi uma surpresa agradável. Além disso, com certeza pode ser escrito de forma mais compacta.  Guia do





menu de navegação





para conexão Bluetooth





Guia para troca de dados



Tratamento de postura



Descobrimos duas maneiras diferentes de lidar com a postura: com e sem métodos de análise de dados.



Tratamento Postural Usando Técnicas de Análise de Dados



Na versão anterior, a camiseta tinha apenas um sensor, de acordo com os dados a partir dos quais se decidia a postura correta de uma pessoa: dependia do ângulo de rotação do sensor. Obviamente, esta abordagem não pode fornecer alta precisão, pois não temos dados sobre a posição da maioria das costas. Nossa versão possui 4 sensores. Foi muito difícil descobrir como interpretar suas leituras, por isso decidimos recorrer a métodos de análise de dados. Devido a problemas com protótipos, muito não foi feito dentro do prazo. 



Primeiro, pegamos os dados de nós mesmos: ângulos de torção e leituras do acelerômetro de cada um dos sensores. Conseguimos cerca de 2.000 medições: cerca de 1.000 positivas e 1.000 negativas. A configuração do sensor foi a seguinte (dois sensores estão localizados nas omoplatas e dois na coluna):





 

Infelizmente, em ambos os protótipos, houve problemas com um dos quatro sensores, então o sensor número 3 não foi usado. Nós os colocamos intuitivamente: queríamos rastrear a posição das omoplatas e da coluna vertebral perto do pescoço.







Projeção de dados no espaço bidimensional.



Aqui, as áreas de postura correta são destacadas em verde e as áreas de postura incorreta são destacadas em vermelho. Em uma projeção no espaço tridimensional, vê-se que as posições corretas e incorretas são facilmente separáveis ​​umas das outras. 





Em seguida, foi necessário selecionar modelos de previsão. Decidimos tentar a regressão linear, ou melhor, sua modificação de Ridge, máquina de vetor de suporte (SVM) com um kernel linear e uma árvore de decisão. A escolha se deve à simplicidade de transferência dos modelos para o microcontrolador: os dois primeiros são descritos por um certo número de coeficientes, e o último é um conjunto de condições if-else. Os modelos foram retirados da biblioteca scikit-learn. Exemplo de transição de regressão linear:



bool isPostureCorrect =
           (a11 * deviceAngles1[0] + a12 * deviceAngles1[1] + a13 * deviceAngles1[2] +
           g11 * deviceGravity1[0] + g12 * deviceGravity1[1] + g13 * deviceGravity1[2] +
           a21 * deviceAngles2[0] + a22 * deviceAngles2[1] + a23 * deviceAngles2[2] +
           g21 * deviceGravity2[0] + g22 * deviceGravity2[1] + g23 * deviceGravity2[2] +
           a41 * deviceAngles3[0] + a42 * deviceAngles3[1] + a43 * deviceAngles3[2] +
           g41 * deviceGravity3[0] + g42 * deviceGravity3[1] + g43 * deviceGravity3[2]) > bias;


os valores a ??, g ??, bias são retirados do modelo treinado.



A precisão dos modelos com diferentes configurações na amostra de teste pode ser vista na tabela:





O tamanho da amostra de teste foi de 33% de todos os dados. Essas taxas altas são provavelmente devido à pequena quantidade de dados, porque as previsões são muito boas.



Na vida real, os modelos que testamos (árvores de decisão e algumas configurações de regressão linear) não funcionaram muito bem, então eles tiveram que ser ligeiramente ajustados para que se comportassem de forma mais adequada. O melhor Ridge é aquele treinado em ângulos de torção.





Um exemplo de árvore de decisão.



Em uma pandemia e com apenas dois protótipos, não conseguimos coletar uma grande quantidade de dados de pessoas diferentes, o que é ruim para os modelos. Além disso, a solução atual usa apenas uma medida para determinar a postura correta, o que, obviamente, não é suficiente. Uma pessoa pode simplesmente se curvar sobre o objeto e a camiseta começará a vibrar. Para resolver esses problemas, você deve tentar modelos que façam previsões a partir da sequência de dados de entrada, mas esses modelos serão mais difíceis de transferir para o microcontrolador da forma que era na solução atual.



Postura reversa sem métodos de análise de dados



Para lidar com a postura sem ML, muitos artigos médicos sobre postura tiveram que ser estudados primeiro. Eu realmente queria encontrar informações sobre características quantitativas que pudessem ser medidas e comparadas com a norma: isto é, saber a faixa "normal" de valores.



Estudamos muitos artigos, mas a maioria deles não apresentava características quantitativas, ou as características não puderam ser medidas com os meios de que dispomos. Apenas um artigo se mostrou útil para nós (aliás, muitos outros estudos relacionados à postura humana se referem a ele). Ele descreveu vários ângulos, os valores dos quais podem ser usados ​​para determinar a postura correta.





Métricas de postura em pessoas com transtorno depressivo maior antes (A) e depois (B) do tratamento de J. Canales et al (2010). A



única coisa que resta a fazer é medir esses ângulos. Para medir, você pode representar aproximadamente a posição normal da coluna usando alguma função e, em seguida, pegar os pontos necessários no gráfico e pesquisar os valores de vários ângulos a partir deles. 







Configuração do sensor



Os sensores estão localizados ao longo da coluna. Nos pontos onde elas estão localizadas, você pode obter os ângulos de inclinação das tangentes, e assim encontrar o valor da derivada (que é igual à tangente do ângulo de inclinação das tangentes). À medida que a coluna se curva, as coordenadas dos pontos mudam o tempo todo. Por isso, é impossível aplicar, por exemplo, a interpolação de Hermite. Nesse caso, as distâncias entre os pontos ao longo da curva são conhecidas: podem ser medidas fisicamente. Inicialmente, usando esses dados, queríamos tentar encontrar uma função suave, por exemplo, algum polinômio. Mas, em primeiro lugar, isso requer mais pontos em que as derivadas sejam conhecidas e, em segundo lugar, o problema não é tão simples do ponto de vista matemático e computacional. Portanto, neste estágio de desenvolvimento, decidiu-se aproximar a coluna vertebral usando uma função linear por partes.





Como resultado, dos dois ângulos que tentamos medir (ângulos 3 e 4 na imagem do artigo), um foi medido corretamente e o outro não. Os valores do ângulo 3 coincidiram com os valores normais indicados no artigo. O ângulo 4 foi medido mal devido às características do design. Provavelmente, o problema está no fato de que a camiseta não se ajusta perfeitamente ao corpo em alguns pontos, razão pela qual o ângulo de inclinação das tangentes é calculado incorretamente.



Vídeo de demonstração



Aqui está um vídeo de demonstração da camiseta e do aplicativo funcionando:





O processamento da postura é iniciado primeiro, depois a calibração começa e, em seguida, mensagens sobre a postura correta começam a chegar.



Conclusão



Como resultado, conseguimos processar a postura de duas maneiras, lidar com programação para Android, escrever um aplicativo para Android e ao mesmo tempo entender um pouco sobre a programação do microcontrolador STM32.



Claro, nossa camisa não pode ser considerada acabada - mas até agora estamos trabalhando nela por um semestre do primeiro ano. Ainda há muito a ser feito e no ano que vem pretendemos continuar!



Agora um pouco sobre nossos planos para o futuro. Nós queremos:



  • Refine as aproximações da coluna com uma função para medir com mais precisão os ângulos associados à coluna.
  • Colete mais dados para processamento de postura. No momento, os dados foram obtidos apenas de nós dois e nossos protótipos são ligeiramente diferentes. 
  • Expanda a funcionalidade. Por exemplo, adicione uma gravação de eletrocardiograma para que possa ser usada para identificar várias doenças, anormalidades, etc.
  • Melhore o aplicativo: expanda sua funcionalidade. Por exemplo, calcule estatísticas, analise-as, desenhe gráficos.
  • Crie um protótipo de uma camiseta que terá uma aparência mais comercial. No estágio atual, os protótipos se destinam exclusivamente a testar a funcionalidade. Quero montar uma camiseta pronta para uso.


Links para o github do projeto:



github.com/DT6A/Mithril firmware do microcontrolador,

github.com/DT6A/MithrilAppー aplicativo para Android,

github.com/DT6A/MithrilDataー trabalho com dados.



All Articles