Merge remote-tracking branch 'origin/main'

This commit is contained in:
Luca Warmenhoven
2024-05-29 15:22:49 +02:00
19 changed files with 309 additions and 205 deletions

View File

@@ -1,14 +1,18 @@
#include "headerFile.h"
// SensorManager::Rotation offset;
#define BUFFER_SIZE 1024
#define DEVICE_ID 1
char *buffer = (char *)malloc(sizeof(char) * BUFFER_SIZE);
void setup() {
Serial.begin(9600);
Serial.println("startup");
// Serial.println("startup");
//connect to internet and start sensor
connectivity.connectWiFi(ssid, pass);
sensorManager.sensorSetup();
}
void loop() {
@@ -16,22 +20,26 @@ void loop() {
SensorManager::acceleration rotationAcceleration = sensorManager.getAcelleration();
unsigned long lastTime = 0; // will store the last time the code was run
Serial.print(eulerRotation.roll);
Serial.print(" ");
Serial.print(eulerRotation.yaw);
Serial.print(" ");
Serial.print(eulerRotation.pitch);
Serial.println();
unsigned long currentTime = millis();
if (currentTime - lastTime >= 100) { // 100 ms has passed
String message = "{\"deviceId\": 1, \"rotationX\":\"" + String(eulerRotation.roll) + "\",\"rotationY\":\"" + String(eulerRotation.pitch) + "\",\"rotationZ\":\"" + String(eulerRotation.yaw) + "\",\"accelerationX\":\"" + String(rotationAcceleration.x) + "\",\"accelerationY\":\"" + String(rotationAcceleration.y) + "\",\"accelerationZ\":\"" + String(rotationAcceleration.z) + "\",\"type\":\"data\"}";
Serial.println(connectivity.httpPost("192.168.137.146", "/", 3445, message.c_str(), message.length(), "json"));
Serial.println(message);
memset(buffer, 0, BUFFER_SIZE);
sprintf(
buffer,
"{\"deviceId\": %d, \"rotationX\": %d, \"rotationY\": %d, \"rotationZ\": %d, \"accelerationX\": %d, \"accelerationY\": %d, \"accelerationZ\": %d, \"type\": %s}",
DEVICE_ID,
eulerRotation.roll,
eulerRotation.pitch,
eulerRotation.yaw,
rotationAcceleration.x,
rotationAcceleration.y,
rotationAcceleration.z,
"data");
// Serial.println(connectivity.httpPost("192.168.137.45", "/", 3445, message.c_str(), message.length(), "json"));
// Serial.println(message);
connectivity.httpPost("192.168.137.45", "/", 3445, buffer, strlen(buffer), "application/json");
lastTime = currentTime;
}
}
}
//acceleration.X
//acceleration.Y
//acceleration.Z

View File

@@ -9,15 +9,15 @@ void SensorManager::sensorSetup() {
//wait for the sensor to start before continue
if (myIMU.begin() == false) {
delay(1000);
Serial.println(".");
// Serial.println(".");
}
//start sensorfunction and start autocalibration
//once calibration is enabled it attempts to every 5 min
Wire.setClock(400000);
myIMU.enableGyroIntegratedRotationVector(100); //send data every 100ms
myIMU.enableAccelerometer(100); //Send data update every 100ms
Serial.println(F("magnetometer rotation enabled"));
myIMU.enableStepCounter(500); //Send data update every 500ms
}
//get sensordata
SensorManager::RotationQuintillions SensorManager::getQuintillions() {
@@ -39,7 +39,7 @@ SensorManager::RotationQuintillions SensorManager::getQuintillions() {
return rotation;
}
}
//calculate Quintillions to Euler angles from -1π to +1π
//calculate Quintillions to Euler angles from -1π to +1π
SensorManager::eulerAngles SensorManager::getEulerAngles() {
SensorManager::RotationQuintillions rotation = getQuintillions();
float roll = atan2(2.0f * (rotation.w * rotation.i + rotation.j * rotation.k), 1.0f - 2.0f * (rotation.i * rotation.i + rotation.j * rotation.j));
@@ -48,11 +48,24 @@ SensorManager::eulerAngles SensorManager::getEulerAngles() {
eulerAngles EulerAngles = { roll, pitch, yaw };
return EulerAngles;
}
SensorManager::acceleration SensorManager::getAcelleration(){
float x = myIMU.getAccelX();
float y = myIMU.getAccelY();
float z = myIMU.getAccelZ();
acceleration Acceleration = { x, y, z };
SensorManager::acceleration SensorManager::getAcelleration() {
float x = myIMU.getAccelX();
float y = myIMU.getAccelY();
float z = myIMU.getAccelZ();
acceleration Acceleration = { x, y, z };
return Acceleration;
return Acceleration;
}
bool SensorManager::sensorTap() {
int taps = 0;
if (myIMU.dataAvailable() == true) {
int taps = myIMU.getStepCount();
}
if (taps) {
return true;
}
else {
return false;
}
}

View File

@@ -21,7 +21,7 @@ public:
eulerAngles getEulerAngles();
acceleration getAcelleration();
bool sensorTap();
private:
struct RotationQuintillions {
float i;

View File

@@ -16,6 +16,7 @@
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_end_screen.xml" value="0.165" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_endscreen.xml" value="0.1" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_fitness.xml" value="0.1234375" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_help.xml" value="0.1" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/header.xml" value="0.1234375" />
<entry key="..\:/Users/Niels/muupooviixee66-3/code/src/Fitbot/app/src/main/res/layout/toolbar.xml" value="0.1234375" />

View File

@@ -45,6 +45,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
GesturePath.Builder gesturePathBuilder = new GesturePath.Builder();
/* Generate a random path to test the tracking system */
for ( int i = 0; i < 40; i++)
{
gesturePathBuilder.addVector(
@@ -70,8 +71,10 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
public void onRobotFocusGained(QiContext qiContext) {
// Find the VideoView by its ID
CompletableFuture.runAsync(() -> FitnessCycle.executeMovement("bicepcurl", 10, qiContext));
// CompletableFuture.runAsync(() -> FitnessCycle.executeMovement("bicepcurl", 10, qiContext));
Log.i("Motion", "qiContext provided");
personalMotionPreviewElement.provideQiContext(qiContext);
// FitnessCycle.playVideo(qiContext, videoView, this);
}
@@ -88,5 +91,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
@Override
protected void onDestroy() {
super.onDestroy();
QiSDK.unregister(this, this);
this.personalMotionPreviewElement.onDestroy();
}
}

View File

@@ -4,6 +4,7 @@ import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.fitbot.R;
import com.example.fitbot.util.ButtonNavigation;
public class HelpActivity extends AppCompatActivity {
@@ -11,5 +12,8 @@ public class HelpActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
ButtonNavigation.setupButtonNavigation(this, R.id.homeButton, MainActivity.class);
}
}

View File

@@ -14,6 +14,7 @@ import android.util.Log;
import android.widget.Button;
import com.example.fitbot.R;
import com.example.fitbot.util.ButtonNavigation;
public class MainActivity extends AppCompatActivity {
@@ -48,11 +49,8 @@ public class MainActivity extends AppCompatActivity {
toolbar = findViewById(R.id.toolbar);
startButton = findViewById(R.id.startButton);
startButton.setOnClickListener(v -> { // Switch to fitness activity
Log.i("MainActivity", "Switching to FitnessActivity");
Intent intent = new Intent(MainActivity.this, FitnessActivity.class);
startActivity(intent);
});
ButtonNavigation.setupButtonNavigation(this, R.id.startButton, FitnessActivity.class);
ButtonNavigation.setupButtonNavigation(this, R.id.helpButton, HelpActivity.class);
/*---Tool Bar---*/
setSupportActionBar(toolbar); // Make the toolbar act as the action bar

View File

@@ -22,13 +22,16 @@ import org.joml.Vector2f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class PersonalMotionPreviewElement extends View {
private GesturePath[] paths;
private MotionProcessor motionProcessor;
private double pathTime = 0.0D; // The timestamp at which the path is currently at.
private double exerciseProgress = 0.0D; // The progress of the exercise. Ranges from 0 to 1.
private final AtomicInteger exerciseProgress = new AtomicInteger(0); // The progress of the exercise. Ranges from 0 to 1000.
private QiContext qiContext;
@@ -86,12 +89,19 @@ public class PersonalMotionPreviewElement extends View {
this.targetPath = new Path();
this.startingTime = System.nanoTime(); // Set the last time to the current time
this.exerciseProgress = 0.0d;
this.exercise = exercise;
this.paths = exercise.getPath();
}
public void onDestroy()
{
if ( this.motionProcessor != null )
this.motionProcessor.stopListening();
this.motionProcessor = null;
}
/**
* Function for providing a QiContext to the PersonalMotionPreviewElement.
* This function will be called by the parent activity when the QiContext is available.
@@ -100,20 +110,24 @@ public class PersonalMotionPreviewElement extends View {
* @param context The QiContext to provide.
*/
public void provideQiContext(QiContext context) {
this.qiContext = context;
if ( this.motionProcessor != null )
this.motionProcessor.stopListening();
this.motionProcessor = new MotionProcessor();
this.motionProcessor.startListening();
try {
this.qiContext = context;
if (this.motionProcessor != null)
this.motionProcessor.stopListening();
// Handler that is called every time the motion processor receives new data.
this.motionProcessor.setMotionDataEventHandler((processed, preprocessed, sampleIndex, sampleRate, deviceId) -> {
double progress = this.motionProcessor.getAverageError(this.paths[0], 0);
this.exerciseProgress = Math.min(1, Math.max(0, progress));
this.invalidate();
Log.i("MotionProcessor", "Processed data: " + progress + " (" + preprocessed + ")");
});
saySomethingNice();
this.motionProcessor = new MotionProcessor();
this.motionProcessor.startListening();
// Handler that is called every time the motion processor receives new data.
this.motionProcessor.setMotionDataEventHandler((processed, preprocessed, sampleIndex, sampleRate, deviceId) -> {
int progress = (int) this.motionProcessor.getError(this.paths[0], processed);
this.exerciseProgress.set(Math.min(1000, Math.max(0, progress)));
Log.i("MotionProcessor", "Processed data: " + progress + " (" + preprocessed + ")");
});
saySomethingNice();
} catch (Exception e) {
Log.e("MotionProcessor", "An error occurred whilst attempting to provide QiContext:" + e.getMessage());
}
}
/**
@@ -147,16 +161,18 @@ public class PersonalMotionPreviewElement extends View {
// 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, (float)(targetRadius * exerciseProgress), this.referencePaint);
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)),
(int)(255 * exerciseProgress),
(int)(255 * (1.0 - exerciseProgress.get()/1000.0f)),
(int)(255 * exerciseProgress.get()/1000.0f),
0
)
);
this.invalidate();
timePassed = (System.nanoTime() - startingTime) / 1E9D;
}
}

View File

@@ -71,6 +71,9 @@ public class MotionProcessor {
public void parsePacket(@NotNull String data) {
try {
Log.i("MotionProcessor", "Received packet data: " + data);
JsonElement json = JsonParser.parseString(data);
if (!json.isJsonObject())
@@ -106,6 +109,7 @@ public class MotionProcessor {
addMotionData(motionData);
} catch (Exception e) {
// Don't do anything ... just ignore the exception
Log.i("MotionProcessor", "Failed to parse packet data.");
}
}

View File

@@ -6,6 +6,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
@@ -63,6 +64,7 @@ public class WebServer implements Runnable {
// Find a new connection
Socket newSocket = this.serverSocket.accept();
InputStream streamIn = newSocket.getInputStream();
OutputStream streamOut = newSocket.getOutputStream();
// Read the incoming data
BufferedReader reader = new BufferedReader(new InputStreamReader(streamIn));
@@ -71,7 +73,14 @@ public class WebServer implements Runnable {
while ((line = reader.readLine()) != null)
builder.append(line).append("\n");
// Send generic message back
streamOut.write("HTTP/1.1 200 OK\n".getBytes());
streamOut.write("Content-Type: text/html\n".getBytes());
streamOut.write("Connection: close\n".getBytes());
streamIn.close(); // Closes the reader, stream and socket connection.
streamOut.close();
newSocket.close();
String[] data = builder.toString().split("\n\n");

View File

@@ -56,14 +56,12 @@
style="@style/TextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="539dp"
android:layout_marginEnd="533dp"
android:text="Gefeliciteerd"
app:layout_constraintBottom_toTopOf="@+id/workoutText"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/myRectangleView" />
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.155" />
<TextView
android:id="@+id/workoutText"

View File

@@ -4,6 +4,61 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
tools:context=".ui.activities.HelpActivity">
<View
android:id="@+id/myRectangleView"
android:layout_width="1075dp"
android:layout_height="510dp"
android:background="@drawable/rectangle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.168"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/homeButton"
android:layout_width="200dp"
android:layout_height="75dp"
android:background="@drawable/red_button_gradient"
android:text="@string/home"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.852" />
<TextView
android:id="@+id/textView4.2"
style="@style/TextStyle"
android:layout_width="1053dp"
android:layout_height="191dp"
android:text="@string/uitleg"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.133" />
<TextView
android:id="@+id/textView4"
style="@style/TextStyle"
android:layout_width="1053dp"
android:layout_height="191dp"
android:text="Als je klaar bent kunt u op de COMPLETE knop drukken in het sport scherm en dan kunt u uw punten inzien"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.482" />
</android.support.constraint.ConstraintLayout>

View File

@@ -13,6 +13,8 @@
<string name="home">Home</string>
<string name="skip">Skip</string>
<string name="complete">Complete</string>
<string name="uitleg">Als je op de startknop drukt komen oefingen op het scherm. Het doel is om die zo goedmogelijk na te doen zodat je punten verzameld. Als je klaar bent kunt u op de COMPLETE knop drukken in het sport scherm en dan kunt u uw punten inzien</string>
<color name="red">#f22b1d</color>
</resources>

View File

@@ -7,7 +7,7 @@ app.use(bodyParser.json());
const serverPort = 3000;
const databaseCredentials = {
host: 'localhost',
host: '127.0.0.1',
user: 'fitbot',
password: 'fitbot123',
database: 'fitbot',