crack cocaine and sport activities
This commit is contained in:
1
code/src/Fitbot/.idea/misc.xml
generated
1
code/src/Fitbot/.idea/misc.xml
generated
@@ -30,6 +30,7 @@
|
|||||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_sport_menu.xml" value="0.1" />
|
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_sport_menu.xml" value="0.1" />
|
||||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/header.xml" value="0.125" />
|
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/header.xml" value="0.125" />
|
||||||
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/toolbar.xml" value="0.125" />
|
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/toolbar.xml" value="0.125" />
|
||||||
|
<entry key="app/src/main/res/layout/activity_end_screen.xml" value="0.1" />
|
||||||
<entry key="app/src/main/res/layout/activity_fitness.xml" value="0.23550724637681159" />
|
<entry key="app/src/main/res/layout/activity_fitness.xml" value="0.23550724637681159" />
|
||||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.1" />
|
<entry key="app/src/main/res/layout/activity_main.xml" value="0.1" />
|
||||||
<entry key="app/src/main/res/layout/activity_sport_item.xml" value="0.2341485507246377" />
|
<entry key="app/src/main/res/layout/activity_sport_item.xml" value="0.2341485507246377" />
|
||||||
|
@@ -5,6 +5,8 @@ import android.os.Bundle;
|
|||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import com.example.fitbot.ui.activities.MainActivity;
|
||||||
|
|
||||||
public class EndScreenActivity extends AppCompatActivity {
|
public class EndScreenActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -8,14 +8,17 @@ import com.example.fitbot.util.server.WebSocket;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public abstract class AbstractExercise implements IWebSocketHandler {
|
public class Exercise implements IWebSocketHandler {
|
||||||
|
|
||||||
private EMuscleGroup muscleGroup;
|
private EMuscleGroup muscleGroup;
|
||||||
private GesturePath path;
|
private GesturePath path;
|
||||||
|
private String title;
|
||||||
|
private String description;
|
||||||
|
private float segmentsPerSecond;
|
||||||
|
|
||||||
// Static fields.
|
// Static fields.
|
||||||
private static WebSocket webSocket;
|
private static WebSocket webSocket;
|
||||||
private static AbstractExercise currentExercise = null;
|
private static Exercise currentExercise = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,10 +26,17 @@ public abstract class AbstractExercise implements IWebSocketHandler {
|
|||||||
*
|
*
|
||||||
* @param muscleGroup The muscle group of the exercise.
|
* @param muscleGroup The muscle group of the exercise.
|
||||||
* @param path The path of the exercise.
|
* @param path The path of the exercise.
|
||||||
|
* @param title The title of the exercise.
|
||||||
|
* @param description The description of the exercise.
|
||||||
|
* @param segmentsPerSecond The number of segments per second.
|
||||||
|
* This determines how fast the exercise should be performed.
|
||||||
*/
|
*/
|
||||||
public AbstractExercise(EMuscleGroup muscleGroup, GesturePath path) {
|
public Exercise(EMuscleGroup muscleGroup, String title, String description, GesturePath path, float segmentsPerSecond) {
|
||||||
this.muscleGroup = muscleGroup;
|
this.muscleGroup = muscleGroup;
|
||||||
|
this.title = title;
|
||||||
|
this.description = description;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
|
this.segmentsPerSecond = segmentsPerSecond;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -101,4 +111,19 @@ public abstract class AbstractExercise implements IWebSocketHandler {
|
|||||||
public GesturePath getPath() {
|
public GesturePath getPath() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the speed of the exercise.
|
||||||
|
*/
|
||||||
|
public double getSegmentsPerSecond() {
|
||||||
|
return segmentsPerSecond;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,41 @@
|
|||||||
|
package com.example.fitbot.exercise;
|
||||||
|
|
||||||
|
import com.example.fitbot.util.processing.IMotionDataConsumer;
|
||||||
|
import com.example.fitbot.util.processing.MotionData;
|
||||||
|
import com.example.fitbot.util.processing.MotionProcessor;
|
||||||
|
import com.example.fitbot.util.server.IWebSocketHandler;
|
||||||
|
import com.example.fitbot.util.server.WebSocket;
|
||||||
|
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
public class ExerciseBuilder implements IWebSocketHandler, IMotionDataConsumer {
|
||||||
|
|
||||||
|
private MotionProcessor processor;
|
||||||
|
|
||||||
|
public ExerciseBuilder() {
|
||||||
|
this.processor = new MotionProcessor();
|
||||||
|
this.processor.setMotionDataEventHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnected(Socket socket) {
|
||||||
|
IWebSocketHandler.super.onDisconnected(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageReceived(WebSocket.Message message, WebSocket.MessageReply replier) {
|
||||||
|
IWebSocketHandler.super.onMessageReceived(message, replier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Socket socket, String error) {
|
||||||
|
IWebSocketHandler.super.onError(socket, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(Vector3f transformedVector, MotionData motionData, int sampleIndex, double sampleRate, int sensorId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -50,7 +50,7 @@ public class FitnessManager {
|
|||||||
* @param uniqueIdentifier The unique identifier of the exercise
|
* @param uniqueIdentifier The unique identifier of the exercise
|
||||||
* @return The exercise, if it exists on the server. Otherwise null.
|
* @return The exercise, if it exists on the server. Otherwise null.
|
||||||
*/
|
*/
|
||||||
public static <T extends AbstractExercise> AbstractExercise acquireExercise(String uniqueIdentifier, Class<T> referenceClass) {
|
public static <T extends Exercise> Exercise acquireExercise(String uniqueIdentifier, Class<T> referenceClass) {
|
||||||
String response = sendHTTP(
|
String response = sendHTTP(
|
||||||
HOST_ADDRESS + "/acquire", "GET", "application/json", "{\"kind\":\"" + uniqueIdentifier + "\"}"
|
HOST_ADDRESS + "/acquire", "GET", "application/json", "{\"kind\":\"" + uniqueIdentifier + "\"}"
|
||||||
);
|
);
|
||||||
|
@@ -1,15 +1,52 @@
|
|||||||
package com.example.fitbot.ui.activities;
|
package com.example.fitbot.ui.activities;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.aldebaran.qi.sdk.QiContext;
|
import com.aldebaran.qi.sdk.QiContext;
|
||||||
import com.aldebaran.qi.sdk.RobotLifecycleCallbacks;
|
import com.aldebaran.qi.sdk.RobotLifecycleCallbacks;
|
||||||
import com.aldebaran.qi.sdk.design.activity.RobotActivity;
|
import com.aldebaran.qi.sdk.design.activity.RobotActivity;
|
||||||
|
import com.example.fitbot.R;
|
||||||
|
import com.example.fitbot.exercise.Exercise;
|
||||||
|
import com.example.fitbot.exercise.EMuscleGroup;
|
||||||
|
import com.example.fitbot.ui.components.PersonalMotionPreviewElement;
|
||||||
|
import com.example.fitbot.util.path.GesturePath;
|
||||||
|
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
public class FitnessActivity extends RobotActivity implements RobotLifecycleCallbacks {
|
public class FitnessActivity extends RobotActivity implements RobotLifecycleCallbacks {
|
||||||
|
|
||||||
|
PersonalMotionPreviewElement personalMotionPreviewElement;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_fitness);x
|
||||||
|
|
||||||
|
GesturePath.Builder gesturePathBuilder = new GesturePath.Builder();
|
||||||
|
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(-.5f, -.5f, -.5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(.5f, -.5f, -.5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(.5f, -.5f, .5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(-.5f, -.5f, .5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(-.5f, -.5f, -.5f));
|
||||||
|
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(-.5f, .5f, -.5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(.5f, .5f, -.5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(.5f, .5f, .5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(-.5f, .5f, .5f));
|
||||||
|
gesturePathBuilder.addVector(new Vector3f(-.5f, .5f, -.5f));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
personalMotionPreviewElement = findViewById(R.id.personalMotionPreviewElement);
|
||||||
|
personalMotionPreviewElement.post(() -> {
|
||||||
|
Log.i("FitnessActivity", "PersonalMotionPreviewElement.post()");
|
||||||
|
|
||||||
|
Exercise exercise = new Exercise(EMuscleGroup.ARMS, "Bicep Curls", "Oefening voor de biceps.", gesturePathBuilder.build(), 1);
|
||||||
|
|
||||||
|
personalMotionPreviewElement.initialize(exercise);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -4,9 +4,11 @@ import android.content.Context;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
|
import android.util.AttributeSet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.example.fitbot.exercise.Exercise;
|
||||||
import com.example.fitbot.util.path.GesturePath;
|
import com.example.fitbot.util.path.GesturePath;
|
||||||
import com.example.fitbot.util.path.PathSegment;
|
import com.example.fitbot.util.path.PathSegment;
|
||||||
import com.example.fitbot.util.processing.MotionData;
|
import com.example.fitbot.util.processing.MotionData;
|
||||||
@@ -22,50 +24,77 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
private GesturePath path;
|
private GesturePath path;
|
||||||
private double pathTime = 0.0D; // The timestamp at which the path is currently at.
|
private double pathTime = 0.0D; // The timestamp at which the path is currently at.
|
||||||
private MotionProcessor motionProcessor;
|
private MotionProcessor motionProcessor;
|
||||||
private Path referencePath, performingPath;
|
|
||||||
private Paint referencePaint, performingPaint;
|
private Path referencePath; // The path the user is supposed to follow.
|
||||||
|
private Path performingPath; // The path the user is currently following.
|
||||||
|
private Path stickmanPath; // The path of the stickman that is drawn on the screen.
|
||||||
|
|
||||||
|
private Paint referencePaint;
|
||||||
|
private Paint performingPaint;
|
||||||
|
|
||||||
private Paint backgroundColor = new Paint();
|
private Paint backgroundColor = new Paint();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants for the preview path projection.
|
* Constants for the preview path projection.
|
||||||
*/
|
*/
|
||||||
private final float FOV = 70.0f; // The field of view of the preview path
|
private final float FOV = 80.0f; // The field of view of the preview path
|
||||||
private final float Z_NEAR = 0.1f; // The near clipping plane
|
private final float Z_NEAR = 0.1f; // The near clipping plane
|
||||||
private final float Z_FAR = 1000.0f; // The far clipping plane
|
private final float Z_FAR = 1000.0f; // The far clipping plane
|
||||||
private Vector3f cameraPosition = new Vector3f(0.0f, 0.0f, 0.0f); // The position of the camera
|
private Vector3f cameraPosition = new Vector3f(0.0f, 0.0f, -1.5f); // The position of the camera
|
||||||
private Vector2f screenDimensions = new Vector2f(); // Width and height dimensions of the screen
|
private Vector2f screenDimensions = new Vector2f(); // Width and height dimensions of the screen
|
||||||
private Vector2f rotation = new Vector2f(); // Rotation vector (yaw, pitch)
|
private Vector2f rotation = new Vector2f(); // Rotation vector (yaw, pitch)
|
||||||
|
|
||||||
|
public PersonalMotionPreviewElement(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
this.referencePaint = new Paint();
|
||||||
|
this.referencePaint.setColor(0xFFFF0000); // Red
|
||||||
|
this.referencePaint.setStyle(Paint.Style.STROKE);
|
||||||
|
this.referencePaint.setStrokeWidth(5.0f);
|
||||||
|
|
||||||
|
this.performingPaint = new Paint();
|
||||||
|
this.performingPaint.setColor(0xFF0000FF); // Blue
|
||||||
|
this.performingPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
this.performingPaint.setStrokeWidth(5.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStickmanGestures() {
|
||||||
|
// Reset previous path
|
||||||
|
stickmanPath.reset();
|
||||||
|
|
||||||
|
PathSegment[] bodySegments = new PathSegment[] {
|
||||||
|
new PathSegment(new Vector3f(0.0f, -.5f, -.5f), new Vector3f(0, 0, 0)), // Left leg
|
||||||
|
new PathSegment(new Vector3f(0.0f, -.5f, .5f), new Vector3f(0, 0, 0)), // Right leg
|
||||||
|
new PathSegment(new Vector3f(0.0f, .5f, 0.0f), new Vector3f(0, 0, 0)), // Body
|
||||||
|
new PathSegment(new Vector3f(-.25f, .25f, 0f), new Vector3f(0, 0, 0)), // Left arm
|
||||||
|
new PathSegment(new Vector3f(.25f, .25f, 0f), new Vector3f(0, 0, 0)) // Right arm
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate new path for stickman
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the PersonalMotionPreviewElement class.
|
* Method for initializing the PersonalMotionPreviewElement.
|
||||||
*
|
*
|
||||||
* @param context The context in which this element is created.
|
* @param exercise The exercise that the user is currently performing.
|
||||||
* @param path The gesture path that will be drawn on the canvas.
|
|
||||||
*/
|
*/
|
||||||
public PersonalMotionPreviewElement(Context context, GesturePath path) {
|
public void initialize(Exercise exercise) {
|
||||||
super(context);
|
|
||||||
Log.i("PersonalMotionPreviewElement", "Creating new PersonalMotionPreviewElement.");
|
Log.i("PersonalMotionPreviewElement", "Creating new PersonalMotionPreviewElement.");
|
||||||
this.backgroundColor = new Paint();
|
this.backgroundColor = new Paint();
|
||||||
this.backgroundColor.setColor(0xFF000000); // Black
|
this.backgroundColor.setColor(0xFF000000); // Black
|
||||||
|
|
||||||
|
this.screenDimensions.x = this.getWidth();
|
||||||
|
this.screenDimensions.y = this.getHeight();
|
||||||
|
this.performingPath = new Path();
|
||||||
|
this.referencePath = new Path();
|
||||||
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.motionProcessor = new MotionProcessor();
|
this.motionProcessor = new MotionProcessor();
|
||||||
this.motionProcessor.startListening();
|
this.motionProcessor.startListening();
|
||||||
this.motionProcessor.setMotionDataEventHandler((processed, preprocessed, sampleIndex, sampleRate) -> {
|
this.motionProcessor.setMotionDataEventHandler((processed, preprocessed, sampleIndex, sampleRate) -> {
|
||||||
// TODO: Implement the calculation of the `performingPath` based on the motion data
|
// TODO: Implement the calculation of the `performingPath` based on the motion data
|
||||||
});
|
});
|
||||||
|
|
||||||
this.referencePath = getDrawablePath(path.getSegments());
|
|
||||||
this.performingPath = new Path();
|
|
||||||
|
|
||||||
this.referencePaint = new Paint();
|
|
||||||
this.referencePaint.setColor(-1); // White
|
|
||||||
this.referencePaint.setStyle(Paint.Style.STROKE);
|
|
||||||
this.referencePaint.setStrokeWidth(5.0f);
|
|
||||||
this.performingPaint = new Paint();
|
|
||||||
this.performingPaint.setColor(0xFF0000FF); // Blue
|
|
||||||
this.performingPaint.setStyle(Paint.Style.STROKE);
|
|
||||||
this.performingPaint.setStrokeWidth(5.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,7 +119,7 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
/**
|
/**
|
||||||
* Method for setting the rotation of the preview path.
|
* Method for setting the rotation of the preview path.
|
||||||
*
|
*
|
||||||
* @param yaw The yaw rotation of the preview path.
|
* @param yaw The yaw rotation of the preview path.
|
||||||
* @param pitch The pitch rotation of the preview path.
|
* @param pitch The pitch rotation of the preview path.
|
||||||
*/
|
*/
|
||||||
public void setRotation(float yaw, float pitch) {
|
public void setRotation(float yaw, float pitch) {
|
||||||
@@ -98,28 +127,27 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method for projecting a 3D point onto the screen.
|
* Method for projecting a 3D point onto the screen.
|
||||||
* This method converts the 3D point to 2D space using a Model-View-Projection matrix transformation.
|
* This method converts the 3D point to 2D space using a Model-View-Projection matrix transformation.
|
||||||
*
|
*
|
||||||
* @param point The point to cast to the screen.
|
* @param point The point to cast to the screen.
|
||||||
* @param virtualWidth The width of the virtual screen.
|
* @param virtualWidth The width of the virtual screen.
|
||||||
* This is used to normalize the screen coordinates.
|
* This is used to normalize the screen coordinates.
|
||||||
* @param virtualHeight The height of the virtual screen.
|
* @param virtualHeight The height of the virtual screen.
|
||||||
* @return The transformed vector in screen coordinates ranging from (0, 0) to (virtualWidth, virtualHeight).
|
* @return The transformed vector in screen coordinates ranging from (0, 0) to (virtualWidth, virtualHeight).
|
||||||
*/
|
*/
|
||||||
private Vector2f projectVertex(Vector3f point, int virtualWidth, int virtualHeight) {
|
private Vector2f projectVertex(Vector3f point, int virtualWidth, int virtualHeight) {
|
||||||
|
Log.i("VertexProjection", "Projecting vertex to screen coordinates: " + point.toString() + " with virtual width " + virtualWidth + " and virtual height " + virtualHeight + ".");
|
||||||
Matrix4f modelViewMatrix = new Matrix4f()
|
Matrix4f modelViewMatrix = new Matrix4f()
|
||||||
.rotateX((float) Math.toRadians(rotation.x))
|
.translate(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z)
|
||||||
.rotateY((float) Math.toRadians(rotation.y))
|
.rotateX((float) Math.toRadians(rotation.y))
|
||||||
.translate(cameraPosition);
|
.rotateY((float) Math.toRadians(rotation.x));
|
||||||
|
|
||||||
Matrix4f projectionMatrix = new Matrix4f()
|
Matrix4f projectionMatrix = new Matrix4f()
|
||||||
.perspective((float) Math.toRadians(FOV), (float) virtualWidth / virtualHeight, Z_NEAR, Z_FAR);
|
.perspective((float) Math.toRadians(FOV), (float) virtualWidth / virtualHeight, Z_NEAR, Z_FAR);
|
||||||
|
|
||||||
// Calculate Model-View-Projection matrix
|
// Calculate Model-View-Projection matrix
|
||||||
Matrix4f MVP = new Matrix4f()
|
Matrix4f MVP = new Matrix4f(projectionMatrix)
|
||||||
.set(projectionMatrix)
|
|
||||||
.mul(modelViewMatrix);
|
.mul(modelViewMatrix);
|
||||||
|
|
||||||
// Convert to screen coordinates
|
// Convert to screen coordinates
|
||||||
@@ -129,7 +157,7 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
// Normalize screen coordinates from (-1, 1) to (0, virtualWidth) and (0, virtualHeight)
|
// Normalize screen coordinates from (-1, 1) to (0, virtualWidth) and (0, virtualHeight)
|
||||||
float normalizedX = (screenCoordinates.x / screenCoordinates.w + 1.0f) * 0.5f * virtualWidth;
|
float normalizedX = (screenCoordinates.x / screenCoordinates.w + 1.0f) * 0.5f * virtualWidth;
|
||||||
float normalizedY = (1.0f - screenCoordinates.y / screenCoordinates.w) * 0.5f * virtualHeight;
|
float normalizedY = (1.0f - screenCoordinates.y / screenCoordinates.w) * 0.5f * virtualHeight;
|
||||||
|
Log.i("VertexProjection", "Projected vertex to screen coordinates: (" + normalizedX + ", " + normalizedY + ").");
|
||||||
return new Vector2f(normalizedX, normalizedY);
|
return new Vector2f(normalizedX, normalizedY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,9 +165,9 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
* Method that converts a sequence of vectors to a Path object.
|
* Method that converts a sequence of vectors to a Path object.
|
||||||
* This path is a set of bezier curves that will be drawn on the canvas.
|
* This path is a set of bezier curves that will be drawn on the canvas.
|
||||||
*
|
*
|
||||||
* @param segments The path segments in the path.
|
* @param segments The path segments in the path.
|
||||||
* These segments will be connected by bezier curves, which
|
* These segments will be connected by bezier curves, which
|
||||||
* all have unique curvature values.
|
* all have unique curvature values.
|
||||||
* @return The generated path object.
|
* @return The generated path object.
|
||||||
*/
|
*/
|
||||||
private Path getDrawablePath(PathSegment... segments) {
|
private Path getDrawablePath(PathSegment... segments) {
|
||||||
@@ -152,8 +180,8 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
|
|
||||||
// Draw the path segments
|
// Draw the path segments
|
||||||
for (PathSegment segment : segments) {
|
for (PathSegment segment : segments) {
|
||||||
Vector2f startProjected = projectVertex(segment.getStart(), getWidth()/2, getHeight());
|
Vector2f startProjected = projectVertex(segment.getStart(), getWidth(), getHeight());
|
||||||
Vector2f endProjected = projectVertex(segment.getEnd(), getWidth()/2, getHeight());
|
Vector2f endProjected = projectVertex(segment.getEnd(), getWidth(), getHeight());
|
||||||
calculatedPath.lineTo(startProjected.x, startProjected.y);
|
calculatedPath.lineTo(startProjected.x, startProjected.y);
|
||||||
calculatedPath.lineTo(endProjected.x, endProjected.y);
|
calculatedPath.lineTo(endProjected.x, endProjected.y);
|
||||||
}
|
}
|
||||||
@@ -165,8 +193,15 @@ public class PersonalMotionPreviewElement extends View {
|
|||||||
@Override
|
@Override
|
||||||
public void onDraw(Canvas canvas) {
|
public void onDraw(Canvas canvas) {
|
||||||
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundColor);
|
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundColor);
|
||||||
|
this.setBackgroundColor(0xFF000000); // Black
|
||||||
|
if (path == null)
|
||||||
|
return;
|
||||||
// Draw the sport preview canvas
|
// Draw the sport preview canvas
|
||||||
canvas.drawPath(referencePath, referencePaint);
|
canvas.drawPath(referencePath, referencePaint);
|
||||||
canvas.drawPath(performingPath, performingPaint);
|
canvas.drawPath(performingPath, performingPaint);
|
||||||
|
|
||||||
|
this.rotation.add(1f, 0);
|
||||||
|
this.referencePath = getDrawablePath(this.path.getSegments());
|
||||||
|
this.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,17 +11,12 @@ public class GesturePath {
|
|||||||
// The vectors that make up the path.
|
// The vectors that make up the path.
|
||||||
private final PathSegment[] segments;
|
private final PathSegment[] segments;
|
||||||
|
|
||||||
public GesturePath(Vector3f[] vectors) {
|
|
||||||
this(vectors, 0.0D);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new gesture path with a given set of vectors and curvature.
|
* Create a new gesture path with a given set of vectors and curvature.
|
||||||
*
|
*
|
||||||
* @param vectors The vectors that make up the path.
|
* @param vectors The vectors that make up the path.
|
||||||
* @param curvature The curvature of the path.
|
|
||||||
*/
|
*/
|
||||||
public GesturePath(Vector3f[] vectors, double curvature)
|
public GesturePath(Vector3f[] vectors)
|
||||||
{
|
{
|
||||||
if ( vectors.length < 2)
|
if ( vectors.length < 2)
|
||||||
throw new IllegalArgumentException("A path must have at least two points.");
|
throw new IllegalArgumentException("A path must have at least two points.");
|
||||||
|
@@ -11,6 +11,6 @@ public interface IMotionDataConsumer {
|
|||||||
* @param sampleIndex The index of the current sample
|
* @param sampleIndex The index of the current sample
|
||||||
* @param sampleRate The sample rate.
|
* @param sampleRate The sample rate.
|
||||||
*/
|
*/
|
||||||
void accept(Vector3f transformedVector, MotionData motionData, int sampleIndex, double sampleRate);
|
void accept(Vector3f transformedVector, MotionData motionData, int sampleIndex, double sampleRate, int sensorId);
|
||||||
|
|
||||||
}
|
}
|
@@ -8,6 +8,7 @@ public class MotionData {
|
|||||||
|
|
||||||
// Data of the motion sensor
|
// Data of the motion sensor
|
||||||
public Vector3f acceleration, rotation;
|
public Vector3f acceleration, rotation;
|
||||||
|
public int sensorId;
|
||||||
|
|
||||||
// Delimiter for the data received from the motion sensor
|
// Delimiter for the data received from the motion sensor
|
||||||
private static final String DATA_DELIMITER = ";";
|
private static final String DATA_DELIMITER = ";";
|
||||||
@@ -21,10 +22,10 @@ public class MotionData {
|
|||||||
* @param rotationX The rotation in the X axis in degrees.
|
* @param rotationX The rotation in the X axis in degrees.
|
||||||
* @param rotationY The rotation in the Y axis in degrees.
|
* @param rotationY The rotation in the Y axis in degrees.
|
||||||
* @param rotationZ The rotation in the Z axis in degrees.
|
* @param rotationZ The rotation in the Z axis in degrees.
|
||||||
|
* @param sensorId The sensor id.
|
||||||
*/
|
*/
|
||||||
public MotionData(float accelerationX, float accelerationY, float accelerationZ, float rotationX, float rotationY, float rotationZ) {
|
public MotionData(float accelerationX, float accelerationY, float accelerationZ, float rotationX, float rotationY, float rotationZ, int sensorId) {
|
||||||
this.acceleration = new Vector3f(accelerationX, accelerationY, accelerationZ);
|
this(new Vector3f(accelerationX, accelerationY, accelerationZ), new Vector3f(rotationX, rotationY, rotationZ), sensorId);
|
||||||
this.rotation = new Vector3f(rotationX, rotationY, rotationZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,9 +34,10 @@ public class MotionData {
|
|||||||
* @param acceleration The acceleration vector in m/s^2.
|
* @param acceleration The acceleration vector in m/s^2.
|
||||||
* @param rotation The rotation vector in degrees.
|
* @param rotation The rotation vector in degrees.
|
||||||
*/
|
*/
|
||||||
public MotionData(Vector3f acceleration, Vector3f rotation) {
|
public MotionData(Vector3f acceleration, Vector3f rotation, int sensorId) {
|
||||||
this.acceleration = acceleration;
|
this.acceleration = acceleration;
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
|
this.sensorId = sensorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +52,7 @@ public class MotionData {
|
|||||||
Objects.requireNonNull(data); // Ensure data is not null
|
Objects.requireNonNull(data); // Ensure data is not null
|
||||||
|
|
||||||
String[] parts = data.split(DATA_DELIMITER);
|
String[] parts = data.split(DATA_DELIMITER);
|
||||||
if (parts.length != 6)
|
if (parts.length != 7)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new MotionData(
|
return new MotionData(
|
||||||
@@ -59,7 +61,8 @@ public class MotionData {
|
|||||||
Float.parseFloat(parts[2]),
|
Float.parseFloat(parts[2]),
|
||||||
Float.parseFloat(parts[3]),
|
Float.parseFloat(parts[3]),
|
||||||
Float.parseFloat(parts[4]),
|
Float.parseFloat(parts[4]),
|
||||||
Float.parseFloat(parts[5])
|
Float.parseFloat(parts[5]),
|
||||||
|
Integer.parseInt(parts[6])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,7 @@ public class MotionProcessor {
|
|||||||
private Vector3f ZERO = new Vector3f(0, 0, 0);
|
private Vector3f ZERO = new Vector3f(0, 0, 0);
|
||||||
|
|
||||||
private float sampleRate = 1.0F; // samples/second
|
private float sampleRate = 1.0F; // samples/second
|
||||||
private IMotionDataConsumer motionDataConsumer = (p1, p2, p3, p4) -> {};
|
private IMotionDataConsumer motionDataConsumer = (p1, p2, p3, p4, p5) -> {};
|
||||||
private GesturePath path;
|
private GesturePath path;
|
||||||
private WebSocket socket;
|
private WebSocket socket;
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ public class MotionProcessor {
|
|||||||
Vector3f previous = this.relativePath.isEmpty() ? ZERO : this.relativePath.get(this.relativePath.size() - 1);
|
Vector3f previous = this.relativePath.isEmpty() ? ZERO : this.relativePath.get(this.relativePath.size() - 1);
|
||||||
Vector3f relativeVector = getRelativeVector(data).add(previous);
|
Vector3f relativeVector = getRelativeVector(data).add(previous);
|
||||||
this.relativePath.add(relativeVector);
|
this.relativePath.add(relativeVector);
|
||||||
motionDataConsumer.accept(relativeVector, data, this.relativePath.size(), this.sampleRate);
|
motionDataConsumer.accept(relativeVector, data, this.relativePath.size(), this.sampleRate, data.sensorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/drawer_layout"
|
android:id="@+id/drawer_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@@ -9,17 +9,10 @@ android:fitsSystemWindows="true"
|
|||||||
tools:context=".ui.activities.FitnessActivity"
|
tools:context=".ui.activities.FitnessActivity"
|
||||||
tools:openDrawer="start">
|
tools:openDrawer="start">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<com.example.fitbot.ui.components.PersonalMotionPreviewElement
|
<com.example.fitbot.ui.components.PersonalMotionPreviewElement
|
||||||
android:id="@+id/personalMotionPreviewElement"
|
android:id="@+id/personalMotionPreviewElement"
|
||||||
android:visibility="visible"
|
android:layout_width="356dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:visibility="visible" />
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</android.support.v4.widget.DrawerLayout>
|
</android.support.v4.widget.DrawerLayout>
|
6
code/src/Fitbot/app/src/main/res/values/attrs.xml
Normal file
6
code/src/Fitbot/app/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="PersonalMotionPreviewElement">
|
||||||
|
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
@@ -1,3 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="Theme.Fitbot" parent="Theme.AppCompat.Light.NoActionBar">
|
<style name="Theme.Fitbot" parent="Theme.AppCompat.Light.NoActionBar">
|
||||||
@@ -6,9 +7,5 @@
|
|||||||
<item name="colorPrimaryDark">@color/purple_700</item>
|
<item name="colorPrimaryDark">@color/purple_700</item>
|
||||||
<item name="colorAccent">@color/teal_200</item>
|
<item name="colorAccent">@color/teal_200</item>
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<!-- Style for general buttons -->
|
|
||||||
</resources>
|
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
Reference in New Issue
Block a user