Removed ExerciseStatusElement.java, moved all functionality to InputProcessor.java
This commit is contained in:
@@ -40,6 +40,12 @@ public class ExerciseManager {
|
|||||||
public static final float EXERCISE_ERROR_MARGIN = 1.0f;
|
public static final float EXERCISE_ERROR_MARGIN = 1.0f;
|
||||||
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
|
||||||
|
public static int TOTAL_REPETITIONS_REQUIRED = 0;
|
||||||
|
public static int TOTAL_REPETITIONS_PERFORMED = 0;
|
||||||
|
public static int TOTAL_EXERCISES_PREFORMED = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for sending an HTTP request to the server.
|
* Function for sending an HTTP request to the server.
|
||||||
*
|
*
|
||||||
@@ -60,6 +66,7 @@ public class ExerciseManager {
|
|||||||
// Send a body if it is present
|
// Send a body if it is present
|
||||||
if (body != null)
|
if (body != null)
|
||||||
connection.getOutputStream().write(body.getBytes());
|
connection.getOutputStream().write(body.getBytes());
|
||||||
|
|
||||||
InputStream stream = connection.getInputStream();
|
InputStream stream = connection.getInputStream();
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
|
@@ -6,14 +6,12 @@ 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.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.VideoView;
|
import android.widget.VideoView;
|
||||||
|
|
||||||
import com.aldebaran.qi.sdk.QiContext;
|
import com.aldebaran.qi.sdk.QiContext;
|
||||||
@@ -25,16 +23,12 @@ 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;
|
||||||
import com.example.fitbot.pepper.Pepper;
|
import com.example.fitbot.pepper.Pepper;
|
||||||
import com.example.fitbot.ui.components.ExerciseStatusElement;
|
|
||||||
import com.example.fitbot.util.NavigationManager;
|
import com.example.fitbot.util.NavigationManager;
|
||||||
import com.example.fitbot.util.processing.InputProcessor;
|
import com.example.fitbot.util.processing.InputProcessor;
|
||||||
|
|
||||||
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 exerciseStatusElement;
|
|
||||||
private InputProcessor motionProcessor;
|
private InputProcessor motionProcessor;
|
||||||
private Exercise currentExercise;
|
private Exercise currentExercise;
|
||||||
|
|
||||||
@@ -104,22 +98,15 @@ 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());
|
||||||
|
|
||||||
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.
|
||||||
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.getAngleVectors(), exercise.rightPath.getAngleVectors()};
|
motionProcessor = new InputProcessor(SENSOR_SAMPLE_RATE, this);
|
||||||
|
|
||||||
motionProcessor = new InputProcessor(vectors, exercise.exerciseTimeInSeconds, SENSOR_SAMPLE_RATE);
|
|
||||||
|
|
||||||
exerciseStatusElement.initialize(exercise, motionProcessor, EXERCISE_COUNT);
|
|
||||||
motionProcessor.useExercise(exercise);
|
motionProcessor.useExercise(exercise);
|
||||||
/* TODO: Remove if not needed */motionProcessor.setRecording(true, 10);
|
/* TODO: Remove if not needed */
|
||||||
motionProcessor.setInputHandler(exerciseStatusElement);
|
motionProcessor.setRecording(true, 10);
|
||||||
motionProcessor.startListening();
|
motionProcessor.startListening();
|
||||||
|
|
||||||
}, (n) -> {
|
}, (n) -> {
|
||||||
@@ -128,7 +115,6 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
Pepper.say(EXERCISE_NOT_FOUND_SEEK_HELP_MESSAGE);
|
Pepper.say(EXERCISE_NOT_FOUND_SEEK_HELP_MESSAGE);
|
||||||
NavigationManager.navigateToActivity(this, EndScreenActivity.class);
|
NavigationManager.navigateToActivity(this, EndScreenActivity.class);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,14 +151,11 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
videoView.setOnCompletionListener(mp -> {
|
||||||
@Override
|
|
||||||
public void onCompletion(MediaPlayer mp) {
|
|
||||||
if (EXERCISE_REP < EXERCISE_COUNT) {
|
if (EXERCISE_REP < EXERCISE_COUNT) {
|
||||||
videoView.start(); // start the video again
|
videoView.start(); // start the video again
|
||||||
EXERCISE_REP++;
|
EXERCISE_REP++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -1,159 +0,0 @@
|
|||||||
package com.example.fitbot.ui.components;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.example.fitbot.exercise.Exercise;
|
|
||||||
import com.example.fitbot.pepper.Pepper;
|
|
||||||
import com.example.fitbot.ui.activities.EndScreenActivity;
|
|
||||||
import com.example.fitbot.ui.activities.FitnessActivity;
|
|
||||||
import com.example.fitbot.ui.activities.MainActivity;
|
|
||||||
import com.example.fitbot.util.NavigationManager;
|
|
||||||
import com.example.fitbot.util.processing.IInputHandler;
|
|
||||||
import com.example.fitbot.util.processing.InputProcessor;
|
|
||||||
|
|
||||||
import org.joml.Vector3f;
|
|
||||||
|
|
||||||
public class ExerciseStatusElement extends View implements IInputHandler {
|
|
||||||
|
|
||||||
// Fields regarding Exercise and speech handling.
|
|
||||||
private InputProcessor motionProcessor;
|
|
||||||
private Exercise exercise;
|
|
||||||
private int exerciseCount;
|
|
||||||
|
|
||||||
private FitnessActivity parentActivity;
|
|
||||||
|
|
||||||
private final Paint userProgressPaint = new Paint();
|
|
||||||
private final Paint borderPaint = new Paint();
|
|
||||||
private final Paint backgroundPaint = new Paint();
|
|
||||||
|
|
||||||
private static final String[] STARTING_PHRASES = {
|
|
||||||
"Veel success met de oefening!",
|
|
||||||
"Je kan het!",
|
|
||||||
"Veel plezier!"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public ExerciseStatusElement(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
|
|
||||||
if (context instanceof Activity) {
|
|
||||||
this.parentActivity = (FitnessActivity) context;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.userProgressPaint.setColor(0xFFFF0000); // Red
|
|
||||||
this.userProgressPaint.setStyle(Paint.Style.FILL);
|
|
||||||
this.userProgressPaint.setStrokeWidth(5.0f);
|
|
||||||
this.userProgressPaint.setAntiAlias(true);
|
|
||||||
|
|
||||||
// Target paint is the filling of the target path.
|
|
||||||
this.borderPaint.setColor(-1);
|
|
||||||
this.borderPaint.setStyle(Paint.Style.STROKE);
|
|
||||||
this.borderPaint.setStrokeWidth(5.0f);
|
|
||||||
this.borderPaint.setAntiAlias(true);
|
|
||||||
|
|
||||||
this.backgroundPaint.setColor(0xFF000000); // Black
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method for initializing the PersonalMotionPreviewElement.
|
|
||||||
* This method has to be called with a "post" function when the element has been
|
|
||||||
* created, otherwise the dimensions of the element aren't initialized yet, which
|
|
||||||
* will cause the vertex projections to fail (0 width and height).
|
|
||||||
*
|
|
||||||
* @param exercise The exercise that the user is currently performing.
|
|
||||||
* @param motionProcessor The motion processor that will be used to process the user's motion.
|
|
||||||
* @param exerciseCount The total amount of exercises that the user has to perform.
|
|
||||||
*/
|
|
||||||
public void initialize(@Nullable Exercise exercise, InputProcessor motionProcessor, int exerciseCount) {
|
|
||||||
Log.i("PersonalMotionPreviewElement", "Creating new PersonalMotionPreviewElement.");
|
|
||||||
|
|
||||||
this.motionProcessor = motionProcessor;
|
|
||||||
this.exercise = exercise;
|
|
||||||
this.exerciseCount = exerciseCount;
|
|
||||||
|
|
||||||
Pepper.say(STARTING_PHRASES[(int) Math.floor(Math.random() * STARTING_PHRASES.length)]);
|
|
||||||
|
|
||||||
// Handler that is called every time the motion processor receives new data.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method for setting the gesture path that will be drawn on the canvas.
|
|
||||||
*
|
|
||||||
* @param exercise The exercise that the user is currently performing.
|
|
||||||
*/
|
|
||||||
public void setExercise(Exercise exercise) {
|
|
||||||
this.motionProcessor.useExercise(exercise);
|
|
||||||
this.exercise = exercise;
|
|
||||||
Log.i("MotionProcessor", "Updating exercise in ExerciseStatusElement");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDraw(Canvas canvas) {
|
|
||||||
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);
|
|
||||||
this.setBackgroundColor(0xFF000000); // Black
|
|
||||||
/*if (this.exercise == null)
|
|
||||||
return;*/
|
|
||||||
/*
|
|
||||||
// Draw target circle
|
|
||||||
float targetRadius = (this.screenDimensions.x + this.screenDimensions.y) / 5.0f;
|
|
||||||
canvas.drawCircle(this.screenDimensions.x / 2, this.screenDimensions.y / 2, targetRadius, this.targetPaint);
|
|
||||||
canvas.drawCircle(this.screenDimensions.x / 2, this.screenDimensions.y / 2, (targetRadius * exerciseProgress.get()/1000.0f), this.referencePaint);
|
|
||||||
referencePaint.setColor(
|
|
||||||
Color.argb(
|
|
||||||
255,
|
|
||||||
(int)(255 * (1.0 - exerciseProgress.get()/1000.0f)),
|
|
||||||
(int)(255 * exerciseProgress.get()/1000.0f),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
);*/
|
|
||||||
|
|
||||||
this.invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(Vector3f rotationVector, int sensorId) {
|
|
||||||
Log.i("MotionProcessor", "Rotation vector received: " + rotationVector);
|
|
||||||
Log.i("MotionProcessor", "Last error offset:" + this.motionProcessor.getError(sensorId, 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() && !this.motionProcessor.isRecording()) {
|
|
||||||
// If for some reason the parent activity is not defined,
|
|
||||||
// move back to the main screen.
|
|
||||||
if (this.parentActivity == null) {
|
|
||||||
// Move to main screen
|
|
||||||
Log.i("MotionProcessor", "Parent activity was null.");
|
|
||||||
NavigationManager.navigateToActivity(getContext(), MainActivity.class);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Move on to the next exercise, or finish.
|
|
||||||
if (this.exerciseCount > 0) {
|
|
||||||
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
|
|
||||||
Log.i("MotionProcessor", "Failed to fetch exercise from database");
|
|
||||||
NavigationManager.navigateToActivity(parentActivity, MainActivity.class);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Finish the exercise.
|
|
||||||
Log.i("MotionProcessor", "Exercise has finished");
|
|
||||||
NavigationManager.navigateToActivity(parentActivity, EndScreenActivity.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@@ -53,13 +53,15 @@ public class AnglePath {
|
|||||||
throw new IllegalArgumentException("Input string must contain 2 elements");
|
throw new IllegalArgumentException("Input string must contain 2 elements");
|
||||||
|
|
||||||
Vector3f[][] angles = new Vector3f[ExerciseManager.SENSOR_COUNT][];
|
Vector3f[][] angles = new Vector3f[ExerciseManager.SENSOR_COUNT][];
|
||||||
|
|
||||||
for ( int dataArrayIdx = 0; dataArrayIdx < parsed.getAsJsonArray().size(); dataArrayIdx++)
|
for ( int dataArrayIdx = 0; dataArrayIdx < parsed.getAsJsonArray().size(); dataArrayIdx++)
|
||||||
{
|
{
|
||||||
JsonArray array = parsed.getAsJsonArray().get(dataArrayIdx).getAsJsonObject().get("data").getAsJsonArray();
|
JsonArray array = parsed.getAsJsonArray().get(dataArrayIdx).getAsJsonObject().get("data").getAsJsonArray();
|
||||||
angles[dataArrayIdx] = new Vector3f[array.size()];
|
int deviceIdx = parsed.getAsJsonArray().get(dataArrayIdx).getAsJsonObject().get("deviceId").getAsInt();
|
||||||
|
angles[deviceIdx] = new Vector3f[array.size()];
|
||||||
for (int i = 0; i < array.size(); i++) {
|
for (int i = 0; i < array.size(); i++) {
|
||||||
JsonArray vec = array.get(i).getAsJsonArray();
|
JsonArray vec = array.get(i).getAsJsonArray();
|
||||||
angles[dataArrayIdx][i] = new Vector3f(vec.get(0).getAsFloat(), vec.get(1).getAsFloat(), vec.get(2).getAsFloat());
|
angles[deviceIdx][i] = new Vector3f(vec.get(0).getAsFloat(), vec.get(1).getAsFloat(), vec.get(2).getAsFloat());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new AnglePath[] {new AnglePath(angles[0]), new AnglePath(angles[1])};
|
return new AnglePath[] {new AnglePath(angles[0]), new AnglePath(angles[1])};
|
||||||
|
@@ -2,15 +2,18 @@ package com.example.fitbot.util.processing;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.aldebaran.qi.sdk.object.geometry.Vector3;
|
|
||||||
import com.example.fitbot.exercise.Exercise;
|
import com.example.fitbot.exercise.Exercise;
|
||||||
import com.example.fitbot.exercise.ExerciseManager;
|
import com.example.fitbot.exercise.ExerciseManager;
|
||||||
|
import com.example.fitbot.pepper.Pepper;
|
||||||
|
import com.example.fitbot.ui.activities.EndScreenActivity;
|
||||||
|
import com.example.fitbot.ui.activities.FitnessActivity;
|
||||||
|
import com.example.fitbot.ui.activities.MainActivity;
|
||||||
|
import com.example.fitbot.util.NavigationManager;
|
||||||
import com.example.fitbot.util.server.WebServer;
|
import com.example.fitbot.util.server.WebServer;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.JsonPrimitive;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
@@ -26,9 +29,21 @@ public class InputProcessor {
|
|||||||
|
|
||||||
private final float sampleRate; // The sample rate of the motion sensor
|
private final float sampleRate; // The sample rate of the motion sensor
|
||||||
private float exerciseDurationInSeconds;
|
private float exerciseDurationInSeconds;
|
||||||
|
private int repetitionsRemaining = 0;
|
||||||
|
private int exercisesRemaining = 0;
|
||||||
private float exerciseScore = 0.0F;
|
private float exerciseScore = 0.0F;
|
||||||
|
|
||||||
|
private final FitnessActivity parentActivity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The phrases that are said by the robot whenever the exercise starts.
|
||||||
|
*/
|
||||||
|
private static final String[] STARTING_PHRASES = {
|
||||||
|
"Veel success met de oefening!",
|
||||||
|
"Je kan het!",
|
||||||
|
"Veel plezier!"
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This field is used to determine if the motion data is being recorded.
|
* This field is used to determine if the motion data is being recorded.
|
||||||
* If this is the case, instead of functioning normally, the element
|
* If this is the case, instead of functioning normally, the element
|
||||||
@@ -48,8 +63,6 @@ public class InputProcessor {
|
|||||||
private double secondsPassed = 0.0D;
|
private double secondsPassed = 0.0D;
|
||||||
private long lastTime;
|
private long lastTime;
|
||||||
|
|
||||||
private IInputHandler motionDataConsumer;
|
|
||||||
|
|
||||||
private static final String[] REQUIRED_SENSOR_JSON_PROPERTIES =
|
private static final String[] REQUIRED_SENSOR_JSON_PROPERTIES =
|
||||||
{"rotationX", "rotationY", "rotationZ", "deviceId"};
|
{"rotationX", "rotationY", "rotationZ", "deviceId"};
|
||||||
|
|
||||||
@@ -60,34 +73,50 @@ public class InputProcessor {
|
|||||||
/**
|
/**
|
||||||
* Constructor for the motion processor.
|
* Constructor for the motion processor.
|
||||||
*
|
*
|
||||||
* @param paths The target paths of the motion data.
|
|
||||||
* The length of this array must be equal to the
|
|
||||||
* amount of sensors available.
|
|
||||||
* @param inputSampleRate The sample rate of the motion sensor.
|
* @param inputSampleRate The sample rate of the motion sensor.
|
||||||
*/
|
*/
|
||||||
public InputProcessor(Vector3f[][] paths, float exerciseTime, float inputSampleRate) {
|
public InputProcessor(float inputSampleRate, FitnessActivity parentActivity) {
|
||||||
this.selfRotationVectorPaths = new ArrayList[2];
|
|
||||||
this.selfRotationVectorPaths[0] = new ArrayList<>();
|
|
||||||
this.selfRotationVectorPaths[1] = new ArrayList<>();
|
|
||||||
targetRotationVectorPaths = paths;
|
|
||||||
|
|
||||||
this.sampleRate = inputSampleRate;
|
this.sampleRate = inputSampleRate;
|
||||||
this.exerciseDurationInSeconds = exerciseTime;
|
this.parentActivity = parentActivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for setting the exercise to use.
|
* Function for setting the exercise to use.
|
||||||
* This updates the user and target path and the
|
* This updates the user and target path and the
|
||||||
* duration of the exercise.
|
* duration of the exercise.
|
||||||
|
* <p>
|
||||||
|
* This function is only initially used to select the starting exercise;
|
||||||
|
* the exercises that follow are determined by a private method 'nextExercise'
|
||||||
*
|
*
|
||||||
* @param exercise The exercise to use the paths for.
|
* @param exercise The exercise to use the paths for.
|
||||||
*/
|
*/
|
||||||
public void useExercise(Exercise exercise) {
|
public void useExercise(Exercise exercise) {
|
||||||
if ( this.recordingMovement )
|
if (this.recordingMovement)
|
||||||
throw new IllegalStateException("Cannot change exercise while recording movement.");
|
throw new IllegalStateException("Cannot change exercise while recording movement.");
|
||||||
|
|
||||||
|
this.exercisesRemaining = 1;
|
||||||
|
this.nextExercise(exercise);
|
||||||
|
Pepper.say(STARTING_PHRASES[(int) Math.floor(Math.random() * STARTING_PHRASES.length)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves on to the next exercise without changing the remaining exercises.
|
||||||
|
*
|
||||||
|
* @param exercise The exercise to move on to.
|
||||||
|
*/
|
||||||
|
private void nextExercise(Exercise exercise) {
|
||||||
|
if (this.exercisesRemaining-- <= 0) {
|
||||||
|
NavigationManager.navigateToActivity(this.parentActivity, EndScreenActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExerciseManager.TOTAL_REPETITIONS_REQUIRED += ExerciseManager.DEFAULT_EXERCISE_REPETITIONS;
|
||||||
|
ExerciseManager.TOTAL_EXERCISES_PREFORMED++;
|
||||||
|
|
||||||
this.selfRotationVectorPaths[0] = new ArrayList<>();
|
this.selfRotationVectorPaths[0] = new ArrayList<>();
|
||||||
this.selfRotationVectorPaths[1] = new ArrayList<>();
|
this.selfRotationVectorPaths[1] = new ArrayList<>();
|
||||||
|
|
||||||
|
this.repetitionsRemaining = ExerciseManager.DEFAULT_EXERCISE_REPETITIONS;
|
||||||
|
|
||||||
this.targetRotationVectorPaths = new Vector3f[2][exercise.rightPath.getAngleVectors().length];
|
this.targetRotationVectorPaths = new Vector3f[2][exercise.rightPath.getAngleVectors().length];
|
||||||
this.targetRotationVectorPaths[0] = exercise.leftPath.getAngleVectors();
|
this.targetRotationVectorPaths[0] = exercise.leftPath.getAngleVectors();
|
||||||
this.targetRotationVectorPaths[1] = exercise.rightPath.getAngleVectors();
|
this.targetRotationVectorPaths[1] = exercise.rightPath.getAngleVectors();
|
||||||
@@ -96,6 +125,21 @@ public class InputProcessor {
|
|||||||
this.lastTime = System.currentTimeMillis();
|
this.lastTime = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that is called whenever the user performs a good repetition.
|
||||||
|
*/
|
||||||
|
public void onAdequateRepetition() {
|
||||||
|
ExerciseManager.TOTAL_REPETITIONS_PERFORMED++;
|
||||||
|
// TODO: Play sound
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method that is called whenever the user performs a bad repetition.
|
||||||
|
*/
|
||||||
|
public void onInadequateRepetition() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for setting whether the motion data
|
* Function for setting whether the motion data
|
||||||
* should be recorded or not.
|
* should be recorded or not.
|
||||||
@@ -171,7 +215,7 @@ public class InputProcessor {
|
|||||||
try {
|
try {
|
||||||
|
|
||||||
Log.i("MotionProcessor", "Time passed: " + this.secondsPassed + "s");
|
Log.i("MotionProcessor", "Time passed: " + this.secondsPassed + "s");
|
||||||
if ( this.recordingMovement)
|
if (this.recordingMovement)
|
||||||
Log.i("MotionProcessor", this.secondsPassed + " / " + this.recordingDurationInSeconds);
|
Log.i("MotionProcessor", this.secondsPassed + " / " + this.recordingDurationInSeconds);
|
||||||
Log.i("MotionProcessor", "Received packet data: " + data);
|
Log.i("MotionProcessor", "Received packet data: " + data);
|
||||||
|
|
||||||
@@ -218,7 +262,7 @@ public class InputProcessor {
|
|||||||
// Supposed index of the current rotation vector in the `rotationVectorPaths` array
|
// Supposed index of the current rotation vector in the `rotationVectorPaths` array
|
||||||
this.selfRotationVectorPaths[deviceId].add(rotation);
|
this.selfRotationVectorPaths[deviceId].add(rotation);
|
||||||
|
|
||||||
if ( this.recordingMovement && this.secondsPassed >= this.recordingDurationInSeconds) {
|
if (this.recordingMovement && this.secondsPassed >= this.recordingDurationInSeconds) {
|
||||||
// Do something with the recorded data.
|
// Do something with the recorded data.
|
||||||
this.recordingMovement = false;
|
this.recordingMovement = false;
|
||||||
// Convert recorded data from `selfRotationVectorPaths` to string, and
|
// Convert recorded data from `selfRotationVectorPaths` to string, and
|
||||||
@@ -231,7 +275,21 @@ public class InputProcessor {
|
|||||||
Log.i("MotionProcessor", converted);
|
Log.i("MotionProcessor", converted);
|
||||||
}
|
}
|
||||||
|
|
||||||
motionDataConsumer.accept(rotation, deviceId);
|
// Do something else with the vector
|
||||||
|
// TODO: Implement !!
|
||||||
|
|
||||||
|
Log.i("MotionProcessor", "Rotation vector: " + rotation.toString() + " from device: " + deviceId);
|
||||||
|
|
||||||
|
// Whenever the exercise has finished and it's not recording,
|
||||||
|
// attempt to move to the next exercise.
|
||||||
|
// If this fails, navigate back to the main activity.
|
||||||
|
if (this.hasFinished() && !this.recordingMovement) {
|
||||||
|
this.parentActivity.fetchExerciseAsync(this::nextExercise, (nil) -> {
|
||||||
|
Log.i("MotionProcessor", "Failed to fetch exercise data.");
|
||||||
|
NavigationManager.navigateToActivity(this.parentActivity, MainActivity.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,8 +300,7 @@ public class InputProcessor {
|
|||||||
*
|
*
|
||||||
* @return The converted string.
|
* @return The converted string.
|
||||||
*/
|
*/
|
||||||
private String convertRecordedDataToString()
|
private String convertRecordedDataToString() {
|
||||||
{
|
|
||||||
int[] intBits = new int[3];
|
int[] intBits = new int[3];
|
||||||
char[] vectorChars = new char[12]; // 4 bytes per scalar, 12 chars per vector
|
char[] vectorChars = new char[12]; // 4 bytes per scalar, 12 chars per vector
|
||||||
JsonArray jsonArray = new JsonArray();
|
JsonArray jsonArray = new JsonArray();
|
||||||
@@ -255,14 +312,14 @@ public class InputProcessor {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Iterate over all devices. In the current instance, it's 2.
|
// Iterate over all devices. In the current instance, it's 2.
|
||||||
for ( int deviceId = 0; deviceId < selfRotationVectorPaths.length; deviceId++) {
|
for (int deviceId = 0; deviceId < selfRotationVectorPaths.length; deviceId++) {
|
||||||
JsonObject jsonDeviceObject = new JsonObject();
|
JsonObject jsonDeviceObject = new JsonObject();
|
||||||
jsonDeviceObject.addProperty("deviceId", deviceId);
|
jsonDeviceObject.addProperty("deviceId", deviceId);
|
||||||
|
|
||||||
// Data array
|
// Data array
|
||||||
JsonArray jsonDeviceDataArray = new JsonArray();
|
JsonArray jsonDeviceDataArray = new JsonArray();
|
||||||
|
|
||||||
for ( Vector3f vector : selfRotationVectorPaths[deviceId]) {
|
for (Vector3f vector : selfRotationVectorPaths[deviceId]) {
|
||||||
JsonArray jsonScalarArray = new JsonArray();
|
JsonArray jsonScalarArray = new JsonArray();
|
||||||
jsonScalarArray.add(vector.x);
|
jsonScalarArray.add(vector.x);
|
||||||
jsonScalarArray.add(vector.y);
|
jsonScalarArray.add(vector.y);
|
||||||
@@ -286,16 +343,6 @@ public class InputProcessor {
|
|||||||
return secondsPassed / exerciseDurationInSeconds;
|
return secondsPassed / exerciseDurationInSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function for setting the motion data receiver.
|
|
||||||
*
|
|
||||||
* @param consumer The consumer to set.
|
|
||||||
*/
|
|
||||||
public void setInputHandler(IInputHandler consumer) {
|
|
||||||
if (consumer != null)
|
|
||||||
this.motionDataConsumer = consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function for getting the combined (average) error value of both sensors.
|
* Function for getting the combined (average) error value of both sensors.
|
||||||
public double getCombinedError()
|
public double getCombinedError()
|
||||||
|
Reference in New Issue
Block a user