Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66
This commit is contained in:
@@ -23,6 +23,7 @@ void Connectivity::connectWiFi(char* ssid, char* pass){
|
|||||||
const char* getServerURL = "http://145.92.8.132:443/get-ip";
|
const char* getServerURL = "http://145.92.8.132:443/get-ip";
|
||||||
String ipAddress = ""; // string that will hold the server's IP address
|
String ipAddress = ""; // string that will hold the server's IP address
|
||||||
|
|
||||||
|
/** Fetch the IP address of pepper from the server */
|
||||||
const char* Connectivity::fetchIPAddress() {
|
const char* Connectivity::fetchIPAddress() {
|
||||||
char* ipAddress = NULL; // Declare ipAddress as a char*
|
char* ipAddress = NULL; // Declare ipAddress as a char*
|
||||||
if (WiFi.status() == WL_CONNECTED) {
|
if (WiFi.status() == WL_CONNECTED) {
|
||||||
@@ -41,14 +42,14 @@ const char* Connectivity::fetchIPAddress() {
|
|||||||
ipAddress = strdup(ip);
|
ipAddress = strdup(ip);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
|
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
http.end();
|
http.end();
|
||||||
} else {
|
} else {
|
||||||
Serial.println("WiFi not connected");
|
Serial.println("WiFi not connected");
|
||||||
}
|
}
|
||||||
return ipAddress; // Add this return statement
|
return ipAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send a POST request to a server with provided data */
|
/** Send a POST request to a server with provided data */
|
||||||
|
@@ -14,8 +14,8 @@
|
|||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
|
||||||
|
// declare the class Connectivity with all functions
|
||||||
class Connectivity {
|
class Connectivity {
|
||||||
public:
|
public:
|
||||||
void connectWiFi(char* ssid, char* pass);
|
void connectWiFi(char* ssid, char* pass);
|
||||||
void websocketSetup(char* ip, uint16_t port, char* adress);
|
void websocketSetup(char* ip, uint16_t port, char* adress);
|
||||||
|
@@ -4,11 +4,10 @@ void setup() {
|
|||||||
//connect to internet and start sensor
|
//connect to internet and start sensor
|
||||||
connectivity.connectWiFi(ssid, pass);
|
connectivity.connectWiFi(ssid, pass);
|
||||||
sensorManager.sensorSetup();
|
sensorManager.sensorSetup();
|
||||||
Serial.begin(115200);
|
|
||||||
Serial.println("startup");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
//get data from sensor
|
||||||
SensorManager::eulerAngles Rotation = sensorManager.getEulerAngles();
|
SensorManager::eulerAngles Rotation = sensorManager.getEulerAngles();
|
||||||
|
|
||||||
//static structure
|
//static structure
|
||||||
@@ -28,6 +27,7 @@ struct acceleration {
|
|||||||
unsigned long currentTime = millis();
|
unsigned long currentTime = millis();
|
||||||
if (currentTime - lastTime >= 100) { // do everything inside every 100 ms
|
if (currentTime - lastTime >= 100) { // do everything inside every 100 ms
|
||||||
memset(buffer, 0, BUFFER_SIZE);
|
memset(buffer, 0, BUFFER_SIZE);
|
||||||
|
//convert string to char*
|
||||||
sprintf(
|
sprintf(
|
||||||
buffer,
|
buffer,
|
||||||
"{\"deviceId\": %d, \"rotationX\": %f, \"rotationY\": %f, \"rotationZ\": %f, \"accelerationX\": %f, \"accelerationY\": %f, \"accelerationZ\": %f, \"type\": %s}",
|
"{\"deviceId\": %d, \"rotationX\": %f, \"rotationY\": %f, \"rotationZ\": %f, \"accelerationX\": %f, \"accelerationY\": %f, \"accelerationZ\": %f, \"type\": %s}",
|
||||||
@@ -40,9 +40,8 @@ struct acceleration {
|
|||||||
accelData.z,
|
accelData.z,
|
||||||
"data");
|
"data");
|
||||||
// %d = int, %f = floatation, %s = string
|
// %d = int, %f = floatation, %s = string
|
||||||
|
//send data to pepper
|
||||||
connectivity.httpPost(serverIp, "/", 3445, buffer, strlen(buffer), "application/json");
|
connectivity.httpPost(serverIp, "/", 3445, buffer, strlen(buffer), "application/json");
|
||||||
Serial.println(serverIp);
|
|
||||||
Serial.println(buffer);
|
|
||||||
lastTime = currentTime;
|
lastTime = currentTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ public class ExerciseManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static final int DEFAULT_EXERCISE_REPETITIONS = 10;
|
public static final int DEFAULT_EXERCISE_REPETITIONS = 10;
|
||||||
public static final float EXERCISE_ERROR_MARGIN = 1.0f;
|
public static final float EXERCISE_ERROR_MARGIN = 1.5f;
|
||||||
public static final float EXERCISE_TIME_SCALING_FACTOR = 1.0f;
|
public static final float EXERCISE_TIME_SCALING_FACTOR = 1.0f;
|
||||||
|
|
||||||
// Fields representing the statistics of the user
|
// Fields representing the statistics of the user
|
||||||
|
@@ -1,4 +0,0 @@
|
|||||||
package com.example.fitbot.ui.activities;
|
|
||||||
|
|
||||||
public class CompletionActivity {
|
|
||||||
}
|
|
@@ -16,6 +16,5 @@ public class EndScreenActivity extends AppCompatActivity {
|
|||||||
NavigationManager.hideSystemUI(this);
|
NavigationManager.hideSystemUI(this);
|
||||||
|
|
||||||
NavigationManager.setupButtonNavigation(this, R.id.homeButtonEndScreen, MainActivity.class);
|
NavigationManager.setupButtonNavigation(this, R.id.homeButtonEndScreen, MainActivity.class);
|
||||||
NavigationManager.setupButtonNavigation(this, R.id.startButtonEndScreen, FitnessActivity.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -10,6 +10,7 @@ import android.content.res.ColorStateList;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.media.MediaPlayer;
|
import android.media.MediaPlayer;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.content.ContextCompat;
|
import android.support.v4.content.ContextCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -19,16 +20,12 @@ import android.widget.ProgressBar;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.VideoView;
|
import android.widget.VideoView;
|
||||||
|
|
||||||
import com.aldebaran.qi.Future;
|
|
||||||
import com.aldebaran.qi.sdk.QiContext;
|
import com.aldebaran.qi.sdk.QiContext;
|
||||||
import com.aldebaran.qi.sdk.QiSDK;
|
import com.aldebaran.qi.sdk.QiSDK;
|
||||||
import com.aldebaran.qi.sdk.RobotLifecycleCallbacks;
|
import com.aldebaran.qi.sdk.RobotLifecycleCallbacks;
|
||||||
import com.aldebaran.qi.sdk.builder.AnimateBuilder;
|
|
||||||
import com.aldebaran.qi.sdk.builder.AnimationBuilder;
|
|
||||||
import com.aldebaran.qi.sdk.design.activity.RobotActivity;
|
import com.aldebaran.qi.sdk.design.activity.RobotActivity;
|
||||||
import com.aldebaran.qi.sdk.design.activity.conversationstatus.SpeechBarDisplayStrategy;
|
import com.aldebaran.qi.sdk.design.activity.conversationstatus.SpeechBarDisplayStrategy;
|
||||||
import com.aldebaran.qi.sdk.object.actuation.Animate;
|
import com.aldebaran.qi.sdk.object.actuation.Animate;
|
||||||
import com.aldebaran.qi.sdk.object.actuation.Animation;
|
|
||||||
import com.example.fitbot.R;
|
import com.example.fitbot.R;
|
||||||
import com.example.fitbot.exercise.Exercise;
|
import com.example.fitbot.exercise.Exercise;
|
||||||
import com.example.fitbot.exercise.ExerciseManager;
|
import com.example.fitbot.exercise.ExerciseManager;
|
||||||
@@ -45,7 +42,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
// Progress circle for the exercises
|
// Progress circle for the exercises
|
||||||
private ProgressBar progressCircle;
|
private ProgressBar progressCircle;
|
||||||
private TextView progressText;
|
private TextView progressText;
|
||||||
private int progress = 0;
|
private int progress = 1;
|
||||||
private final int maxProgress = 10;
|
private final int maxProgress = 10;
|
||||||
|
|
||||||
// Exercise status element data
|
// Exercise status element data
|
||||||
@@ -72,7 +69,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
|
|
||||||
private static final float SENSOR_SAMPLE_RATE = 10.0f;
|
private static final float SENSOR_SAMPLE_RATE = 10.0f;
|
||||||
private static final int EXERCISE_COUNT = 5;
|
private static final int EXERCISE_COUNT = 5;
|
||||||
private static int EXERCISE_REP = 1;
|
private static int EXERCISE_VIDEO_REPETITION = 1;
|
||||||
private static final float EXERCISE_SPEED_MULTIPLIER = 1.0f;
|
private static final float EXERCISE_SPEED_MULTIPLIER = 1.0f;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -88,7 +85,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
//this.exerciseDescriptionTextView = findViewById(R.id.textViewDialogDescription);
|
//this.exerciseDescriptionTextView = findViewById(R.id.textViewDialogDescription);
|
||||||
|
|
||||||
// Set the repetition count for the exercise
|
// Set the repetition count for the exercise
|
||||||
EXERCISE_REP = 1;
|
EXERCISE_VIDEO_REPETITION = 1;
|
||||||
|
|
||||||
progressCircle = findViewById(R.id.progressCircle);
|
progressCircle = findViewById(R.id.progressCircle);
|
||||||
progressText = findViewById(R.id.progressText);
|
progressText = findViewById(R.id.progressText);
|
||||||
@@ -179,6 +176,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
// Start checking for user movement once the video has loaded
|
// Start checking for user movement once the video has loaded
|
||||||
this.motionProcessor.startListening();
|
this.motionProcessor.startListening();
|
||||||
this.motionProcessor.startCheckingUserMovement();
|
this.motionProcessor.startCheckingUserMovement();
|
||||||
|
// this.motionProcessor.setRecording(true, 4.f);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -192,9 +190,9 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
}
|
}
|
||||||
|
|
||||||
videoView.setOnCompletionListener(mp -> {
|
videoView.setOnCompletionListener(mp -> {
|
||||||
if (EXERCISE_REP < EXERCISE_COUNT) {
|
if (EXERCISE_VIDEO_REPETITION < ExerciseManager.DEFAULT_EXERCISE_REPETITIONS) {
|
||||||
videoView.start(); // start the video again
|
videoView.start(); // start the video again
|
||||||
EXERCISE_REP++;
|
EXERCISE_VIDEO_REPETITION++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -211,7 +209,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
public void playVideo(VideoView videoView, Context context) {
|
public void playVideo(VideoView videoView, Context context) {
|
||||||
// Set up the video player
|
// Set up the video player
|
||||||
if (videoView != null) {
|
if (videoView != null) {
|
||||||
videoView.setVideoPath(exerciseVideoUrl);
|
videoView.setVideoURI(Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.arm_raises));
|
||||||
videoView.start();
|
videoView.start();
|
||||||
} else {
|
} else {
|
||||||
Log.e("FitnessActivity", "VideoView is null. Check your layout XML.");
|
Log.e("FitnessActivity", "VideoView is null. Check your layout XML.");
|
||||||
@@ -267,8 +265,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void incrementProgress() {
|
public void incrementProgress() {
|
||||||
if (progress < maxProgress) {
|
if (progress++ < maxProgress) {
|
||||||
progress++;
|
|
||||||
triggerColorBurst(true);
|
triggerColorBurst(true);
|
||||||
updateProgress();
|
updateProgress();
|
||||||
}
|
}
|
||||||
@@ -281,19 +278,25 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
|
|
||||||
public void triggerColorBurst(boolean isGoodRep) {
|
public void triggerColorBurst(boolean isGoodRep) {
|
||||||
|
|
||||||
int circleId = isGoodRep ? R.drawable.progress_circle_good : R.drawable.progress_circle_bad;
|
Log.i("InputProcessor", "Color Burst");
|
||||||
int soundId = isGoodRep ? R.raw.good_sound : R.raw.wrong_sound;
|
|
||||||
progressCircle.setProgressDrawable(ContextCompat.getDrawable(this, circleId));
|
|
||||||
MediaPlayer.create(this, soundId).start();
|
|
||||||
|
|
||||||
ObjectAnimator animator = ObjectAnimator.ofFloat(progressCircle, "alpha", 1f, 0f, 1f);
|
try {
|
||||||
animator.setDuration(700); // Burst duration
|
int circleId = isGoodRep ? R.drawable.progress_circle_good : R.drawable.progress_circle_bad;
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
int soundId = isGoodRep ? R.raw.good_sound : R.raw.wrong_sound;
|
||||||
@Override
|
progressCircle.setProgressDrawable(ContextCompat.getDrawable(this, circleId));
|
||||||
public void onAnimationEnd(Animator animation) {
|
// MediaPlayer.create(this, soundId).start();
|
||||||
progressCircle.setProgressDrawable(ContextCompat.getDrawable(FitnessActivity.this, R.drawable.progress_circle));
|
|
||||||
}
|
ObjectAnimator animator = ObjectAnimator.ofFloat(progressCircle, "alpha", 1f, 0f, 1f);
|
||||||
});
|
animator.setDuration(700); // Burst duration
|
||||||
animator.start();
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
progressCircle.setProgressDrawable(ContextCompat.getDrawable(FitnessActivity.this, R.drawable.progress_circle));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
animator.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -17,17 +17,18 @@ import com.google.gson.JsonParser;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class InputProcessor {
|
public class InputProcessor {
|
||||||
|
|
||||||
private List<Vector3f>[] selfRotationVectorPaths; // Relative path of the motion data
|
private List<Vector3f>[] selfRotationVectorPaths = null; // Relative path of the motion data
|
||||||
private Vector3f[][] targetRotationVectorPaths; // Target path of the motion data
|
private Vector3f[][] targetRotationVectorPaths; // Target path of the motion data
|
||||||
|
|
||||||
private float exerciseRepetitionDurationInSeconds = 0.0f;
|
private float exerciseRepetitionDurationInSeconds = 0.0f;
|
||||||
private int exercisesRemaining = 0;
|
private int exercisesRemaining = 1;
|
||||||
|
|
||||||
private float errorCheckInterval_s;
|
private float errorCheckInterval_s;
|
||||||
private int checksPerformed = 0;
|
private int checksPerformed = 0;
|
||||||
@@ -104,9 +105,20 @@ public class InputProcessor {
|
|||||||
public void startCheckingUserMovement() {
|
public void startCheckingUserMovement() {
|
||||||
// Error checking thread.
|
// Error checking thread.
|
||||||
(new Thread(() -> {
|
(new Thread(() -> {
|
||||||
|
Log.i("InputProcessor", "Movement Checking Thread started");
|
||||||
|
|
||||||
while (this.exercisesRemaining > 0) {
|
while (this.exercisesRemaining > 0) {
|
||||||
|
|
||||||
|
if ( this.totalChecks == 0 || this.selfRotationVectorPaths == null
|
||||||
|
|| this.selfRotationVectorPaths.length == 0
|
||||||
|
|| this.selfRotationVectorPaths[0].size() == 0
|
||||||
|
|| this.selfRotationVectorPaths[1].size() == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
boolean isFaulty = this.isFaultyMovement();
|
boolean isFaulty = this.isFaultyMovement();
|
||||||
|
|
||||||
|
Log.i("InputProcessor", "Movement checked: " + (isFaulty ? "Faulty" : "Good"));
|
||||||
|
|
||||||
if (isFaulty) {
|
if (isFaulty) {
|
||||||
this.onInadequateRepetition();
|
this.onInadequateRepetition();
|
||||||
} else this.onAdequateRepetition();
|
} else this.onAdequateRepetition();
|
||||||
@@ -114,7 +126,11 @@ public class InputProcessor {
|
|||||||
this.checksPerformed++;
|
this.checksPerformed++;
|
||||||
|
|
||||||
if (this.checksPerformed >= this.totalChecks)
|
if (this.checksPerformed >= this.totalChecks)
|
||||||
|
{
|
||||||
|
this.checksPerformed = 0;
|
||||||
|
this.exercisesRemaining--;
|
||||||
acquireExercise();
|
acquireExercise();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep((long) (this.errorCheckInterval_s * 1000));
|
Thread.sleep((long) (this.errorCheckInterval_s * 1000));
|
||||||
@@ -131,21 +147,21 @@ public class InputProcessor {
|
|||||||
* @param exercise The exercise to move on to.
|
* @param exercise The exercise to move on to.
|
||||||
*/
|
*/
|
||||||
private void nextExercise(Exercise exercise) {
|
private void nextExercise(Exercise exercise) {
|
||||||
if (this.exercisesRemaining-- <= 0) {
|
//TODO: Remove when more than one exercise
|
||||||
|
if (this.exercisesRemaining <= 0) {
|
||||||
|
Log.i("InputProcessor", "Moving to end screen; finished all exercises");
|
||||||
// Move to end screen on main activity
|
// Move to end screen on main activity
|
||||||
this.parentActivity.runOnUiThread(() -> NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class));
|
this.parentActivity.runOnUiThread(() -> NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.i("InputProcessor", "Acquired next exercise: " + exercise.name);
|
||||||
ExerciseManager.TOTAL_REPETITIONS_REQUIRED += ExerciseManager.DEFAULT_EXERCISE_REPETITIONS;
|
ExerciseManager.TOTAL_REPETITIONS_REQUIRED += ExerciseManager.DEFAULT_EXERCISE_REPETITIONS;
|
||||||
ExerciseManager.TOTAL_EXERCISES_PREFORMED++;
|
ExerciseManager.TOTAL_EXERCISES_PREFORMED++;
|
||||||
|
|
||||||
this.checksPerformed = 0;
|
this.checksPerformed = 0;
|
||||||
this.totalChecks = ExerciseManager.DEFAULT_EXERCISE_REPETITIONS * 6;
|
this.totalChecks = ExerciseManager.DEFAULT_EXERCISE_REPETITIONS * 6;
|
||||||
|
|
||||||
this.errorCheckInterval_s = this.exerciseRepetitionDurationInSeconds * ExerciseManager.DEFAULT_EXERCISE_REPETITIONS / 6.0f;
|
|
||||||
|
|
||||||
this.selfRotationVectorPaths = new ArrayList[2];
|
this.selfRotationVectorPaths = new ArrayList[2];
|
||||||
this.selfRotationVectorPaths[0] = new ArrayList<>();
|
this.selfRotationVectorPaths[0] = new ArrayList<>();
|
||||||
this.selfRotationVectorPaths[1] = new ArrayList<>();
|
this.selfRotationVectorPaths[1] = new ArrayList<>();
|
||||||
@@ -156,6 +172,11 @@ public class InputProcessor {
|
|||||||
this.exerciseRepetitionDurationInSeconds = exercise.exerciseTimeInSeconds;
|
this.exerciseRepetitionDurationInSeconds = exercise.exerciseTimeInSeconds;
|
||||||
this.secondsPassed = 0.0D;
|
this.secondsPassed = 0.0D;
|
||||||
this.lastTime = System.currentTimeMillis();
|
this.lastTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
Log.i("InputProcessor", "Repetition time: " + exercise.exerciseTimeInSeconds);
|
||||||
|
this.exerciseRepetitionDurationInSeconds = Math.max(this.exerciseRepetitionDurationInSeconds, 2);
|
||||||
|
this.errorCheckInterval_s = exercise.exerciseTimeInSeconds / 3.0f;
|
||||||
|
Log.i("InputProcessor", "Exercise error checking interval: " + this.errorCheckInterval_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,14 +184,16 @@ public class InputProcessor {
|
|||||||
*/
|
*/
|
||||||
public void onAdequateRepetition() {
|
public void onAdequateRepetition() {
|
||||||
ExerciseManager.TOTAL_REPETITIONS_PERFORMED++;
|
ExerciseManager.TOTAL_REPETITIONS_PERFORMED++;
|
||||||
this.parentActivity.incrementProgress();
|
Log.i("InputProcessor", "Adequate repetition performed");
|
||||||
|
this.parentActivity.runOnUiThread(this.parentActivity::incrementProgress);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that is called whenever the user performs a bad repetition.
|
* Method that is called whenever the user performs a bad repetition.
|
||||||
*/
|
*/
|
||||||
public void onInadequateRepetition() {
|
public void onInadequateRepetition() {
|
||||||
this.parentActivity.triggerColorBurst(false);
|
Log.i("InputProcessor", "Inadequate repetition performed");
|
||||||
|
this.parentActivity.runOnUiThread(() -> this.parentActivity.triggerColorBurst(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -231,7 +254,17 @@ public class InputProcessor {
|
|||||||
* Upon successful retrieval, it will call the nextExercise method.
|
* Upon successful retrieval, it will call the nextExercise method.
|
||||||
*/
|
*/
|
||||||
private void acquireExercise() {
|
private void acquireExercise() {
|
||||||
this.exercisesRemaining--;
|
|
||||||
|
if ( this.exercisesRemaining <= 0)
|
||||||
|
{
|
||||||
|
Log.i("InputProcessor", "Exercises finished");
|
||||||
|
this.parentActivity.runOnUiThread(() -> {
|
||||||
|
NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i("MotionProcessor", "Fetching exercise data.");
|
||||||
|
|
||||||
this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> {
|
this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> {
|
||||||
|
|
||||||
@@ -386,29 +419,31 @@ public class InputProcessor {
|
|||||||
* Function for checking whether the last movement was faulty
|
* Function for checking whether the last movement was faulty
|
||||||
*/
|
*/
|
||||||
public boolean isFaultyMovement() {
|
public boolean isFaultyMovement() {
|
||||||
|
boolean upMovementDetected = false;
|
||||||
// Calculate the index of the reference rotation vector
|
boolean downMovementDetected = false;
|
||||||
// This is done by calculating the closest index of the last received vector
|
|
||||||
// to the current time.
|
for (List<Vector3f> path : selfRotationVectorPaths) {
|
||||||
// i = | (t % T) / T * N |
|
if (path.size() < 2) {
|
||||||
|
continue; // Skip if there are not enough points to compare
|
||||||
int i, referenceIndex;
|
}
|
||||||
float distance;
|
|
||||||
|
Vector3f firstPoint = path.get(0);
|
||||||
for (i = 0; i < selfRotationVectorPaths.length; i++) {
|
Vector3f lastPoint = path.get(path.size() - 1);
|
||||||
referenceIndex = (int) (Math.round(
|
|
||||||
((this.secondsPassed % this.exerciseRepetitionDurationInSeconds) /
|
float y1 = firstPoint.y;
|
||||||
(this.exerciseRepetitionDurationInSeconds)) * this.targetRotationVectorPaths[i].length))
|
float y2 = lastPoint.y;
|
||||||
% this.targetRotationVectorPaths[i].length;
|
|
||||||
// If distance is greater than the threshold, return true
|
if (y2 > y1) {
|
||||||
distance = this.selfRotationVectorPaths[i].get(this.selfRotationVectorPaths[i].size() - 1).distance(
|
upMovementDetected = true;
|
||||||
this.targetRotationVectorPaths[i][referenceIndex]);
|
} else if (y2 < y1) {
|
||||||
|
downMovementDetected = true;
|
||||||
if (distance > ExerciseManager.EXERCISE_ERROR_MARGIN) {
|
}
|
||||||
Log.i("MotionProcessor", "Faulty movement detected: " + distance + " > " + ExerciseManager.EXERCISE_ERROR_MARGIN);
|
|
||||||
return true;
|
if (upMovementDetected && downMovementDetected) {
|
||||||
|
return false; // Return false for faulty movement if both up and down movements are detected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
return true; // Return true for faulty movement if only up or down movement is detected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,13 +8,14 @@
|
|||||||
tools:context=".ui.activities.HelpActivity">
|
tools:context=".ui.activities.HelpActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
android:layout_width="800dp"
|
android:layout_width="800dp"
|
||||||
android:layout_height="450dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="80dp"
|
android:layout_marginStart="80dp"
|
||||||
android:layout_marginTop="24dp"
|
android:layout_marginTop="80dp"
|
||||||
android:background="@drawable/border_background"
|
android:background="@drawable/border_background"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="16dp"
|
android:padding="40dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
@@ -26,8 +27,8 @@
|
|||||||
android:layout_marginBottom="40dp"
|
android:layout_marginBottom="40dp"
|
||||||
android:background="@drawable/border_background_3"
|
android:background="@drawable/border_background_3"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingVertical="15dp"
|
|
||||||
android:paddingHorizontal="20dp"
|
android:paddingHorizontal="20dp"
|
||||||
|
android:paddingVertical="15dp"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
@@ -56,27 +57,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:text="@string/voltooid"
|
android:text="@string/voltooid"
|
||||||
android:textAlignment="center"/>
|
android:textAlignment="center" />
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:background="@drawable/border_background_3"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textViewScoreEndScreen"
|
|
||||||
style="@style/TextStyle"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text="@string/score"
|
|
||||||
android:textAlignment="center"/>
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -85,8 +66,8 @@
|
|||||||
android:id="@+id/homeButtonEndScreen"
|
android:id="@+id/homeButtonEndScreen"
|
||||||
android:layout_width="150dp"
|
android:layout_width="150dp"
|
||||||
android:layout_height="75dp"
|
android:layout_height="75dp"
|
||||||
android:layout_marginEnd="280dp"
|
android:layout_marginEnd="404dp"
|
||||||
android:layout_marginBottom="30dp"
|
android:layout_marginBottom="48dp"
|
||||||
android:background="@drawable/red_button_gradient"
|
android:background="@drawable/red_button_gradient"
|
||||||
android:drawableTop="@drawable/ic_baseline_home_48"
|
android:drawableTop="@drawable/ic_baseline_home_48"
|
||||||
android:drawableTint="@color/white"
|
android:drawableTint="@color/white"
|
||||||
@@ -94,20 +75,4 @@
|
|||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/startButtonEndScreen"
|
|
||||||
android:layout_width="150dp"
|
|
||||||
android:layout_height="75dp"
|
|
||||||
android:layout_marginStart="280dp"
|
|
||||||
android:layout_marginBottom="30dp"
|
|
||||||
android:background="@drawable/red_button_gradient"
|
|
||||||
android:padding="15dp"
|
|
||||||
android:text="@string/start"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:textSize="30sp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
</android.support.constraint.ConstraintLayout>
|
</android.support.constraint.ConstraintLayout>
|
@@ -113,7 +113,7 @@
|
|||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:indeterminate="false"
|
android:indeterminate="false"
|
||||||
android:max="10"
|
android:max="10"
|
||||||
android:progress="0"
|
android:progress="1"
|
||||||
android:progressDrawable="@drawable/progress_circle" />
|
android:progressDrawable="@drawable/progress_circle" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:text="0/10" />
|
android:text="1/10" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
BIN
code/src/Fitbot/app/src/main/res/raw/arm_raises.mp4
Normal file
BIN
code/src/Fitbot/app/src/main/res/raw/arm_raises.mp4
Normal file
Binary file not shown.
@@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
### Embedded hardware
|
### Embedded hardware
|
||||||
|
|
||||||
- [BNO085](https://shop.slimevr.dev/products/slimevr-imu-module-bno085) (IMU)
|
| Part | Amount needed for 1 tracker | Price in Euros | Extra notes | |
|
||||||
- [Custom PCB](https://github.com/Sorakage033/SlimeVR-CheeseCake/tree/main/002-%E2%80%98%E2%80%99Choco%E2%80%98%E2%80%99SpecialRemake) (Use file 8 9 and 10 and pcb thickness 1 mm)
|
|---|---|---|---|---|
|
||||||
- [Battery](https://nl.aliexpress.com/item/32583443309.html) (900 mAh)
|
| - [BNO085](https://shop.slimevr.dev/products/slimevr-imu-module-bno085) (IMU) | 1 | 12 | | |
|
||||||
- [3D print model](https://github.com/Sorakage033/SlimeVR-CheeseCake/blob/main/004-3D%20Print%20Model/001.3-Chocolate-Case_TypeC-Only.stl)
|
| - [Custom PCB](https://github.com/Sorakage033/SlimeVR-CheeseCake/tree/main/002-%E2%80%98%E2%80%99Choco%E2%80%98%E2%80%99SpecialRemake) | 1 | ~5 at 30 pieces | (Use file 8, 9 and 10 and use pcb thickness 1mm | |
|
||||||
|
| - [Battery](https://nl.aliexpress.com/item/32583443309.html) (900 mAh) | 1 | ~4 at 20 pieces | | |
|
||||||
- [Optional Acrylic lid](https://github.com/Sorakage033/SlimeVR-CheeseCake/blob/main/004-3D%20Print%20Model/acryliclid.svg)
|
| - [3D print model](https://github.com/Sorakage033/SlimeVR-CheeseCake/blob/main/004-3D%20Print%20Model/001.3-Chocolate-Case_TypeC-Only.stl) | 1 | 0,2 | | |
|
||||||
|
| - [Optional Acrylic lid](https://github.com/Sorakage033/SlimeVR-CheeseCake/blob/main/004-3D%20Print%20Model/acryliclid.svg) | 1 | 0,50 | | |
|
||||||
|
| | | | | |
|
||||||
|
|
||||||
#### Extra notes for assembly
|
#### Extra notes for assembly
|
||||||
* Watch out when inserting the assembled product into the case. Make sure you put it in at an angle so you don't break the power switch.
|
* Watch out when inserting the assembled product into the case. Make sure you put it in at an angle so you don't break the power switch.
|
||||||
|
Reference in New Issue
Block a user