Overview
========
The application detects anomalies in gyroscope and accelerometer
sensor readings using autoencoder, a neural network that learns
in unsupervised manner. Autoencoder takes sensor data as an input,
reduces them down to core features and than recreates them back.
It is expected data that has never been seen (anomalies) is recreated
poorly with a large error. Data reduction is called encoding and
recreation process is called decoding. Note that the network is trained
using "good" data without any anomalies.

Data consists of 3 accelerometer and 3 gyroscope readings. Accelerometer
readings are scaled down by 10. Raw data is derived (difference between
two consecutive readings is calculated) and 5 consecutive derivatives are
flatten to a 30-dimensional (3*3*5) input vector. Autoencoder is fed by
the input vector to produce an ouput vector. Euclidean distance between input
and output vector is computed. If the error is larger than a threshold,
anomaly is detected.

HOW TO USE APPLICATION:
You can launch the anomaly detection application by runnig adt.cpp. Make sure
that DATA_COLLECT variable is set to false (line 46). You will see an output
similar to this:

Files:
  adt.cpp - main application file
  adt_model.h - hexdump of adt_train/adt_model.tflite
  get_senor_data.c - sensor functions (initialization and reading)
  get_senor_data.h - header for sensor functions
  parameters.h - parameters generated by adt_train/adt_train.py  script 
  adt_train/adt_model.tflite - trained TF-Lite model converted from adt_train/keras_model.h5
  adt_train/adt_train.py - training script
  adt_train/requirements.txt - list of Python libraries required for adt_train.py


Toolchain supported
===================
- Keil MDK  5.30
- IAR embedded Workbench  8.50.1
- MCUXpresso  11.2.0
- GCC ARM Embedded  9.2.1

Hardware requirements
=====================
- Mini/micro USB cable
- EVK-MIMXRT1060 board
- FRMD-STBC-AGM01
- Personal computer

Board settings
==============
Plug FRMD-STBC-AGM01 kit to arduino connector (J22, J23, J24, J25)

Prepare the demo
1. Connect a USB cable between the host PC and the OpenSDA USB port on the target board. 
2. Connect a camera to J35 connector. (Skip this step in the case offline version is used.)
3. Connect a LCD display to A1-A40 and B1-B6. (Skip this step in the case offline version is used.)
4. Open a serial terminal with the following settings:
   - 115200 baud rate
   - 8 data bits
   - No parity
   - One stop bit
   - No flow control
5. Download the program to the target board.
Prepare the Demo
================

Running the demo
================
The log below shows the output of the demo in the terminal window (compiled with ARM GCC):

Anomaly Detection example using a TensorFlow Lite model.
Threshold value 4.80
INFO: Initialized TensorFlow Lite runtime.
(116 us) 27911.50 anomaly detected!!
(62 us) 452.91 anomaly detected!!
(58 us) 1.89
(57 us) 2.11
(51 us) 2.45
(54 us) 2.3
(46 us) 1.7
(48 us) 3.59
(45 us) 2.21
(46 us) 1.34
(44 us) 2.11
(50 us) 12.96 anomaly detected!!
(44 us) 18.15 anomaly detected!!
(46 us) 9.76 anomaly detected!!
(47 us) 8.67 anomaly detected!!
(47 us) 3.8
(46 us) 4.11
(45 us) 2.78
(46 us) 1.88
(48 us) 9.41 anomaly detected!!
(47 us) 13.28 anomaly detected!!
(47 us) 4.51
(47 us) 2.72
(46 us) 2.88
(47 us) 2.88
(49 us) 4.30
(47 us) 6.49 anomaly detected!!
(47 us) 3.78
(45 us) 2.73
(44 us) 1.9
(45 us) 1.81
(47 us) 3.36
(46 us) 22.15 anomaly detected!!
(46 us) 38.68 anomaly detected!!
(46 us) 7.41 anomaly detected!!
(48 us) 3.58
(47 us) 2.21
(47 us) 2.19
(44 us) 2.82

Train your own model
To train your own model, you need to collect "good" data on board, train a new
model on PC and load it to the project.

1 Collect data

The first step is to collect "good" sensor data. Set DATA_COLLECT variable is set
to true (line 46) and run adt.cpp. By default, 1000 samples are collected. You can
change this number by changing SAMPLE_NUM variable (line 47). Data is printed
to an external console; copy and save the output to a file. SmarTTY terminal is
recommended to use.
Put the board with sensors on a stable surface. Do not shake sensors while
collecting training data. You can repeat data collect with surface shakes to
validate the model.
Reference data contains 1000 samples of training data (input_data.txt) collected
with the sensor placed on a level horizontal surface and 1000 samples of
validation (validation_data.txt) data with surface shakes happening every
50 samples.

2 Train autoencoder model

2.1 Install python libraries

  Create new anaconda environment (can be skipped)

  >> conda create -n adt pip
  >> activate adt

  Install python libraries from requirements.txt placed in adt_train folder

  >> pip install -r requirements.txt

2.2 Run adt_train.py script:

  >> python adt_train.py --input_data="input_data.txt" --validation_data="validation_data.txt" --vizualize=1

The script creates an autoencoder model and trains it with data loaded from
"input_data" file. The trained model is converted into tflite model and dumped
as a C source code file. The trained keras model, converted tflite model and
dumped C file are stored as "keras_model", "tflite_model" and "c_model" files.
The script also creaset parameters.h file with parameters of the model.
In the end, data from "validation_data" file are evaluated and the error is
printed. As the patch size is set to 5, every 10th patch evidences a higher
error due shakes.

Note that quoted words represent parameters of adt_train.py script.

3 Run application

Copy "c_model" and parameters.h files into the project. The project expects
"c_model" file to be named 'adt_model.h'. Set DATA_COLLECT variable is set to
false (line 46) and run the main script.
Customization options
=====================

