Updated InputProcessor and FitnessActivity, fixed some issues.
This commit is contained in:
@@ -7,7 +7,7 @@ public class Exercise {
|
|||||||
public final EMuscleGroup muscleGroup;
|
public final EMuscleGroup muscleGroup;
|
||||||
public final GesturePath leftPath;
|
public final GesturePath leftPath;
|
||||||
public final GesturePath rightPath;
|
public final GesturePath rightPath;
|
||||||
public final String title;
|
public final String name;
|
||||||
public final String description;
|
public final String description;
|
||||||
public final String imageUrl;
|
public final String imageUrl;
|
||||||
public final String videoUrl;
|
public final String videoUrl;
|
||||||
@@ -19,14 +19,14 @@ public class Exercise {
|
|||||||
* @param muscleGroup The muscle group of the exercise.
|
* @param muscleGroup The muscle group of the exercise.
|
||||||
* @param leftPath The path of the left hand.
|
* @param leftPath The path of the left hand.
|
||||||
* @param rightPath The path of the right 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 description The description of the exercise.
|
||||||
* @param imageUrl The URL of the image.
|
* @param imageUrl The URL of the image.
|
||||||
* @param videoUrl The URL of the video.
|
* @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.muscleGroup = muscleGroup;
|
||||||
this.title = title;
|
|
||||||
this.description = description;
|
this.description = description;
|
||||||
this.leftPath = leftPath;
|
this.leftPath = leftPath;
|
||||||
this.rightPath = rightPath;
|
this.rightPath = rightPath;
|
||||||
|
@@ -13,7 +13,7 @@ import java.net.URLConnection;
|
|||||||
|
|
||||||
public class ExerciseManager {
|
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 value of these property variables must be equivalent of
|
||||||
// the JSON data that the database sends back.
|
// the JSON data that the database sends back.
|
||||||
@@ -85,11 +85,12 @@ public class ExerciseManager {
|
|||||||
*/
|
*/
|
||||||
public static Exercise fetchExerciseFromDatabase() {
|
public static Exercise fetchExerciseFromDatabase() {
|
||||||
String response = sendHTTP(
|
String response = sendHTTP(
|
||||||
HOST_ADDRESS, "POST", "application/json", null
|
HOST_ADDRESS, "POST", "application/json", "{}"
|
||||||
);
|
);
|
||||||
// Validate the response
|
// Validate the response
|
||||||
if (response != null) {
|
if (response != null) {
|
||||||
try {
|
try {
|
||||||
|
System.out.println(response);
|
||||||
JsonObject content = JsonParser.parseString(response).getAsJsonObject();
|
JsonObject content = JsonParser.parseString(response).getAsJsonObject();
|
||||||
|
|
||||||
// Ensure all required properties are present
|
// Ensure all required properties are present
|
||||||
|
@@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.TextView;
|
||||||
import android.widget.VideoView;
|
import android.widget.VideoView;
|
||||||
|
|
||||||
import com.aldebaran.qi.sdk.QiContext;
|
import com.aldebaran.qi.sdk.QiContext;
|
||||||
@@ -24,9 +25,10 @@ import org.joml.Vector3f;
|
|||||||
public class FitnessActivity extends RobotActivity implements RobotLifecycleCallbacks {
|
public class FitnessActivity extends RobotActivity implements RobotLifecycleCallbacks {
|
||||||
|
|
||||||
// Private fields for the FitnessActivity class.
|
// Private fields for the FitnessActivity class.
|
||||||
private ExerciseStatusElement personalMotionPreviewElement;
|
private ExerciseStatusElement exerciseStatusElement;
|
||||||
private InputProcessor motionProcessor;
|
private InputProcessor motionProcessor;
|
||||||
private Exercise currentExercise;
|
private Exercise currentExercise;
|
||||||
|
private TextView exerciseNameTextView;
|
||||||
|
|
||||||
// Some nice little messages for the user
|
// Some nice little messages for the user
|
||||||
private static final String[] EXERCISE_NOT_FOUND_MESSAGES = new String[]{
|
private static final String[] EXERCISE_NOT_FOUND_MESSAGES = new String[]{
|
||||||
@@ -51,6 +53,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
|
|
||||||
// Remove the ugly ass bar on top of the view
|
// Remove the ugly ass bar on top of the view
|
||||||
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
|
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
|
||||||
|
this.exerciseNameTextView = findViewById(R.id.textViewFitnessTitle);
|
||||||
|
|
||||||
// Find the VideoView by its ID
|
// Find the VideoView by its ID
|
||||||
VideoView videoView = findViewById(R.id.videoView);
|
VideoView videoView = findViewById(R.id.videoView);
|
||||||
@@ -65,22 +68,23 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
// Provide the context so that all queued actions can be performed.
|
// Provide the context so that all queued actions can be performed.
|
||||||
Pepper.provideContext(qiContext, this.getClass());
|
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.
|
// Initialize the element whenever it has been added to the screen.
|
||||||
// This will provide the element with the appropriate dimensions for drawing
|
// This will provide the element with the appropriate dimensions for drawing
|
||||||
// the canvas properly.
|
// the canvas properly.
|
||||||
personalMotionPreviewElement.post(() -> {
|
exerciseStatusElement.post(() -> {
|
||||||
this.fetchExerciseAsync((exercise) -> {
|
this.fetchExerciseAsync((exercise) -> {
|
||||||
// Acquire paths from the exercise and provide them to the motion processor
|
// Acquire paths from the exercise and provide them to the motion processor
|
||||||
Vector3f[][] vectors = new Vector3f[][]{exercise.leftPath.getVectors(), exercise.rightPath.getVectors()};
|
Vector3f[][] vectors = new Vector3f[][]{exercise.leftPath.getVectors(), exercise.rightPath.getVectors()};
|
||||||
|
|
||||||
motionProcessor = new InputProcessor(vectors, exercise.exerciseTimeInSeconds, SENSOR_SAMPLE_RATE);
|
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.startListening();
|
||||||
motionProcessor.setInputHandler(personalMotionPreviewElement);
|
motionProcessor.setInputHandler(exerciseStatusElement);
|
||||||
|
|
||||||
}, (n) -> {
|
}, (n) -> {
|
||||||
int randomMessageIndex = (int) Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length);
|
int randomMessageIndex = (int) Math.floor(Math.random() * EXERCISE_NOT_FOUND_MESSAGES.length);
|
||||||
@@ -106,6 +110,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
if (exercise == null) {
|
if (exercise == null) {
|
||||||
onFailedFetch.handle(null);
|
onFailedFetch.handle(null);
|
||||||
} else {
|
} else {
|
||||||
|
exerciseNameTextView.setText(exercise.name);
|
||||||
onSuccessfulFetch.handle(exercise);
|
onSuccessfulFetch.handle(exercise);
|
||||||
}
|
}
|
||||||
})).start();
|
})).start();
|
||||||
|
@@ -38,16 +38,6 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
|||||||
private final Paint borderPaint = new Paint();
|
private final Paint borderPaint = new Paint();
|
||||||
private final Paint backgroundPaint = 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 = {
|
private static final String[] STARTING_PHRASES = {
|
||||||
"Veel success met de oefening!",
|
"Veel success met de oefening!",
|
||||||
"Je kan het!",
|
"Je kan het!",
|
||||||
@@ -93,16 +83,6 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
|||||||
this.exercise = exercise;
|
this.exercise = exercise;
|
||||||
this.exerciseCount = exerciseCount;
|
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)]);
|
Pepper.say(STARTING_PHRASES[(int) Math.floor(Math.random() * STARTING_PHRASES.length)]);
|
||||||
|
|
||||||
// Handler that is called every time the motion processor receives new data.
|
// 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", "Rotation vector received: " + rotationVector);
|
||||||
Log.i("MotionProcessor", "Last error offset:" + this.motionProcessor.getError(deviceId, this.motionProcessor.secondsPassed()));
|
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 (this.motionProcessor.hasFinished()) {
|
||||||
// If for some reason the parent activity is not defined,
|
// If for some reason the parent activity is not defined,
|
||||||
// move back to the main screen.
|
// move back to the main screen.
|
||||||
@@ -124,6 +108,8 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
|||||||
this.exerciseCount--;
|
this.exerciseCount--;
|
||||||
this.parentActivity.fetchExerciseAsync((newExercise) -> {
|
this.parentActivity.fetchExerciseAsync((newExercise) -> {
|
||||||
this.motionProcessor.useExercise(newExercise);
|
this.motionProcessor.useExercise(newExercise);
|
||||||
|
|
||||||
|
// Whenever the database retrieval failed, we return to the main screen.
|
||||||
}, (failed) -> {
|
}, (failed) -> {
|
||||||
// Move to main screen
|
// Move to main screen
|
||||||
NavigationManager.navigateToActivity(parentActivity, MainActivity.class);
|
NavigationManager.navigateToActivity(parentActivity, MainActivity.class);
|
||||||
@@ -131,21 +117,8 @@ public class ExerciseStatusElement extends View implements IInputHandler {
|
|||||||
} else {
|
} else {
|
||||||
// Finish the exercise.
|
// Finish the exercise.
|
||||||
NavigationManager.navigateToActivity(parentActivity, EndScreenActivity.class);
|
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;
|
this.exercise = exercise;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** TODO: Remove */
|
|
||||||
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
|
@Override
|
||||||
public void onDraw(Canvas canvas) {
|
public void onDraw(Canvas canvas) {
|
||||||
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);
|
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);
|
||||||
this.setBackgroundColor(0xFF000000); // Black
|
this.setBackgroundColor(0xFF000000); // Black
|
||||||
/*if (this.exercise == null)
|
/*if (this.exercise == null)
|
||||||
return;*/
|
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
|
// Draw target circle
|
||||||
float targetRadius = (this.screenDimensions.x + this.screenDimensions.y) / 5.0f;
|
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.selfRotationVectorPaths = new Vector3f[2][(int) (exercise.exerciseTimeInSeconds * this.sampleRate)];
|
||||||
this.targetRotationVectorPaths = new Vector3f[2][exercise.rightPath.getVectors().length];
|
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.exerciseDurationInSeconds = exercise.exerciseTimeInSeconds;
|
||||||
this.secondsPassed = 0.0D;
|
this.secondsPassed = 0.0D;
|
||||||
this.lastTime = System.currentTimeMillis();
|
this.lastTime = System.currentTimeMillis();
|
||||||
@@ -99,7 +101,6 @@ public class InputProcessor {
|
|||||||
if (recording) {
|
if (recording) {
|
||||||
this.secondsPassed = 0.0D;
|
this.secondsPassed = 0.0D;
|
||||||
this.lastTime = System.currentTimeMillis();
|
this.lastTime = System.currentTimeMillis();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ public class DatabaseFetchingTest {
|
|||||||
assert exercise != null;
|
assert exercise != null;
|
||||||
System.out.println("\n---------------------------------");
|
System.out.println("\n---------------------------------");
|
||||||
System.out.println("Exercise:");
|
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("Description: " + exercise.description);
|
||||||
System.out.println("Muscle Group: " + exercise.muscleGroup);
|
System.out.println("Muscle Group: " + exercise.muscleGroup);
|
||||||
System.out.println("Image URL: " + exercise.imageUrl);
|
System.out.println("Image URL: " + exercise.imageUrl);
|
||||||
|
Reference in New Issue
Block a user