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:
Niels Gras
2024-06-07 14:28:40 +02:00
12 changed files with 121 additions and 121 deletions

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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;
} }
} }

View File

@@ -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

View File

@@ -1,4 +0,0 @@
package com.example.fitbot.ui.activities;
public class CompletionActivity {
}

View File

@@ -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);
} }
} }

View File

@@ -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();
}
} }
} }

View File

@@ -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
} }
} }

View File

@@ -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>

View File

@@ -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>

Binary file not shown.

View File

@@ -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.