%% Hacking Better Emergency Response Times with MATLAB Mobile
% Today we are joined by Rafael Otero, Alejandro Sánchez Roncero, Víctor Manuel López Higueras, and Pablo Pastor, who won first place at MATHACK 2022 by developing an application that can detect if someone has experienced a physical shock and, if so, send an alert to a chosen emergency contact. Over to you guys!
%
%% Inspiration
% For MATHACK 2022, organized by the European MATLAB Student Ambassadors, we had to develop a small application that contributed to the UN Sustainable Development Goals with the help of MATLAB, a mobile device and its sensors. Via MATLAB Mobile we could acquire data such as accelerations (linear and angular) and position (3D coordinates) and stream it to our personal computers in real-time. Measured data should be processed (i.e., filtering and state estimation). Using this data, we had to propose an application that contributed positively to at least 1 Sustainable Development Goal (SDG).
%
% [image source: https://sdgs.un.org/goals]
%% Breaking down the problem
% All the members of the team had previous experience working with MATLAB since it is included in our university degree curriculum (Aerospace Engineering). However, the fact of having to apply our knowledge to a real problem was initially difficult for us because we hadn’t used MATLAB Mobile before and we had difficulty collectively generating our own datasets for training and validation (usually they are provided in class lessons). For the same reason, we were also excited to get hands on experience and tackle this challenge. After a few minutes of brainstorming and some ideas, we came up with the idea to implement a Shock Alert Monitor (SAM). SAM would have two main functionalities: estimate the current dynamic state of the person carrying the mobile (i.e., idle, walking or running) and detecting shocks. In this way, the application could notify to the person's relatives via Telegram if a shock was detected, so that medical assistance could be provided faster than in normal situations.
% This project is thus related to the following SDGs:
% SDG3 (Good health and well-being) by improving healthcare since it greatly reduces the arrival time of medical staff.
% SDG10 (Reduces inequalities): by helping people who live far from hospitals in big cities and whose access to healthcare is not totally guaranteed.
% SDG11 (Sustainable cities and communities): by extending the Smart City concept since it provides useful information for city services.
%
% [image source: https://sdgs.un.org/goals]
%
%% How SAM works?
% During the competition, all members of the team worked hard to develop the Shock Alert Monitor. The SAM project can be divided into five parts: Data acquisition, Filtering, State classification, Shock detection and Shock Notification. These parts can be seen in the following figure:
%
%% 1. Data acquisition
% Using the application MATLAB Mobile, we gather from the sensors of the smartphone the following data:
% Acceleration (linear and angular) in the body reference system of the mobile.
% Speed.
% Position (i.e., latitude, longitude and altitude).
%
% The data is streamed continuously and in real time from the mobile phone to the computer via internet. This provides a great advantage since both devices are not required to remain close to each other for the application to work correctly. The acquisition frequency was set to 100 Hz (the maximum allowed by the application). With the help of MATLAB documentation, the implementation was straightforward: from the mobile side, we only need to install the application and connect to the MATLAB cloud. From the computer side, we also connect to the MATLAB cloud and create a moviledev object which gets updated continuously.
% To validate the model in later stages, we also allowed the option to choose between real-time data or data that was logged previously. Using the second option, a datafile was loaded during the setup of our program.

if obj.isModeOffline() 

    load(obj.input_file); 
    obj.offline_data.Acceleration = Acceleration; 
    obj.offline_data.Position = Position; 

elseif obj.isModeStream() 

    % Enables the mobile to log and stream data 
    obj.mobile_obj = mobiledev; 
    obj.mobile_obj.SampleRate = 100; % Sets sample rate at which device will acquire the data 
    obj.mobile_obj.AngularVelocitySensorEnabled = 1; 
    obj.mobile_obj.OrientationSensorEnabled = 1; 
    obj.mobile_obj.AccelerationSensorEnabled = 1; 
    obj.mobile_obj.PositionSensorEnabled = 1; 
    obj.mobile_obj.MagneticSensorEnabled = 1; 
    obj.mobile_obj.Logging = 1; % Start the transmission of data from all selected sensors 

else 
    
    error('Selected mode: %s not valid', obj.mode); 

end  

%% 2. Filtering
% The acceleration data acquired from the mobile device is noisy, so after acquisition, a second stage of filtering is required to be implemented. Due to our background in signal analysis, we already knew that we should implement a low-pass filter, since the information is contained the low-band frequency. However, it is always a good practice to analyse the signal, so we used the Signal Analyzer App of MATLAB. Since the acceleration is obtained in the 3-body axis, we first compute its norm. In the following figure it can be seen how the signal energy is concentrated in the low frequencies.
%
% Once it was confirmed that a low-pass filter should be designed, we moved to the MATLAB's Filter Designer App to choose the best model and adjust its coefficients. We selected a Finite Impulse Response (FIR) filter with the design method Least-squares. The pass and stop frequencies were set to 0.5 and 20 Hz respectively. The raw and filtered signals are depicted in the following figure.
%
% The velocity and the position were not required to be filtered.
%% 3. State classifier
% The speed of the user, which can be obtained through MATLAB Mobile, is used to determine if they are idle, walking, running or driving. But why do we need to know the state of the smartphone if we only want to detect acceleration shocks? For a safety reason: If we detect a 2g shock while the user is driving, it will be more dangerous than the same shock when the user is idle or walking. That reason makes this part of the project very important because if we know the state of the user, we can determine how harmful the detected shock has been.
% To determine the state of the smartphone based on its velocity, we have used a K-Nearest Neighbor Classifier Model. Machine Learning and Deep Learning are very powerful tools and we wanted to include one of these techniques in our project. On https://www.kaggle.com/, we found a dataset that contained the velocity of the sensor and four different states to classify: IDLE, WALKING, RUNNING and DRIVING. Our K-NN model was trained using automatic hyperparameter optimization:

load dataset.mat 

%% Variable assignment 
velocity = dataset.velocity; 
label = dataset.label; 

%% Train the model 
model = fitcknn(velocity,label,'OptimizeHyperparameters','auto'); 

%% Compute the loss and get the confusion chart 
predictions = predict(model,velocity); 
loss(model,velocity,label) 
confusionchart(predictions,label) 

%% Save the model 
save('model.mat','model')

%
% Once the model is trained, we are ready to predict the state of the user with the next MATLAB function:

function state = getState(velocity,model,interval,Fs) 

    % state -> State of the sensor based in its velocity 
    % velocity -> Velocity magnitude time vector (m/s) 
    % model -> Machine Learning model used for prediction 
    % interval -> Interval used for computing the mean of velocity (s) 
    % Fs -> Sampling rate (Hz) 
    
    Vmean = mean(velocity(end-interval*Fs:end)); 
    state = char(predict(model,Vmean)); 

end 

%% 4. Shock detection
% To manage if the smartphone of the user has suffered an important acceleration shock, we just compute the maximum acceleration in a pre-defined interval. Then, we compare this maximum with our threshold acceleration and if the threshold is exceeded, we detect the shock with a Boolean variable:

function [shock, Amax] = isShock(acceleration,threshold,interval,Fs) 

    % shock -> Indicates a shock in the acceleration data (boolean) 
    % Amax -> Maximum acceleration in the samples (m/s2) 
    % acceleration -> Acceleration magnitude time vector (m/s2) 
    % threshold -> Acceleration above this value will be considered as shocks (m/s2) 
    % interval -> Interval used in the shock search (s) 
    % Fs -> Sampling rate (Hz) 

    Amax = max(acceleration(end-interval*Fs:end)); 
    
    if Amax > threshold 
        shock = true; 
    else 
        shock = false; 
    end 

end 

%% 5. Notification
% SAM only sends a notification if the acceleration threshold has been exceeded. In the message we can see the magnitude of the shock (measured in g’s), the state of the user (IDLE, WALKING, RUNNING or DRIVING) and the location of the impact in a map.
% Through a Telegram bot, the notification is sent to an external device (emergency services, relatives, friends, …). The MATLAB-Telegram coupling was very easy with the Telegram Bot Toolbox API. We want to thank Aleksei Kulkin for this work because it lets you to do useful things with a few lines of code. The function that we used to notify a dangerous shock is:

function sendAlert(state,Amax,lat,lon) 

% state -> State of the sensor based in its velocity 
% Amax -> Maximum acceleration of the shock (m/s2) 
% lat -> Latitude (deg) 
% lon -> Longitude (deg) 

addpath('telegram_functions') 
BotToken = 'HERE YOUR BOT TOKEN'; 
ChatID = 'HERE THE CHAT ID OF THE PERSON YOU WANT TO NOTIFY'; 
ShockBot = telegram_bot(BotToken); 

mapsURL = ['https://www.google.es/maps/dir//' sprintf('%.7f',lat)... 
    ',' sprintf('%.7f',lon) '/@' sprintf('%.7f',lat) ',' sprintf('%.7f',lon) ',16z?hl=es']; 

figure('visible','off'); 
geoplot(lat,lon,'.r','MarkerSize',30) 
geolimits([lat-0.001 lat+0.001],[lon-0.001 lon+0.001]) 
geobasemap streets 
saveas(gcf,'map.png') 

msg = ['System detected a <b>' sprintf('%.2f',Amax/9.81) 'g shock</b> while '... 
    'user was <b>' state '</b>. Google Maps: ' mapsURL]; 

ShockBot.sendPhoto(ChatID, 'photo_file', 'map.png',... % photo 
    'usepm', true,... % show progress monitor 
    'caption', msg,'parse_mode','HTML'); % caption of photo 

end 

%% Results
% Combining every explained step in the previous sections, we can now see how SAM works. To test and validate the model, we implement a simulation environment in Simulink. To debug the model in real-time, we select as solver an ode1 (Euler) with a fixed-step (1 s) and a stop time of infinity. In this way, the model can be running all the time it is needed, and we can visualise and debug the results in real time. In the following picture we show the scheme of the Simulink model, where the main_class refers a to a MATLAB class which implements all the functions that were described previously.
%
% Now we use this model to test SAM. First, we can see one member of the team hanging his smartphone. The acceleration measurements are below the threshold (he is not shaking his phone) so no shock is detected by SAM.
%
% Then, he throws his phone, and a big acceleration spike is captured. When the signal is bigger than the acceleration threshold, SAM detects a shock as we can see in the next image:
%
% When the shock is detected, a message through a Telegram bot is sent to another device. The alert contains the maximum acceleration detected, the identified state by the ML model and the location of the phone in a map:
%
%% Key Takeaways
% Participation in MATHACK 2022 has created a great motivation and experience for all of us. It not only allowed us to improve our teamwork skills, but also to know how to work under pressure, something that is essential in a hackathon. We also gained a great insight in new applications that MATLAB offers and got hands on experience in a real-life project, with all the difficulties that it carries. Last but not least, we would like to congratulate the rest of the MATHACK 2022 participants. Their projects were very interesting, and at the end we all need to cooperate in order to have effective and positive contributions on the SDGs. The code, model and datasets can be found in this repository.