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:
@@ -21,9 +21,9 @@ void Connectivity::connectWiFi(char* ssid, char* pass){
|
||||
// }
|
||||
|
||||
const char* getServerURL = "http://145.92.8.132:443/get-ip";
|
||||
String ipAddress = "";
|
||||
char* ipAddress = "";
|
||||
|
||||
String Connectivity::fetchIPAddress() {
|
||||
const char* Connectivity::fetchIPAddress() {
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
HTTPClient http;
|
||||
WiFiClient client;
|
||||
@@ -32,7 +32,7 @@ String Connectivity::fetchIPAddress() {
|
||||
int httpCode = http.GET();
|
||||
if (httpCode > 0) {
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
ipAddress = http.getString();
|
||||
ipAddress = strdup(http.getString().c_str());
|
||||
}
|
||||
} else {
|
||||
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());
|
||||
|
@@ -19,7 +19,7 @@ public:
|
||||
void websocketSetup(char* ip, uint16_t port, char* adress);
|
||||
void sendData(float roll, float pitch, float yaw);
|
||||
int httpPost(const char *serverAddress, const char *serverSubPath, const unsigned short serverPort, const char *data, const size_t dataLength, const char *contentType);
|
||||
String fetchIPAddress();
|
||||
const char* fetchIPAddress();
|
||||
|
||||
private:
|
||||
ESP8266WiFiMulti wifi;
|
||||
|
@@ -7,8 +7,6 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
unsigned long lastTime = 0; // will store the last time the code was run
|
||||
|
||||
void loop() {
|
||||
SensorManager::eulerAngles eulerRotation = sensorManager.getEulerAngles();
|
||||
// SensorManager::acceleration rotationAcceleration = sensorManager.getAcelleration();
|
||||
@@ -19,6 +17,11 @@ struct acceleration {
|
||||
float z = 9;
|
||||
} accelData;
|
||||
|
||||
if (!ipAquired) {
|
||||
serverIp = connectivity.fetchIPAddress();
|
||||
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
|
||||
memset(buffer, 0, BUFFER_SIZE);
|
||||
@@ -34,7 +37,7 @@ struct acceleration {
|
||||
accelData.z,
|
||||
"data");
|
||||
// %d = int, %f = floatation, %s = string
|
||||
connectivity.httpPost(connectivity.fetchIPAddress(), "/", 3445, buffer, strlen(buffer), "application/json");
|
||||
connectivity.httpPost(serverIp, "/", 3445, buffer, strlen(buffer), "application/json");
|
||||
lastTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
@@ -15,3 +15,5 @@ WebSocketsClient webSocket;
|
||||
#define IP_ADDRESS "192.168.137.12"
|
||||
|
||||
char *buffer = (char *)malloc(sizeof(char) * BUFFER_SIZE);
|
||||
const char* serverIp = NULL; // Declare serverIp here
|
||||
bool ipAquired = false;
|
1
code/src/Fitbot/.gitignore
vendored
1
code/src/Fitbot/.gitignore
vendored
@@ -15,3 +15,4 @@
|
||||
local.properties
|
||||
.idea
|
||||
.vscode
|
||||
/.idea/
|
||||
|
@@ -7,7 +7,7 @@ public class Exercise {
|
||||
public final EMuscleGroup muscleGroup;
|
||||
public final GesturePath leftPath;
|
||||
public final GesturePath rightPath;
|
||||
public final String title;
|
||||
public final String name;
|
||||
public final String description;
|
||||
public final String imageUrl;
|
||||
public final String videoUrl;
|
||||
@@ -19,14 +19,14 @@ public class Exercise {
|
||||
* @param muscleGroup The muscle group of the exercise.
|
||||
* @param leftPath The path of the left hand.
|
||||
* @param rightPath The path of the right hand.
|
||||
* @param title The title of the exercise.
|
||||
* @param name The title of the exercise.
|
||||
* @param description The description of the exercise.
|
||||
* @param imageUrl The URL of the image.
|
||||
* @param videoUrl The URL of the video.
|
||||
*/
|
||||
public Exercise(EMuscleGroup muscleGroup, String title, String description, String imageUrl, String videoUrl, GesturePath leftPath, GesturePath rightPath, float exerciseTimeInSeconds) {
|
||||
public Exercise(EMuscleGroup muscleGroup, String name, String description, String imageUrl, String videoUrl, GesturePath leftPath, GesturePath rightPath, float exerciseTimeInSeconds) {
|
||||
this.name = name;
|
||||
this.muscleGroup = muscleGroup;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.leftPath = leftPath;
|
||||
this.rightPath = rightPath;
|
||||
|
@@ -13,7 +13,7 @@ import java.net.URLConnection;
|
||||
|
||||
public class ExerciseManager {
|
||||
|
||||
private static final String HOST_ADDRESS = "http://145.92.8.132:443/";
|
||||
private static final String HOST_ADDRESS = "http://145.92.8.132:443";
|
||||
|
||||
// The value of these property variables must be equivalent of
|
||||
// the JSON data that the database sends back.
|
||||
@@ -85,11 +85,12 @@ public class ExerciseManager {
|
||||
*/
|
||||
public static Exercise fetchExerciseFromDatabase() {
|
||||
String response = sendHTTP(
|
||||
HOST_ADDRESS, "POST", "application/json", null
|
||||
HOST_ADDRESS, "POST", "application/json", "{}"
|
||||
);
|
||||
// Validate the response
|
||||
if (response != null) {
|
||||
try {
|
||||
System.out.println(response);
|
||||
JsonObject content = JsonParser.parseString(response).getAsJsonObject();
|
||||
|
||||
// Ensure all required properties are present
|
||||
|
@@ -6,6 +6,7 @@ import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.TextView;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
@@ -29,9 +30,10 @@ import org.joml.Vector3f;
|
||||
public class FitnessActivity extends RobotActivity implements RobotLifecycleCallbacks {
|
||||
|
||||
// Private fields for the FitnessActivity class.
|
||||
private ExerciseStatusElement personalMotionPreviewElement;
|
||||
private ExerciseStatusElement exerciseStatusElement;
|
||||
private InputProcessor motionProcessor;
|
||||
private Exercise currentExercise;
|
||||
private TextView exerciseNameTextView;
|
||||
|
||||
// Some nice little messages for the user
|
||||
private static final String[] EXERCISE_NOT_FOUND_MESSAGES = new String[]{
|
||||
@@ -56,6 +58,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
|
||||
// Remove the ugly ass bar on top of the view
|
||||
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
|
||||
this.exerciseNameTextView = findViewById(R.id.textViewFitnessTitle);
|
||||
|
||||
// Find the VideoView by its ID
|
||||
VideoView videoView = findViewById(R.id.videoView);
|
||||
@@ -82,22 +85,23 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
// Provide the context so that all queued actions can be performed.
|
||||
Pepper.provideContext(qiContext, this.getClass());
|
||||
|
||||
personalMotionPreviewElement = findViewById(R.id.personalMotionPreviewElement);
|
||||
exerciseStatusElement = findViewById(R.id.personalMotionPreviewElement);
|
||||
|
||||
// Initialize the element whenever it has been added to the screen.
|
||||
// This will provide the element with the appropriate dimensions for drawing
|
||||
// the canvas properly.
|
||||
personalMotionPreviewElement.post(() -> {
|
||||
exerciseStatusElement.post(() -> {
|
||||
this.fetchExerciseAsync((exercise) -> {
|
||||
// Acquire paths from the exercise and provide them to the motion processor
|
||||
Vector3f[][] vectors = new Vector3f[][]{exercise.leftPath.getVectors(), exercise.rightPath.getVectors()};
|
||||
|
||||
motionProcessor = new InputProcessor(vectors, exercise.exerciseTimeInSeconds, SENSOR_SAMPLE_RATE);
|
||||
|
||||
personalMotionPreviewElement.initialize(exercise, motionProcessor, EXERCISE_COUNT);
|
||||
|
||||
exerciseStatusElement.initialize(exercise, motionProcessor, EXERCISE_COUNT);
|
||||
motionProcessor.useExercise(exercise);
|
||||
/* TODO: Remove if not needed */motionProcessor.setRecording(true, 10);
|
||||
motionProcessor.startListening();
|
||||
motionProcessor.setInputHandler(personalMotionPreviewElement);
|
||||
motionProcessor.setInputHandler(exerciseStatusElement);
|
||||
|
||||
}, (n) -> {
|
||||
int randomMessageIndex = (int) Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length);
|
||||
@@ -123,6 +127,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
||||
if (exercise == null) {
|
||||
onFailedFetch.handle(null);
|
||||
} else {
|
||||
exerciseNameTextView.setText(exercise.name);
|
||||
onSuccessfulFetch.handle(exercise);
|
||||
}
|
||||
})).start();
|
||||
|
@@ -38,16 +38,6 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
||||
private final Paint borderPaint = new Paint();
|
||||
private final Paint backgroundPaint = new Paint();
|
||||
|
||||
// TODO: Remove
|
||||
private final Matrix4f viewMatrix = new Matrix4f(); // The view matrix for the 3D to 2D transformation.
|
||||
private final Matrix4f projectionMatrix = new Matrix4f(); // The projection matrix for the 3D to 2D transformation.
|
||||
private final Vector4f objectPosition = new Vector4f(0, 0, 0, 1); // The location of the object in 3D space.
|
||||
private final ConcurrentLinkedQueue<Vector2f> vectors = new ConcurrentLinkedQueue<>();
|
||||
|
||||
// TODO: Remove
|
||||
private Vector2f[] axisVectors = new Vector2f[0];
|
||||
|
||||
|
||||
private static final String[] STARTING_PHRASES = {
|
||||
"Veel success met de oefening!",
|
||||
"Je kan het!",
|
||||
@@ -93,16 +83,6 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
||||
this.exercise = exercise;
|
||||
this.exerciseCount = exerciseCount;
|
||||
|
||||
/* TODO: Remove */
|
||||
this.axisVectors = new Vector2f[]{
|
||||
projectVertex(new Vector3f(-5.0f, 0, 0), getWidth(), getHeight()),
|
||||
projectVertex(new Vector3f(5.0f, 0, 0), getWidth(), getHeight()),
|
||||
projectVertex(new Vector3f(0, -5.0f, 0), getWidth(), getHeight()),
|
||||
projectVertex(new Vector3f(0, 5.0f, 0), getWidth(), getHeight()),
|
||||
projectVertex(new Vector3f(0, 0, -5.0f), getWidth(), getHeight()),
|
||||
projectVertex(new Vector3f(0, 0, 5.0f), getWidth(), getHeight())
|
||||
};
|
||||
|
||||
Pepper.say(STARTING_PHRASES[(int) Math.floor(Math.random() * STARTING_PHRASES.length)]);
|
||||
|
||||
// Handler that is called every time the motion processor receives new data.
|
||||
@@ -111,6 +91,10 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
||||
Log.i("MotionProcessor", "Rotation vector received: " + rotationVector);
|
||||
Log.i("MotionProcessor", "Last error offset:" + this.motionProcessor.getError(deviceId, this.motionProcessor.secondsPassed()));
|
||||
|
||||
// Check whether the current exercise has been completed.
|
||||
// This is determined by the duration of the exercise, and the amount of time that has passed.
|
||||
// The duration of the exercise originates from the database, and is stored in seconds.
|
||||
// Whenever 'useExercise' is called, the timer resets and this method will be called again.
|
||||
if (this.motionProcessor.hasFinished()) {
|
||||
// If for some reason the parent activity is not defined,
|
||||
// move back to the main screen.
|
||||
@@ -124,6 +108,8 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
||||
this.exerciseCount--;
|
||||
this.parentActivity.fetchExerciseAsync((newExercise) -> {
|
||||
this.motionProcessor.useExercise(newExercise);
|
||||
|
||||
// Whenever the database retrieval failed, we return to the main screen.
|
||||
}, (failed) -> {
|
||||
// Move to main screen
|
||||
NavigationManager.navigateToActivity(parentActivity, MainActivity.class);
|
||||
@@ -131,21 +117,8 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
||||
} else {
|
||||
// Finish the exercise.
|
||||
NavigationManager.navigateToActivity(parentActivity, EndScreenActivity.class);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Use raw vector */
|
||||
vectors.add(projectVertex(rotationVector, this.getWidth(), this.getHeight()));
|
||||
|
||||
/* TODO: Remove */
|
||||
Vector2f parsed = projectVertex(rotationVector, this.getWidth(), this.getHeight());
|
||||
|
||||
this.vectors.add(parsed /* TODO: Add regular vertex once exercise data is stored in DB*/);
|
||||
|
||||
// Remove the first element if the array is too big
|
||||
if (this.vectors.size() > 100)
|
||||
this.vectors.poll();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -159,50 +132,12 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
||||
this.exercise = exercise;
|
||||
}
|
||||
|
||||
|
||||
private Vector2f projectVertex(Vector3f point, int virtualWidth, int virtualHeight) {
|
||||
viewMatrix
|
||||
.identity()
|
||||
.lookAt(new Vector3f(0, 0, -2), new Vector3f(0, 0, 0), new Vector3f(0, 1, 0));
|
||||
|
||||
// Transform the projection matrix to a perspective projection matrix
|
||||
// Perspective transformation conserves the depth of the object
|
||||
projectionMatrix
|
||||
.identity()
|
||||
.perspective((float) Math.toRadians(70), (float) virtualWidth / virtualHeight, .01f, 1000.0f);
|
||||
|
||||
// Convert world coordinates to screen-space using MVP matrix
|
||||
Vector4f screenCoordinates = new Vector4f(point, 1.0f)
|
||||
.mul(this.viewMatrix)
|
||||
.mul(this.projectionMatrix);
|
||||
|
||||
// Normalize screen coordinates from (-1, 1) to (0, virtualWidth) and (0, virtualHeight)
|
||||
float normalizedX = (screenCoordinates.x / screenCoordinates.w + 1.0f) * 0.5f * virtualWidth;
|
||||
float normalizedY = (1.0f - screenCoordinates.y / screenCoordinates.w) * 0.5f * virtualHeight;
|
||||
return new Vector2f(normalizedX, normalizedY);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);
|
||||
this.setBackgroundColor(0xFF000000); // Black
|
||||
/*if (this.exercise == null)
|
||||
return;*/
|
||||
|
||||
|
||||
/* TODO: Remove */
|
||||
for (int i = 0, startX, endX, startY, endY; i < axisVectors.length / 2; i++) {
|
||||
startX = (int) Math.max(0, Math.min(this.getWidth(), (int) axisVectors[i * 2].x));
|
||||
endX = (int) Math.max(0, Math.min(this.getWidth(), (int) axisVectors[i * 2 + 1].x));
|
||||
startY = (int) Math.max(0, Math.min(this.getHeight(), (int) axisVectors[i * 2].y));
|
||||
endY = (int) Math.max(0, Math.min(this.getHeight(), (int) axisVectors[i * 2 + 1].y));
|
||||
canvas.drawLine(startX, startY, endX, endY, this.borderPaint);
|
||||
}
|
||||
|
||||
for (Vector2f point : this.vectors) {
|
||||
canvas.drawRect(point.x, point.y, point.x + 5, point.y + 5, this.userProgressPaint);
|
||||
}
|
||||
/*
|
||||
// Draw target circle
|
||||
float targetRadius = (this.screenDimensions.x + this.screenDimensions.y) / 5.0f;
|
||||
|
@@ -80,6 +80,8 @@ public class InputProcessor {
|
||||
|
||||
this.selfRotationVectorPaths = new Vector3f[2][(int) (exercise.exerciseTimeInSeconds * this.sampleRate)];
|
||||
this.targetRotationVectorPaths = new Vector3f[2][exercise.rightPath.getVectors().length];
|
||||
this.targetRotationVectorPaths[0] = exercise.leftPath.getVectors();
|
||||
this.targetRotationVectorPaths[1] = exercise.rightPath.getVectors();
|
||||
this.exerciseDurationInSeconds = exercise.exerciseTimeInSeconds;
|
||||
this.secondsPassed = 0.0D;
|
||||
this.lastTime = System.currentTimeMillis();
|
||||
@@ -99,7 +101,6 @@ public class InputProcessor {
|
||||
if (recording) {
|
||||
this.secondsPassed = 0.0D;
|
||||
this.lastTime = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -14,7 +14,7 @@ public class DatabaseFetchingTest {
|
||||
assert exercise != null;
|
||||
System.out.println("\n---------------------------------");
|
||||
System.out.println("Exercise:");
|
||||
System.out.println("Name: " + exercise.title);
|
||||
System.out.println("Name: " + exercise.name);
|
||||
System.out.println("Description: " + exercise.description);
|
||||
System.out.println("Muscle Group: " + exercise.muscleGroup);
|
||||
System.out.println("Image URL: " + exercise.imageUrl);
|
||||
|
Reference in New Issue
Block a user