Merge remote-tracking branch 'origin/main'
# Conflicts: # code/src/Fitbot/app/src/main/java/com/example/fitbot/ui/activities/FitnessActivity.java
This commit is contained in:
@@ -33,8 +33,12 @@ const char* Connectivity::fetchIPAddress() {
|
||||
int httpCode = http.GET();
|
||||
if (httpCode > 0) {
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
// If successful (code 200), read the response body and store the IP address
|
||||
ipAddress = strdup(http.getString().c_str());
|
||||
// If successful (code 200), read the response body and parse the IP address
|
||||
String response = http.getString();
|
||||
StaticJsonDocument<200> doc;
|
||||
deserializeJson(doc, response);
|
||||
const char* ip = doc["ip"]; // Extract the IP address
|
||||
ipAddress = strdup(ip);
|
||||
}
|
||||
} else {
|
||||
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#include <ESP8266WiFiSTA.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
|
||||
|
||||
class Connectivity {
|
||||
|
@@ -4,11 +4,12 @@ void setup() {
|
||||
//connect to internet and start sensor
|
||||
connectivity.connectWiFi(ssid, pass);
|
||||
sensorManager.sensorSetup();
|
||||
Serial.begin(9600);
|
||||
Serial.begin(115200);
|
||||
Serial.println("startup");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SensorManager::eulerAngles eulerRotation = sensorManager.getEulerAngles();
|
||||
SensorManager::RotationQuaternions Rotation = sensorManager.getQuaternions();
|
||||
// SensorManager::acceleration rotationAcceleration = sensorManager.getAcelleration();
|
||||
|
||||
struct acceleration {
|
||||
@@ -18,9 +19,10 @@ struct acceleration {
|
||||
} accelData;
|
||||
|
||||
if (!ipAquired) {
|
||||
serverIp = connectivity.fetchIPAddress();
|
||||
serverIp = connectivity.fetchIPAddress(); // Assign the value here
|
||||
ipAquired = true;
|
||||
}
|
||||
|
||||
unsigned long lastTime = 0; // will store the last time the code was run
|
||||
unsigned long currentTime = millis();
|
||||
if (currentTime - lastTime >= 100) { // 100 ms has passed
|
||||
@@ -29,15 +31,17 @@ struct acceleration {
|
||||
buffer,
|
||||
"{\"deviceId\": %d, \"rotationX\": %f, \"rotationY\": %f, \"rotationZ\": %f, \"accelerationX\": %f, \"accelerationY\": %f, \"accelerationZ\": %f, \"type\": %s}",
|
||||
DEVICE_ID,
|
||||
eulerRotation.roll,
|
||||
eulerRotation.pitch,
|
||||
eulerRotation.yaw,
|
||||
accelData.x,
|
||||
Rotation.i,
|
||||
Rotation.j,
|
||||
Rotation.k,
|
||||
Rotation.w,
|
||||
accelData.y,
|
||||
accelData.z,
|
||||
"data");
|
||||
// %d = int, %f = floatation, %s = string
|
||||
connectivity.httpPost("192.168.137.30", "/", 3445, buffer, strlen(buffer), "application/json");
|
||||
connectivity.httpPost(serverIp, "/", 3445, buffer, strlen(buffer), "application/json");
|
||||
Serial.println(serverIp);
|
||||
Serial.println(buffer);
|
||||
lastTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
@@ -22,14 +22,17 @@ public:
|
||||
eulerAngles getEulerAngles();
|
||||
acceleration getAcelleration();
|
||||
bool sensorTap();
|
||||
private:
|
||||
struct RotationQuaternions {
|
||||
|
||||
struct RotationQuaternions {
|
||||
float i;
|
||||
float j;
|
||||
float k;
|
||||
float w;
|
||||
};
|
||||
RotationQuaternions getQuaternions();
|
||||
|
||||
private:
|
||||
|
||||
BNO080 myIMU;
|
||||
};
|
||||
|
||||
|
@@ -8,8 +8,8 @@ Connectivity connectivity;
|
||||
WebSocketsClient webSocket;
|
||||
#define USE_SERIAL Serial
|
||||
|
||||
#define ssid "1235678i"
|
||||
#define pass "12345678"
|
||||
#define ssid "msi 5556"
|
||||
#define pass "abc12345"
|
||||
#define BUFFER_SIZE 1024
|
||||
#define DEVICE_ID 1
|
||||
#define IP_ADDRESS "192.168.137.12"
|
||||
|
1
code/src/Fitbot/.idea/misc.xml
generated
1
code/src/Fitbot/.idea/misc.xml
generated
@@ -22,6 +22,7 @@
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable-v24/ic_launcher_foreground.xml" value="0.25" />
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/big_red_button_gradient.xml" value="0.2555" />
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/border_background.xml" value="0.2475" />
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/border_background_2.xml" value="0.2475" />
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/border_background_3.xml" value="0.2475" />
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/box_background.xml" value="0.2555" />
|
||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/darkred_button_gradient.xml" value="0.346" />
|
||||
|
@@ -13,6 +13,8 @@ public class EndScreenActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_end_screen);
|
||||
|
||||
NavigationManager.hideSystemUI(this);
|
||||
|
||||
NavigationManager.setupButtonNavigation(this, R.id.homeButtonEndScreen, MainActivity.class);
|
||||
NavigationManager.setupButtonNavigation(this, R.id.startButtonEndScreen, FitnessActivity.class);
|
||||
}
|
||||
|
@@ -2,11 +2,17 @@ package com.example.fitbot.ui.activities;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.VideoView;
|
||||
|
||||
@@ -53,7 +59,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
|
||||
private static final float SENSOR_SAMPLE_RATE = 10.0f;
|
||||
private static final int EXERCISE_COUNT = 5;
|
||||
private static int EXERCISE_REP = 10;
|
||||
private static int EXERCISE_REP = 1;
|
||||
private static final float EXERCISE_SPEED_MULTIPLIER = 1.0f;
|
||||
|
||||
@Override
|
||||
@@ -67,6 +73,13 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
this.exerciseShortDescriptionTextView = findViewById(R.id.textViewFitnessShortDescription);
|
||||
//this.exerciseDescriptionTextView = findViewById(R.id.textViewDialogDescription);
|
||||
|
||||
// Set the repetition count for the exercise
|
||||
EXERCISE_REP = 1;
|
||||
|
||||
// Set color of loading circle
|
||||
ProgressBar loadingCircle = findViewById(R.id.loadingCircle);
|
||||
loadingCircle.setIndeterminateTintList(ColorStateList.valueOf(Color.RED));
|
||||
|
||||
// Navigation Buttons
|
||||
NavigationManager.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class);
|
||||
NavigationManager.setupButtonNavigation(this, R.id.skipButtonFitness, MainActivity.class); //Needs to skip exercises once those are implemented
|
||||
@@ -99,7 +112,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
exerciseStatusElement.post(() -> {
|
||||
this.fetchExerciseAsync((exercise) -> {
|
||||
// Acquire paths from the exercise and provide them to the motion processor
|
||||
Vector3f[][] vectors = new Vector3f[][]{exercise.leftPath.getAngleVectors(), exercise.rightPath.getAngleVectors()};
|
||||
Vector3f[][] vectors = new Vector3f[][]{exercise.leftPath.getVectors(), exercise.rightPath.getVectors()};
|
||||
|
||||
motionProcessor = new InputProcessor(vectors, exercise.exerciseTimeInSeconds, SENSOR_SAMPLE_RATE);
|
||||
|
||||
@@ -126,7 +139,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
public void fetchExerciseAsync(Exercise.ExerciseFetchHandler onSuccessfulFetch, Exercise.ExerciseFetchHandler onFailedFetch) {
|
||||
// For some stupid reason we cannot perform network operations on the main thread.
|
||||
// therefore we'll have to do it like this...
|
||||
(new Thread(() -> {
|
||||
new Thread(() -> {
|
||||
Exercise exercise = ExerciseManager.fetchExerciseFromDatabase();
|
||||
if (exercise == null) {
|
||||
onFailedFetch.handle(null);
|
||||
@@ -142,14 +155,28 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
VideoView videoView = findViewById(R.id.videoView);
|
||||
playVideo(videoView, this);
|
||||
|
||||
// Set a listener to repeat the video
|
||||
while (EXERCISE_REP > 1) {
|
||||
videoView.setOnCompletionListener(mp -> videoView.start()); // start the video again);
|
||||
EXERCISE_REP--;
|
||||
}
|
||||
// When the video has started playing remove the loading circle
|
||||
videoView.setOnInfoListener((mp, what, extra) -> {
|
||||
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
|
||||
ProgressBar loadingCircle = findViewById(R.id.loadingCircle);
|
||||
loadingCircle.setVisibility(View.GONE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
@Override
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
if (EXERCISE_REP < EXERCISE_COUNT) {
|
||||
videoView.start(); // start the video again
|
||||
EXERCISE_REP++;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})).start();
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,7 +185,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
* @param videoView The VideoView to play the video in
|
||||
* @param context The context to use
|
||||
*/
|
||||
public static void playVideo(VideoView videoView, Context context) {
|
||||
public void playVideo(VideoView videoView, Context context) {
|
||||
// Set up the video player
|
||||
if (videoView != null) {
|
||||
videoView.setVideoPath(exerciseVideoUrl);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/lightBlue" />
|
||||
<stroke android:width="2dp" android:color="#FF0000" />
|
||||
<stroke android:width="2dp" android:color="#FFFFFF" />
|
||||
<corners android:radius="20dp" />
|
||||
</shape>
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/midBlue" />
|
||||
<stroke android:width="2dp" android:color="#FF0000" />
|
||||
<stroke android:width="2dp" android:color="#FFFFFF" />
|
||||
<corners android:radius="10dp" />
|
||||
</shape>
|
@@ -12,7 +12,7 @@
|
||||
android:layout_height="450dp"
|
||||
android:layout_marginStart="80dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="@drawable/border_background_2"
|
||||
android:background="@drawable/border_background"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -24,7 +24,7 @@
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:orientation="vertical"
|
||||
android:paddingVertical="15dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
@@ -40,11 +40,11 @@
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="700dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -60,11 +60,11 @@
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="700dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@@ -11,140 +11,138 @@
|
||||
tools:openDrawer="start">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="450dp"
|
||||
android:layout_height="450dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="@drawable/border_background_2"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.505"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="410dp"
|
||||
android:layout_height="410dp"
|
||||
android:layout_marginVertical="20dp"
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:layout_gravity="center">
|
||||
<android.support.v7.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerInParent="true"
|
||||
app:cardCornerRadius="20dp">
|
||||
|
||||
<VideoView
|
||||
android:id="@+id/videoView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/loadingPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center" >
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loadingCircle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:progressTint="@color/white"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/infoButtonFitness"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/red_button_gradient"
|
||||
android:drawableTop="@drawable/ic_baseline_info_40"
|
||||
android:drawableTint="@color/white"
|
||||
android:padding="2.5dp"
|
||||
android:layout_margin="10dp"
|
||||
android:padding="5dp"
|
||||
tools:ignore="SpeakableTextPresentCheck" />
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="300dp"
|
||||
android:layout_height="300dp"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginTop="50dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_marginBottom="50dp"
|
||||
card_view:cardCornerRadius="30dp">
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<VideoView
|
||||
android:id="@+id/videoView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
<LinearLayout
|
||||
android:layout_width="450dp"
|
||||
android:layout_height="450dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
</RelativeLayout>
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessTitle"
|
||||
style="@style/TextStyleTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:text="@string/title"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="410dp"
|
||||
android:layout_height="410dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginVertical="20dp"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginRight="30dp"
|
||||
android:padding="10dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_margin="10dp"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessTitle"
|
||||
style="@style/TextStyleTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title"
|
||||
android:textAlignment="center"
|
||||
android:layout_gravity="center_horizontal" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:padding="5dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessShortDescription"
|
||||
style="@style/TextStyleDesc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/context"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:padding="5dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessBar"
|
||||
style="@style/TextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/context"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:padding="5dp"
|
||||
android:layout_margin="5dp"
|
||||
android:layout_gravity="center_horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessScore"
|
||||
style="@style/TextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/context"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
android:id="@+id/textViewFitnessShortDescription"
|
||||
style="@style/TextStyleDesc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/context"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_margin="10dp"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessReps"
|
||||
style="@style/TextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/context"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_margin="10dp"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFitnessScore"
|
||||
style="@style/TextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/context"
|
||||
android:textAlignment="center" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.example.fitbot.ui.components.ExerciseStatusElement
|
||||
android:id="@+id/personalMotionPreviewElement"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/homeButtonFitness"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="75dp"
|
||||
android:layout_marginStart="200dp"
|
||||
android:layout_marginStart="175dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:background="@drawable/red_button_gradient"
|
||||
android:drawableTop="@drawable/ic_baseline_home_48"
|
||||
@@ -158,7 +156,7 @@
|
||||
android:id="@+id/skipButtonFitness"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="75dp"
|
||||
android:layout_marginEnd="200dp"
|
||||
android:layout_marginEnd="175dp"
|
||||
android:layout_marginBottom="30dp"
|
||||
android:background="@drawable/red_button_gradient"
|
||||
android:drawableTop="@drawable/ic_baseline_skip_next_48"
|
||||
@@ -168,13 +166,4 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:ignore="SpeakableTextPresentCheck" />
|
||||
|
||||
<com.example.fitbot.ui.components.ExerciseStatusElement
|
||||
android:id="@+id/personalMotionPreviewElement"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
@@ -28,7 +28,7 @@
|
||||
android:layout_height="450dp"
|
||||
android:layout_marginStart="80dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="@drawable/border_background_2"
|
||||
android:background="@drawable/border_background"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -40,10 +40,9 @@
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:orientation="vertical"
|
||||
android:paddingVertical="15dp"
|
||||
android:paddingHorizontal="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
@@ -56,11 +55,11 @@
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="700dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@@ -76,11 +75,11 @@
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="700dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/border_background"
|
||||
android:background="@drawable/border_background_3"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@@ -15,6 +15,7 @@
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:src="@drawable/robot_logo"
|
||||
android:tint="@color/white"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
@@ -24,7 +25,7 @@
|
||||
android:layout_marginTop="60dp"
|
||||
android:text="FitBot"
|
||||
android:textSize="48sp"
|
||||
android:textColor="@color/darkBlue"
|
||||
android:textColor="@color/white"
|
||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
@@ -26,7 +26,7 @@
|
||||
</style>
|
||||
|
||||
<style name="TextStyleDesc">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textSize">20sp</item>
|
||||
<item name="android:textColor">#FFFFFF</item>
|
||||
<item name= "android:textStyle">bold</item>
|
||||
<item name="android:padding">6dp</item>
|
||||
|
37
docs/documentation/android/pepper_handling.md
Normal file
37
docs/documentation/android/pepper_handling.md
Normal file
@@ -0,0 +1,37 @@
|
||||
## Pepper Handling
|
||||
|
||||
---
|
||||
|
||||
To make the handling of the Pepper robot easier, we've made some classes
|
||||
that can be used to interact with the robot.
|
||||
The classes associated with the Pepper robot interaction are located in the
|
||||
`com.example.fitbot.pepper` package. To start interacting with the Pepper robot,
|
||||
one must assign a `QiContext` first. This can be done by calling `Pepper.provideQiContext(QiContext context)`
|
||||
method. This method takes a `QiContext` object as a parameter. This object is used to interact with the robot.
|
||||
|
||||
To make the robot talk, one can call the following method:
|
||||
```java
|
||||
Pepper.say(String text);
|
||||
```
|
||||
|
||||
To make the robot execute an animation, one can call the following method:
|
||||
```java
|
||||
Pepper.animate(String animationName);
|
||||
```
|
||||
|
||||
To make the robot do more sophisticated things, one can call the
|
||||
```java
|
||||
Pepper.addToEventQueue(AbstractPepperActionEvent event);
|
||||
```
|
||||
This adds the provided event to the event queue. The event will be executed in the order it was added.
|
||||
Whenever there's no valid QiContext available to use, the event will maintain in the queue until one is
|
||||
provided.
|
||||
|
||||
*Note* All Pepper action events are added to a queue, and executed synchronously. This means
|
||||
that if the robot is still busy with a task, adding a new event to the queue will not do anything until
|
||||
the robot is done with the current task.
|
||||
|
||||
Currently, the only supported actions are:
|
||||
|
||||
- `PepperSpeechEvent` - This event makes the robot say something.
|
||||
- `PepperAnimationEvent` - This event makes the robot execute an animation.
|
@@ -1,108 +1,60 @@
|
||||
## Motion Tracking System
|
||||
## Motion Tracking System -- Pepper
|
||||
|
||||
---
|
||||
|
||||
To capture the user's motion with the sensing devices, we'll need to use a tracking system that calculates the
|
||||
path the user makes to be able to determine the user's position and orientation, and therefore whether the movement
|
||||
that was made correlates to the provided path.
|
||||
This is done by some calculations in the `MotionProcessor` class. To get started, create an instance of the `MotionProcessor` class and call the `processMotion` method with the `MotionData` object as a parameter. This will return a `MotionResult` object that contains the calculated path.
|
||||
### Introduction
|
||||
|
||||
The robot motion tracking system is a system that allows the robot to track the user's motion and provide feedback
|
||||
based on the user's motion. The system consists of a Web Server, which actively listens for incoming data from the
|
||||
two ESP8266 modules. The ESP8266 modules are connected to the robot and are responsible for tracking the user's motion.
|
||||
These sensors send rotation data to the Web Server, which can then be parsed and used to provide feedback to the user.
|
||||
|
||||
### System Architecture
|
||||
|
||||
The system consists of three main components: the Web Server, the ESP8266 modules, and the Pepper robot. The Web Server
|
||||
is responsible for receiving data from the ESP8266 modules and processing it. The ESP8266 modules are responsible for
|
||||
sending rotation data to the web server, which is then parsed.
|
||||
|
||||
### Parsing Data
|
||||
|
||||
To parse the data received by the web server, one must utilize the class `InputProcessor`. This class is responsible for
|
||||
both starting the server and processing data received by the server. To start parsing data, one can do the following:
|
||||
```java
|
||||
// create the motion processor
|
||||
MotionProcessor motionProcessor = new MotionProcessor();
|
||||
|
||||
InputProcessor processor = new InputProcessor();
|
||||
processor.startListening(); // This starts the web server.
|
||||
|
||||
```
|
||||
|
||||
To start listening for input, one must call the following method:
|
||||
|
||||
To parse data received by the server, one can register an event listener with the `InputProcessor` class. This event listener
|
||||
will be called whenever new data is received by the server. To register an event listener, one can do the following:
|
||||
```java
|
||||
// start listening for input
|
||||
motionProcessor.startListening();
|
||||
|
||||
processor.setInputHandler(new IInputHandler() {
|
||||
@Override
|
||||
public void accept(Vector3f rotationVector, int sensorId) {
|
||||
// Do something with the input.
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
Calling this function creates a WebSocket server, which the sensing devices can connect to.
|
||||
The `MotionProcessor` class will then start listening for a set of messages that start with specified kind of keywords.
|
||||
The messages always start with the keyword, separated by a space, and then the data is sent.
|
||||
The default data separator is `;`.
|
||||
An example of the message format is shown below:
|
||||
### Providing Feedback
|
||||
|
||||
If one wants to provide feedback to the user, one must first provide an exercise to the `InputProcessor` object.
|
||||
This can be done by calling the `setExercise(Exercise exercise)` method. This method takes an `Exercise` object as a parameter.
|
||||
This object contains information about the exercise, such as the name of the exercise, the muscle group it targets, and the
|
||||
video associated with the exercise. One can then check the status of the current exercise by calling one of the following
|
||||
methods:
|
||||
```java
|
||||
// Sending data
|
||||
"data accelerationX;accelerationY;accelerationZ;rotationX;rotationY;rotationZ" // all values are floats
|
||||
processor.getCurrentProgress(); // Returns the current progress of the exercise as a scalar (0 - 1)
|
||||
|
||||
// Changing the sample rate
|
||||
"sampleRate rate" // rate is an integer
|
||||
processor.getError(int sensorId, float time); // Get the error offset for a given sensor at a given time
|
||||
|
||||
// Calibrating the zero point
|
||||
"zero x;y;z" // x, y, z are floats
|
||||
```
|
||||
processor.getAverageError(int sensorId); // Get the average error for a given sensor
|
||||
|
||||
To add a custom message received handler, one can simply call the following method:
|
||||
processor.secondsPassed(); // Get the number of seconds that have passed since the exercise started
|
||||
|
||||
```java
|
||||
// Add a custom message handler
|
||||
motionProcessor.setMotionDataEventHandler((Vector3 vector) -> { ... });
|
||||
```
|
||||
*Note: The message handler provides a vector as a parameter; this vector is already converted from relative acceleration and rotation.*
|
||||
processor.hasFinished(); // Check if the exercise has finished
|
||||
|
||||
### Error checking
|
||||
|
||||
To check whether the made movements correlate with a given path, one must check for their differences.
|
||||
This can be done by a few implemented methods:
|
||||
|
||||
***Get the error of a vector compared to a path***
|
||||
```java
|
||||
GesturePath path = new GesturePath.Builder()
|
||||
.addVector(...)
|
||||
.build();
|
||||
|
||||
Vector3 referencePoint = new Vector3(...);
|
||||
double error = motionProcessor.getError(path, referencePoint);
|
||||
```
|
||||
|
||||
***Get the average error of a computed path to a `GesturePath`***
|
||||
```java
|
||||
GesturePath path = new GesturePath.Builder()
|
||||
.addVector(...)
|
||||
.build();
|
||||
|
||||
double error = motionProcessor.getAverageError(path);
|
||||
```
|
||||
|
||||
***Get a list of error values from a computed path to a `GesturePath`***
|
||||
```java
|
||||
GesturePath path = new GesturePath.Builder()
|
||||
.addVector(...)
|
||||
.build();
|
||||
|
||||
List<Double> errorList = motionProcessor.getErrors(path);
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
An example of how to use a motion tracking system is shown below:
|
||||
|
||||
```java
|
||||
|
||||
// create the motion processor
|
||||
MotionProcessor motionProcessor = new MotionProcessor();
|
||||
|
||||
// Create a gesture path
|
||||
GesturePath.Builder pathBuilder = new GesturePath.Builder();
|
||||
|
||||
for ( int i = 0; i < 100; i++ )
|
||||
pathBuilder.addVector(new Vector3(i, i, i));
|
||||
|
||||
GesturePath path = pathBuilder.build();
|
||||
|
||||
// Set the path
|
||||
for ( int i = 0; i < 100; i++ ) {
|
||||
motionProcessor.addMotionData(new MotionData(i, i, i, i, i, i));
|
||||
}
|
||||
|
||||
// Get error values
|
||||
List<Double> errorList = motionProcessor.getErrors(path);
|
||||
|
||||
// Get average error
|
||||
double averageError = motionProcessor.getAverageError(path);
|
||||
|
||||
// Now you can do whatever you want with these results.
|
||||
```
|
@@ -1,55 +1,73 @@
|
||||
# Infrastructure UML
|
||||
|
||||
---
|
||||
|
||||
The design for our project can be represented by the diagram below.
|
||||
|
||||
A simple linguistic representation of the diagram is as follows:
|
||||
|
||||
We have a Raspberry Pi, which runs a NodeJS server to handle all incoming requests.
|
||||
This server is connected to a MariaDB database, which stores all the exercise data.
|
||||
This data can then be received from the application we built for the Pepper robot.
|
||||
We also have two ESP8266 modules, which are connected to the Pepper robot's Web Server.
|
||||
These modules record angular motion via gyroscopes, and send this data to the web server on the Pepper robot.
|
||||
The web server is a requirement to receive incoming data from the sensors, due to the ESP's not having a
|
||||
dedicated bluetooth chip to communicate with the Pepper robot.
|
||||
The parsed data on the application can then be shown to the user with some feedback regarding their performance.
|
||||
|
||||
``` mermaid
|
||||
classDiagram
|
||||
|
||||
Raspberry pi --> NodeJS
|
||||
Raspberry pi --> Database
|
||||
NodeJS --> Androidapp : getExerciseData (Wifi, Rest API)
|
||||
Raspberry Pi --> NodeJS
|
||||
Raspberry Pi --> Database
|
||||
NodeJS <--> Android Application : Request exercise data from database
|
||||
Database <--> NodeJS : Database queries
|
||||
NodeJS --> ESP8266
|
||||
|
||||
ESP8266 --> Androidapp : getRotationalData (Wifi)
|
||||
|
||||
ESP8266 --> Android Application : Send rotation data via WiFi to\n Pepper Web Server
|
||||
namespace Server {
|
||||
class Raspberry pi {
|
||||
class Raspberry Pi {
|
||||
+MariaDB
|
||||
+Apache2
|
||||
+NodeJS
|
||||
Database()
|
||||
Webserver()
|
||||
|
||||
Database
|
||||
Webserver
|
||||
}
|
||||
|
||||
class Database {
|
||||
+ExerciseID
|
||||
+ExerciseName
|
||||
+ExerciseShortDesc
|
||||
+ExerciseDescription
|
||||
+ExerciseVideo
|
||||
+GyroCoordinates
|
||||
+ExerciseImage
|
||||
+GyroVectors
|
||||
+MuscleGroup
|
||||
}
|
||||
|
||||
class NodeJS {
|
||||
+MariaDB
|
||||
GetRandomExercise()
|
||||
PassIpAddress()
|
||||
+Handle requests
|
||||
}
|
||||
}
|
||||
|
||||
namespace Pepper {
|
||||
class Androidapp {
|
||||
class Android Application {
|
||||
+Java
|
||||
+Android SDK
|
||||
+QiSDK
|
||||
+WebServer
|
||||
+Acquire rotation data from sensors
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Hardware {
|
||||
class ESP8266{
|
||||
+RotationalX
|
||||
+RotationalY
|
||||
+RotationalZ
|
||||
Gyroscope()
|
||||
+RotationX
|
||||
+RotationY
|
||||
+RotationZ
|
||||
Send rotation data to Web Server
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@@ -0,0 +1,88 @@
|
||||
## Pepper Abstraction Design
|
||||
|
||||
---
|
||||
|
||||
### Introduction
|
||||
|
||||
The Pepper robot is a complex system that can be controlled by a variety of different actions. To make the system more
|
||||
manageable, we've decided implement abstraction and encapsulation in the classes related to Pepper controls.
|
||||
This way, we can easily add new action events in the future.
|
||||
All these classes inherit from the `AbstractPepperActionEvent` class.
|
||||
|
||||
### Problems
|
||||
|
||||
1. The Pepper robot functions with a system that only allows one action to be executed at a time, per action category.
|
||||
This means that, for example, when two speech actions are executed at the same time, the application will crash due
|
||||
to a `RuntimeException` being thrown. Due to this fact, whenever the execution of multiple processes overlap,
|
||||
the application will crash.
|
||||
|
||||
2. Besides the first problem, for the Pepper robot to be able to execute any actions, it is required to have a
|
||||
QiContext available. This context is only provided in a class that extends the `RobotLifecycleCallbacks` class.
|
||||
This means, that whenever the class does not extend this class, the robot will be unable to execute any actions.
|
||||
|
||||
### Solution
|
||||
|
||||
To prevent the application from crashing, we've decided to implement a queue system in the `Pepper` class.
|
||||
This system allows us to queue any new actions that need to be executed whenever another action is already
|
||||
being executed. This way, we can prevent the application throwing a `RuntimeException` and thus crashing.
|
||||
|
||||
To tackle the second problem, we've decided to implement a system where the Pepper class has a global variable, which
|
||||
holds the current QiContext. This means, that whenever a user decides to execute an action, and no current QiContext
|
||||
is available, the action will be queued until a QiContext is available. This means that we can queue several actions
|
||||
at once without any exceptions being thrown.
|
||||
|
||||
### Diagrams
|
||||
|
||||
#### Class Diagram
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Pepper {
|
||||
-pepperActionEventQueue : ConcurrentLinkedQueue<AbstractPepperActionEvent>
|
||||
-isAnimating : AtomicBoolean
|
||||
-isSpeaking : AtomicBoolean
|
||||
|
||||
+latestContext : QiContext
|
||||
+addToEventQueue(AbstractPepperActionEvent event)
|
||||
+provideQiContext(QiContext context)
|
||||
|
||||
-processEventQueue()
|
||||
}
|
||||
class AbstractPepperActionEvent {
|
||||
+getAction() EPepperAction
|
||||
}
|
||||
class PepperSpeechEvent {
|
||||
+phrase : String
|
||||
+locale : Locale
|
||||
+PepperSpeechEvent(String phrase, Locale locale)
|
||||
+getSay(QiContext context) Say
|
||||
}
|
||||
class PepperAnimationEvent {
|
||||
+PepperAnimationEvent(String animationName)
|
||||
+PepperAnimationEvent(String animationName, IAnimationCompletedListener listener)
|
||||
+getAnimation(QiContext context) Animate
|
||||
+animationName : String
|
||||
+IAnimationCompletedListener : IAnimationCompletedListener
|
||||
}
|
||||
Pepper <|-- AbstractPepperActionEvent
|
||||
PepperSpeechEvent <|-- AbstractPepperActionEvent
|
||||
PepperAnimationEvent <|-- AbstractPepperActionEvent
|
||||
```
|
||||
|
||||
#### Queue System in Pepper class
|
||||
|
||||
```mermaid
|
||||
|
||||
graph LR
|
||||
subgraph "Pepper Class - Action Queue System"
|
||||
speak[say(String phrase)\nPublic\nCreate PepperSpeechEvent] --Call method--> addQueue
|
||||
animate[animate(String animationName)\nPublic\nCreate PepperAnimationEvent] --Call method--> addQueue
|
||||
addQueue[addToEventQueue(AbstractPepperActionEvent event)\nPublic\nAdd provided event to event queue] --Add to queue--> queue[Event Queue\nPrivate\nQueue containing all events that\nneed to be executed]
|
||||
|
||||
addQueue --Call method--> handleQueue[processEventQueue()\nPrivate\nCheck whether there is a context\navailable, and whether an event\nis currently being executed.\nExecutes the next event in the Queue]
|
||||
|
||||
queue <.-> handleQueue
|
||||
|
||||
provideCtx[provideQiContext(QiContext context)\nPublic\nSets global QiContext variable\nto provided context. If the context \nis not null,process the event queue] --Sets global QiContext variable--> handleQueue
|
||||
end
|
||||
```
|
@@ -1,9 +0,0 @@
|
||||
|
||||
## Expert review #1
|
||||
|
||||
### Document as you go
|
||||
Documenteer alle problemen die voorkomen bij het project en noteer de
|
||||
oplossingen voor deze problemen. Dit kan bijvoorbeeld d.m.v. een command die
|
||||
cache files verwijderd, of op welke manier je een project fixt. Dit kan toekomstige
|
||||
problemen voorkomen.
|
||||
|
48
docs/personal-documentation/Luca/expert-review.md
Normal file
48
docs/personal-documentation/Luca/expert-review.md
Normal file
@@ -0,0 +1,48 @@
|
||||
K1 - Object-Oriented Programming
|
||||
|
||||
---
|
||||
|
||||
In alle classen gerelateerd aan de Pepper besturingen wordt er gebruik gemaakt
|
||||
van abstractie en encapsulatie.
|
||||
Zie:
|
||||
- `PepperAnimationEvent`
|
||||
- `PepperSpeechEvent`
|
||||
|
||||
Deze classes inheriten `AbstractPepperActionEvent`.
|
||||
|
||||
K2: Gebruikers Test
|
||||
|
||||
( Maak een fictief persoon die de applicatie zou kunnen gebruiken, om erachter te komen
|
||||
wat ze zouden willen )
|
||||
|
||||
---
|
||||
|
||||
Wij hebben gezamenlijk gecommuniceerd over het plan, echter is alleen
|
||||
Niels heengegaan om te communiceren met de gebruikers.
|
||||
We hebben om ons heen mede studenten gevraagd om feedback te geven over onze
|
||||
applicatie, gezien we helaas te weinig informatie hebben verkregen van de
|
||||
actuele gebruiker.
|
||||
|
||||
---
|
||||
|
||||
K3 - Infrastructure UML
|
||||
|
||||
---
|
||||
|
||||
Zie bestand 'infrastructure.md'
|
||||
|
||||
---
|
||||
|
||||
K4 - Ontwerp embedded system
|
||||
|
||||
Documenteer het queue systeem van de Pepper class
|
||||
Maak een mermaid graph LR diagram
|
||||
|
||||
---
|
||||
|
||||
Zie '/documentation/hardware/sensors'
|
||||
|
||||
K5 - Embedded Software Schrijven
|
||||
|
||||
Feedback:
|
||||
- Is in principe K1,
|
@@ -0,0 +1,72 @@
|
||||
### Gebruikersonderzoek Personage
|
||||
|
||||
---
|
||||
|
||||
Gezien de huidige omstandigheden is het nogal lastig om actuele feedback te verkrijgen
|
||||
van onze doelgroep. Dit betekent dat we een fictief karakter moeten ontwikkelen die als onze
|
||||
gebruiker functioneert. Hierbij moeten we zo veel mogelijk parameters vaststellen die
|
||||
overeen kunnen komen met een potentiele gebruiker.
|
||||
|
||||
Om hiermee te beginnen is het noodzakelijk om eerst deze parameters vast te stellen.
|
||||
|
||||
Deze zijn als volgt:
|
||||
|
||||
- Bedraagt een leeftijd van tussen de 50 en 70 jaar
|
||||
- Woont in een verzorgingstehuis
|
||||
- Heeft enigzins last van eenzaamheid
|
||||
- Heeft moeite met lichamelijke activiteiten
|
||||
- Grote kans op slecht zicht
|
||||
|
||||
Nu deze parameters vastgesteld zijn kunnen we een fictief personage ontwikkelen die als onze
|
||||
gebruiker functioneert. Dit personage zal de naam 'Henk' dragen.
|
||||
|
||||
Vervolgens is het handig om de applicatie te introduceren.
|
||||
De applicatie zal als volgt geintroduceerd worden:
|
||||
|
||||
"Onze applicatie is een interactief programma waarmee u samen fitness activiteiten kunt
|
||||
verrichten met een virtuele assistent genaamd Pepper. Pepper zal u begeleiden door de
|
||||
verschillende oefeningen en u helpen met het uitvoeren van de oefeningen. Iedere
|
||||
oefening zal worden begeleid door een stem die u verteld wat u moet doen en hoe u dit
|
||||
moet doen. Daarnaast zal Pepper u ook feedback geven over hoe goed u de oefeningen
|
||||
uitvoert."
|
||||
|
||||
Een fictieve reactie op alle gestelde voorwaarden kan zijn als volgt:
|
||||
|
||||
#### Introductie
|
||||
|
||||
Goedendag, ik ben Henk en ik ben 67 jaar oud. Ik woon al een aantal jaar in verzorgingstehuis genaamd Amstelhuis.
|
||||
Helaas heb ik de laatste tijd wat meer last van mijn gezondheid, waardoor ik minder goed kan bewegen. Hierdoor voel ik
|
||||
me soms wat eenzaam en verveel ik me wel eens.
|
||||
|
||||
Ik ben altijd erg actief geweest, dus toen ik hoorde over de Pepper FitBot app was ik meteen enthousiast. De
|
||||
verpleegster vertelde me dat de Pepper app misschien wel kan helpen om mijn conditie op peil te houden en om me minder
|
||||
eenzaam te voelen. Dus ik ben erg benieuwd wat de FitBot app allemaal kan!
|
||||
|
||||
#### Gebruikservaring
|
||||
|
||||
Eerste indruk: Toen ik de FitBot app voor het eerst gebruikte, vond ik het erg leuk dat Pepper me begeleidde door de
|
||||
oefeningen. Hij is duidelijk en behulpzaam, en hij maakt er een gezellige sfeer van.
|
||||
|
||||
##### Gebruiksgemak
|
||||
De FitBot app is erg gebruiksvriendelijk. De app is eenvoudig te bedienen en de instructies zijn
|
||||
duidelijk. Ook vind ik het fijn dat de app mijn voortgang bijhoudt.
|
||||
|
||||
##### Functionaliteit
|
||||
De FitBot app heeft veel leuke en nuttige functies. Ik vind het vooral leuk dat er verschillende
|
||||
oefeningen zijn voor verschillende niveaus.
|
||||
|
||||
##### Motivatie
|
||||
Pepper is een geweldige motivator. Hij moedigt me aan om door te gaan en hij geeft me complimenten als ik
|
||||
goed bezig ben. Hierdoor ben ik gemotiveerder om te blijven sporten.
|
||||
|
||||
##### Verbeterpunten
|
||||
|
||||
- Het zou leuk zijn als er meer oefeningen aan de app worden toegevoegd. Zo zou ik graag meer oefeningen willen doen voor
|
||||
mijn spierkracht en lenigheid.
|
||||
- De uitleg van de oefeningen is soms een beetje kort. Het zou fijn zijn als deze wat uitgebreider zou zijn.
|
||||
- Het zou leuk zijn als er de mogelijkheid was om samen met anderen te sporten via de app. Zo zou ik bijvoorbeeld met
|
||||
mijn kleinkinderen kunnen videobellen terwijl we allebei dezelfde oefeningen doen.
|
||||
|
||||
Al met al ben ik erg tevreden over de FitBot app. Het is een leuke en effectieve manier om te sporten. Pepper is een
|
||||
fijne motivator en de app heeft veel nuttige functies. Ik zou de FitBot app zeker aanbevelen aan andere mensen in het
|
||||
verzorgingstehuis.
|
61
docs/personal-documentation/Luca/infrastructure-design.md
Normal file
61
docs/personal-documentation/Luca/infrastructure-design.md
Normal file
@@ -0,0 +1,61 @@
|
||||
### Infrastructure Design
|
||||
|
||||
---
|
||||
|
||||
As for our project, we've made the following design choices for our infrastructure.
|
||||
We've decided to implement a NodeJS server on a Raspberry Pi, which will handle the requests for retrieving exercises.
|
||||
This server will communicate with a MariaDB database, which contains the exercise data.
|
||||
The Pepper robot will host a web server, which will handle the incoming rotational data from an ESP8266.
|
||||
This data will then be processed by a motion processor class, `InputProcessor`, which will compare the rotational data
|
||||
to the data of the current exercise and show how well the user is performing.
|
||||
|
||||
Down below is a visual representation of how this infrastructure will look like.
|
||||
|
||||
### General Infrastructure Diagram
|
||||
```mermaid
|
||||
|
||||
graph TB
|
||||
subgraph "Raspberry Pi"
|
||||
server[NodeJS Server\n\nHandles requests for\nretrieving exercises]
|
||||
db[Database - MariaDB\n\nContains exercise data]
|
||||
server --Fetch database entry--> db
|
||||
db --Return retrieved entry--> server
|
||||
|
||||
end
|
||||
|
||||
subgraph "Pepper Robot"
|
||||
webServer[Web Server\n\nHandles incoming rotational data\nfrom ESP8266]
|
||||
motionProcessor[Motion Processor\n\nProcesses rotational data,\ncompares it to the current exercise\nand shows the statistics on the screen]
|
||||
ui[User Interface\n\nShows the current exercise,\nhow to perform it and the\nstatistics of the user's performance]
|
||||
motionProcessor --Send HTTP GET for Exercise--> server
|
||||
server --Send exercise data\nin JSON format--> motionProcessor
|
||||
webServer --Process rotational data--> motionProcessor
|
||||
motionProcessor --Show statistics\non the UI--> ui
|
||||
end
|
||||
|
||||
subgraph "Motion Sensing Device"
|
||||
esp[ESP8266\n\nMeasures sensor data\nand sends it to the web server]
|
||||
gyro[Gyroscope\n\nMeasures rotational data\n(Rx, Ry, Rz)]
|
||||
esp --Send rotational data\nto Pepper Web Server--> webServer
|
||||
gyro <---> esp
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
### Database Diagram
|
||||
|
||||
For the design of our database, we've decided to only add a single table named `Exercise`.
|
||||
This table contains all the information needed for the exercises.
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Exercise {
|
||||
+ExerciseId : INT
|
||||
+Name : VARCHAR
|
||||
+Description : VARCHAR
|
||||
+ShortDescription : VARCHAR
|
||||
+ImageURL : VARCHAR
|
||||
+VideoURL : VARCHAR
|
||||
+MuscleGroup : VARCHAR
|
||||
+Path : VARCHAR
|
||||
}
|
||||
```
|
@@ -1,11 +1,71 @@
|
||||
# Reflectie 3 blokken
|
||||
|
||||
## Blok 1
|
||||
### Blok 1
|
||||
In blok 1 heb ik de professionele skills Persoonlijk leiderschap en Toekomstgericht organiseren. Ik had veel moeite met documenteren en het scrumboard te gebruiken, omdat ik er nog geen ervaring mee had. Ik had op dat moment al het hele project in blokjes opgedeeld voor mezelf en keer daarna nooit meer naar het scrumboard. Door die manier van werken deed ik ook 5 dingen tegelijk waardoor ik af en toe het overzicht kwijtraakte . Ik had als doel opgesteld om in de volgende blokken meer het scrumboard te gaan gebruiken. Mijn aanpak was proberen zelf wat user story’s te maken, zodat ik ook wat meer betrokken was bij het scrumboard. Uiteindelijk heb ik daardoor wel wat meer gebruik gemaakt van het scrumboard, maar ik ging nog wel veel mijn eigen weg. Ik was niet helemaal tevreden met het resultaat, maar de aanpak werkte wel. Wat ik heb geleerd is als ik veel gebruik van iets wil maken moet ik er zelf ook bij betrokken zijn. Volgende keren zorg ik er voor dat ik betrokken ben bij het scrum board wat nu ook moet, waardoor ik meer het scrumboard gebruik.
|
||||
|
||||
## Blok 2
|
||||
### Blok 2
|
||||
In blok 2 gingen we voor het eerst samenwerken in een duo, waarbij we ook deels onze eigen user story’s moesten maken, dat heeft me ook geholpen om door het hele blok heen het scrumboard meer te gebruiken. Communicatie ging over het algemeen in dat blok redelijk goed. Als we vragen aan elkaar hadden werden die gewoon gesteld en als een van ons vastliep hielpen we elkaar. In sprint 2 werden classes aan ons geïntroduceerd waarbij ik best wat moeite had om dat te begrijpen. Dus ik had maar 1 class gemaakt en verder alles in functies gestopt. Pas eind sprint 2 probeerde ik de feedback te verwerken om alles in classes te stoppen, maar omdat je code uiteindelijk zo complex is. Is het bijna onmogelijk om het in classes te stoppen. Waarbij het resultaat was een heel lastig leesbaar programma. Ik was niet tevreden of over het resultaat aan het einde van het blok. Mijn aanpak was bij het volgende blok. Meteen alles in classes maken. Wat uiteindelijk wel goed heeft gewerkt. Ben daardoor ook achter gekomen hoe handig classes zijn en dat ze enorm veel overzicht geven van wat je aan het maken bent.
|
||||
|
||||
## Blok 3
|
||||
### Blok 3
|
||||
In blok 3 stond doelgericht interacteren en persoonlijke leiderschap centraal. Het groepje in blok 3 was te gezellig waardoor we vaak meer zaten te lollen dan we aan het werk waren. Ik had mezelf de taak gegeven om proberen om meer gefocust te werken zonder dat ik afgeleid raakte door mijn groepje. Mijn aanpak was door mezelf af te schermen met een koptelefoon of eventjes ergens anders te gaan zitten, wat ook goed hielp was even een rondje lopen. Op die manier kon ik de laatste sprint heel efficiënt werken en in blok 4 merk ik ook dat die techniek enorm erg helpt met meer gefocust en productief blijven op een dag. Dit resultaat was eigenlijk een beetje laat het liefst deed ik dit al eind sprint 1, zodat ik heel het blok beter kon doorwerken.
|
||||
|
||||
|
||||
## Sterkte zwakte analyse.
|
||||
|
||||
### Toekomstgericht organiseren
|
||||
Een van mijn zwakkere punten is organiseren in een team, want ik heb alles heel snel een plan in mijn hoofd maar dat duidelijk op papier zetten is was lastiger. Daardoor kan je ook minder rekening houden met de product owner van wat ze daadwerkelijk willen. Daarbij lukt me het wel beter om andere mogelijkheden en kansen te zien als we bezig zijn met het project waardoor we ons product kunnen verbeteren.
|
||||
Ethiek is een van mijn sterkere punten als ik iets maak denk ik wel er bij van wat de slechte gevolgen er van kunnen zijn en of het wel handig is om te maken. Ook ben ik me er van bewust dat er grenzen zijn bij het verzamelen van informatie.
|
||||
Procesmanagement is ook een van mijn zwakkere punten maar het is zich langzaam aan het verbeteren. Eerst had ik veel moeite met een planning maken en er voor zorgen dat ik me er aan hield. Nu gaat dat allemaal een stuk beter en merk ik dat ik echt volgens de planning bezig ben. Nu ben ik ook product owner binnen mijn groepje en push ik om een minimal viable product af te hebben voor de sprint 2 review.
|
||||
Ik geef mezelf een score van 3. Vanaf het begin van de opleiding is het al stukken verbeterd, maar er is meer ruimte voor verbetering.
|
||||
|
||||
### Onderzoekend probleemoplossen
|
||||
Een zwak punt van mij is methodische probleemaanpak als het gaat om theoretische vraagstukken. Daarbij heb ik veel moeite met het belangrijkste er uit halen en het onder te verdelen in hoofd en bijzaken. Als het praktisch is gaat het een stuk makkelijker en heb ik heel snel een beeld van de hoofd en bijzaken en welke kennis er nog ontbreekt.
|
||||
Met onderzoek heb ik nog wel moeite, over het algemeen heb ik moeite met Nederlands en merk ik zelf dat ik af en toe 3 keer een zin moet lezen totdat ik weet wat er staat. Het onderscheiden van meningen en feiten heb ik minder moeite mee en de betrouwbaarheid van een bron kan ik er redelijk snel uithalen.
|
||||
In oplossingen zoeken ben ik redelijk goed in. Ik kan kritisch zijn op mezelf en anderen en geef vaak suggesties over wat beter kan. Of als iets op een andere manier kan. Ook ben ik goed in het bedenken van nieuwe oplossingen op problemen.
|
||||
Ik geef mezelf nu een score van 2.5, omdat ik nog niet heel goed ben in teksten en formuleren.
|
||||
|
||||
### Persoonlijk leiderschap
|
||||
Ik denk dat ondernemend zijn een sterkte punt van mij is. Ik ga snel dingen uit mezelf doen en als iets me niet lukt probeer ik het nog steeds zelf uit te vogelen anders vraag ik om hulp. Bij beslissingen probeer ik instemmingen van het hele groepje er bij te krijgen. Ook als niemand de leiding in het groepje heeft of er gebeurt niks pak ik snel de leiding om nog proberen iets af te kunnen krijgen.
|
||||
Persoonlijke ontwikkeling is een sterk punt van mij. Ik weet waar ik goed en slecht in ben en ik reflecteer vaak om mijn acties en wat ik doe en wat misschien beter kon. Ik probeer me mee te leven met anderen en hun ideeën. Ook ben ik mij bewust van de consequenties die mijn acties kunnen hebben.
|
||||
Ik heb nog wel moeite met persoonlijke profilering, omdat ik heel snel een rol pak waar ik mij comfortabel bij voel en niet een rol pak dat uitdagender is waarbij ik veel meer leer. Daarentegen weet ik wel heel goed wat ik wil leren en welke kennis ik nog zou willen oppakken. Ook geef ik aan mijn teamgenoten aan waar ik goed en slecht in ben, zodat we makkelijk en beter taken kunnen verdelen als we in tijdnood zitten.
|
||||
Over het algemeen geef ik persoonlijke leiderschap 3.6 punten. Ik moet nog werken aan meer uitdaging zoeken, maar verder gaat het goed op dit vlak.
|
||||
|
||||
### Doelgericht interacteren
|
||||
Ik ben redelijk goed met rekening houden met opdrachtgevers en vraag vaak aan feedback van wat ze willen en laat ze ook zien tussen het project wat we hebben.
|
||||
In communiceren ben ik goed en slecht. Ik kan goed actief luisteren en rekening houden met iemands gevoelens. Ook kan ik mijn meningen logisch onderbouwen. Het gedeelte waar ik af en toe nog moeite mee heb ik begrijpelijk kunnen spreken en woord volgorde.
|
||||
Met samenwerken ben ik redelijk goed. Ik kan goed afspraken maken en die nakomen, bijvoorbeeld dat we samen eerder naar school komen om iets af te krijgen. We werken samen naar een oplossing en helpen elkaar waar nodig is.
|
||||
Ik geef met doelgericht interacteren mezelf 4 punten, omdat het samenwerken elk blok tot nu toe goed is gegaan en ik ook producten naar wens de laatste blokken heb opgeleverd.
|
||||
|
||||
|
||||
## SMART Leerdoelen
|
||||
### Toekomstgericht organiseren
|
||||
Specifiek:
|
||||
Ik wil leren hoe ik plannen beter op papier kan zetten, zodat mijn team ook inzicht heeft in mijn ideeën voor het project.
|
||||
Meetbaar:
|
||||
Ik zal bij de eerste sprint een gestructureerd uitgewerkt plan hebben voor mijn team, zodat ze allemaal op de hoogste zijn van mijn ideeën en zodat we dingen makkelijk kunnen afstemmen.
|
||||
Acceptabel:
|
||||
Het is realistisch, want ik heb al stappen gezet om het te verbeteren en ik wil kijken hoe goed dit gaat werken.
|
||||
Tijdgebonden:
|
||||
Ik zal dit doen komend blok, waarbij ik aan het begin van de eerste sprint werk aan een plan die ik kan zien aan mijn teamgenoten waarbij ik mijn visie van het project kan laten zien.
|
||||
|
||||
### Onderzoekend probleemoplossen
|
||||
Specifiek: Verbeter mijn methodische probleemaanpak bij theoretische vraagstukken en mijn begrip van teksten in het Nederlands.
|
||||
Meetbaar: Ik wil mijn vaardigheden verhogen van het huidige niveau naar een hoger niveau waarbij ik complexe vraagstukken gestructureerd en kritisch aanpak.
|
||||
Acceptabel: Dit doel is belangerijk voor mijn leerproces en zal me helpen om beter en efficiënter te zijn bij onderzoekend probleem oplossen.
|
||||
Realistisch: Ik zal gerichte inspanningen leveren om mijn vaardigheden te verbeteren, bijvoorbeeld door meer te oefenen met theoretische vraagstukken en actief te werken aan mijn taalvaardigheid.
|
||||
Tijdgebonden: Ik wil dit doel bereiken voordat het half jaar project volgend jaar over is.
|
||||
|
||||
### Persoonlijk leiderschap
|
||||
Specifiek: Binnen zes maanden wil ik mijn persoonlijke leiderschapsvaardigheden versterken door minstens drie keer een uitdagende rol binnen teamprojecten op me te nemen en hierin actief te werken aan nieuwe vaardigheden.
|
||||
Meetbaar: Ik zal na elk project een reflectieverslag schrijven en feedback vragen aan ten minste twee teamleden om mijn voortgang te meten. Mijn succescriteria zijn het succesvol voltooien van deze rollen en positieve feedback van teamleden over mijn leiderschapskwaliteiten.
|
||||
Acceptabel: Ik ben bereid tijd en moeite te investeren in deze uitdaging omdat het essentieel is voor mijn professionele groei en het behalen van mijn carrièredoelen.
|
||||
Realistisch: Met mijn huidige competenties en de beschikbare tijd kan ik deze uitdagende rollen aannemen en succesvol voltooien. Ik heb al bewezen initiatief en leiderschap te kunnen tonen.
|
||||
Tijdsgebonden: Ik zal dit doel bereiken door elke twee maanden een nieuw teamproject met een uitdagende rol af te ronden, wat resulteert in drie uitdagende projecten binnen zes maanden.
|
||||
|
||||
### Doelgericht interacteren
|
||||
Specifiek: Binnen drie maanden wil ik mijn bijdragen aan daily standup-meetings verbeteren door elke dag een duidelijke update te geven over mijn voortgang, obstakels en plannen, en door actief feedback te vragen en te geven.
|
||||
Meetbaar: Ik zal elke dag kijken of de daily standup gedaan word. En daarbij elke werkdag mijn bijdrage leveren
|
||||
Acceptabel: Dit zorgt er voor dat de samenwerking uiteindelijk beter word en dat iedereen elkaar sneller helpt met dingen
|
||||
Realistisch: Dit is realistisch want het is iets kleins van 10 min elke dag.
|
||||
Tijdsgebonden: Ik zal dit doel bereiken voor het halfjaar project over is
|
||||
|
||||
|
Reference in New Issue
Block a user