Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66

This commit is contained in:
Niels Gras
2024-06-04 12:02:31 +02:00
10 changed files with 79 additions and 41 deletions

View File

@@ -24,6 +24,7 @@ const char* getServerURL = "http://145.92.8.132:443/get-ip";
String ipAddress = ""; // string that will hold the server's IP address String ipAddress = ""; // string that will hold the server's IP address
const char* Connectivity::fetchIPAddress() { const char* Connectivity::fetchIPAddress() {
char* ipAddress = NULL; // Declare ipAddress as a char*
if (WiFi.status() == WL_CONNECTED) { if (WiFi.status() == WL_CONNECTED) {
HTTPClient http; HTTPClient http;
WiFiClient client; WiFiClient client;
@@ -33,7 +34,7 @@ const char* Connectivity::fetchIPAddress() {
if (httpCode > 0) { if (httpCode > 0) {
if (httpCode == HTTP_CODE_OK) { if (httpCode == HTTP_CODE_OK) {
// If successful (code 200), read the response body and store the IP address // If successful (code 200), read the response body and store the IP address
ipAddress = http.getString(); ipAddress = strdup(http.getString().c_str());
} }
} else { } else {
Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str()); Serial.printf("GET request failed, error: %s\n", http.errorToString(httpCode).c_str());

View File

@@ -37,7 +37,7 @@ struct acceleration {
accelData.z, accelData.z,
"data"); "data");
// %d = int, %f = floatation, %s = string // %d = int, %f = floatation, %s = string
connectivity.httpPost(serverIp, "/", 3445, buffer, strlen(buffer), "application/json"); connectivity.httpPost("192.168.137.30", "/", 3445, buffer, strlen(buffer), "application/json");
lastTime = currentTime; lastTime = currentTime;
} }
} }

View File

@@ -17,14 +17,14 @@ void SensorManager::sensorSetup() {
// myIMU.enableStepCounter(500); //Send data update every 500ms // myIMU.enableStepCounter(500); //Send data update every 500ms
} }
//get sensordata //get sensordata
SensorManager::RotationQuintillions SensorManager::getQuintillions() { SensorManager::RotationQuaternions SensorManager::getQuaternions() {
if (myIMU.dataAvailable() == true) { if (myIMU.dataAvailable() == true) {
float i = myIMU.getQuatI(); float i = myIMU.getQuatI();
float j = myIMU.getQuatJ(); float j = myIMU.getQuatJ();
float k = myIMU.getQuatK(); float k = myIMU.getQuatK();
float w = myIMU.getQuatReal(); float w = myIMU.getQuatReal();
RotationQuintillions rotation = { i, j, k, w }; RotationQuaternions rotation = { i, j, k, w };
return rotation; return rotation;
} else { } else {
float i = myIMU.getQuatI(); float i = myIMU.getQuatI();
@@ -32,13 +32,13 @@ SensorManager::RotationQuintillions SensorManager::getQuintillions() {
float k = myIMU.getQuatK(); float k = myIMU.getQuatK();
float w = myIMU.getQuatReal(); float w = myIMU.getQuatReal();
RotationQuintillions rotation = { i, j, k, w }; RotationQuaternions rotation = { i, j, k, w };
return rotation; return rotation;
} }
} }
//calculate Quintillions to Euler angles from -1π to +1π //calculate Quaternions to Euler angles from -1π to +1π
SensorManager::eulerAngles SensorManager::getEulerAngles() { SensorManager::eulerAngles SensorManager::getEulerAngles() {
SensorManager::RotationQuintillions rotation = getQuintillions(); SensorManager::RotationQuaternions rotation = getQuaternions();
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)); 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));
float pitch = asin(2.0f * (rotation.w * rotation.j - rotation.k * rotation.i)); float pitch = asin(2.0f * (rotation.w * rotation.j - rotation.k * rotation.i));
float yaw = atan2(2.0f * (rotation.w * rotation.k + rotation.i * rotation.j), 1.0f - 2.0f * (rotation.j * rotation.j + rotation.k * rotation.k)); float yaw = atan2(2.0f * (rotation.w * rotation.k + rotation.i * rotation.j), 1.0f - 2.0f * (rotation.j * rotation.j + rotation.k * rotation.k));

View File

@@ -23,13 +23,13 @@ public:
acceleration getAcelleration(); acceleration getAcelleration();
bool sensorTap(); bool sensorTap();
private: private:
struct RotationQuintillions { struct RotationQuaternions {
float i; float i;
float j; float j;
float k; float k;
float w; float w;
}; };
RotationQuintillions getQuintillions(); RotationQuaternions getQuaternions();
BNO080 myIMU; BNO080 myIMU;
}; };

View File

@@ -39,6 +39,9 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
private TextView exerciseNameTextView; private TextView exerciseNameTextView;
private TextView exerciseShortDescriptionTextView; private TextView exerciseShortDescriptionTextView;
private TextView exerciseDescriptionTextView; private TextView exerciseDescriptionTextView;
private static String exerciseVideoUrl;
private final Object lock = new Object();
// 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[]{
@@ -58,25 +61,20 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
QiSDK.register(this, this); QiSDK.register(this, this);
setContentView(R.layout.activity_fitness); setContentView(R.layout.activity_fitness);
// Remove the ugly ass bar on top of the view
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
// Fill empty objects with exercise data // Fill empty objects with exercise data
this.exerciseNameTextView = findViewById(R.id.textViewFitnessTitle); this.exerciseNameTextView = findViewById(R.id.textViewFitnessTitle);
this.exerciseDescriptionTextView = findViewById(R.id.textViewDialogDescription); //this.exerciseDescriptionTextView = findViewById(R.id.textViewDialogDescription);
this.exerciseShortDescriptionTextView = findViewById(R.id.textViewFitnessShortDescription); this.exerciseShortDescriptionTextView = findViewById(R.id.textViewFitnessShortDescription);
// Find the VideoView by its ID // Navigation Buttons
VideoView videoView = findViewById(R.id.videoView);
playVideo(videoView, this);
NavigationManager.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class); NavigationManager.setupButtonNavigation(this, R.id.homeButtonFitness, MainActivity.class);
NavigationManager.setupButtonNavigation(this, R.id.skipButtonFitness, MainActivity.class); //Needs to skip exercises once those are implemented NavigationManager.setupButtonNavigation(this, R.id.skipButtonFitness, MainActivity.class); //Needs to skip exercises once those are implemented
// Hide system UI // Hide system UI
NavigationManager.hideSystemUI(this); NavigationManager.hideSystemUI(this);
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
// Initiate info button // Initiate info button
Button infoButtonFitness = findViewById(R.id.infoButtonFitness); Button infoButtonFitness = findViewById(R.id.infoButtonFitness);
@@ -109,8 +107,8 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
exerciseStatusElement.initialize(exercise, motionProcessor, EXERCISE_COUNT); 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.setRecording(true, 10);
motionProcessor.startListening();
motionProcessor.setInputHandler(exerciseStatusElement); motionProcessor.setInputHandler(exerciseStatusElement);
motionProcessor.startListening();
}, (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);
@@ -119,8 +117,9 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
NavigationManager.navigateToActivity(this, EndScreenActivity.class); NavigationManager.navigateToActivity(this, EndScreenActivity.class);
}); });
}); });
VideoView videoView = findViewById(R.id.videoView);
// FitnessCycle.playVideo(qiContext, videoView, this); Log.e("exerciseVideoUrl", "videoUrl:" + exerciseVideoUrl);
playVideo(videoView, this);
} }
/** /**
@@ -136,10 +135,13 @@ 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);
exerciseShortDescriptionTextView.setText(exercise.shortDescription);
exerciseDescriptionTextView.setText(exercise.description);
onSuccessfulFetch.handle(exercise); onSuccessfulFetch.handle(exercise);
this.runOnUiThread(() -> {
exerciseNameTextView.setText(exercise.name);
exerciseShortDescriptionTextView.setText(exercise.shortDescription);
// exerciseDescriptionTextView.setText(exercise.description);
exerciseVideoUrl = exercise.videoUrl;
});
} }
})).start(); })).start();
} }
@@ -153,14 +155,7 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
public static void playVideo(VideoView videoView, Context context) { public static void playVideo(VideoView videoView, Context context) {
// Set up the video player // Set up the video player
if (videoView != null) { if (videoView != null) {
Uri videoUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.bicepvideo); videoView.setVideoPath(exerciseVideoUrl);
videoView.setVideoURI(videoUri);
videoView.setOnCompletionListener(mp -> {
// Repeat the video when it finishes playing
videoView.start();
});
videoView.start(); videoView.start();
} else { } else {
Log.e("FitnessActivity", "VideoView is null. Check your layout XML."); Log.e("FitnessActivity", "VideoView is null. Check your layout XML.");

View File

@@ -14,7 +14,11 @@ public class GesturePath {
*/ */
public GesturePath(Vector3f[] vectors) { public GesturePath(Vector3f[] vectors) {
if (vectors.length < 2) { if (vectors.length < 2) {
this.segments = new PathSegment[0]; this.segments = new PathSegment[1];
this.segments[0] = new PathSegment(
new Vector3f(0, 0, 0),
new Vector3f(0, 0, 0)
);
return; return;
} }

View File

@@ -160,6 +160,8 @@ public class InputProcessor {
try { try {
Log.i("MotionProcessor", "Time passed: " + this.secondsPassed + "s");
Log.i("MotionProcessor", "Recording: " + this.recordingMovement + ", " + this.secondsPassed + " / " + this.recordingDurationInSeconds);
Log.i("MotionProcessor", "Received packet data: " + data); Log.i("MotionProcessor", "Received packet data: " + data);
JsonElement json = JsonParser.parseString(data); JsonElement json = JsonParser.parseString(data);
@@ -198,18 +200,12 @@ public class InputProcessor {
// Re-calculate time for index calculation // Re-calculate time for index calculation
secondsPassed = (System.currentTimeMillis() - lastTime) / 1000.0d; secondsPassed = (System.currentTimeMillis() - lastTime) / 1000.0d;
lastTime = System.currentTimeMillis();
// Supposed index of the current rotation vector in the `rotationVectorPaths` array // Supposed index of the current rotation vector in the `rotationVectorPaths` array
int selfIndex = (int) (secondsPassed * sampleRate); int selfIndex = (int) (secondsPassed * sampleRate);
motionDataConsumer.accept(rotation, deviceId); if ( this.recordingMovement && this.secondsPassed >= this.recordingDurationInSeconds) {
if (selfIndex >= selfRotationVectorPaths[deviceId].length || selfIndex < 0)
return;
selfRotationVectorPaths[deviceId][selfIndex] = rotation;
if ( this.recordingMovement && this.hasFinished()) {
// 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
@@ -221,6 +217,11 @@ public class InputProcessor {
Log.i("MotionProcessor", "Converted data: "); Log.i("MotionProcessor", "Converted data: ");
Log.i("MotionProcessor", converted); Log.i("MotionProcessor", converted);
} }
motionDataConsumer.accept(rotation, deviceId);
if (selfIndex >= selfRotationVectorPaths[deviceId].length || selfIndex < 0)
return;
selfRotationVectorPaths[deviceId][selfIndex] = rotation;
} }
} }

View File

@@ -47,7 +47,10 @@
android:layout_width="300dp" android:layout_width="300dp"
android:layout_height="300dp" android:layout_height="300dp"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_margin="50dp" /> android:layout_marginStart="50dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="50dp"
android:layout_marginBottom="50dp" />
</RelativeLayout> </RelativeLayout>

View File

@@ -0,0 +1,34 @@
# Dataprotocols
# different types
### Hypertext Transfer Protocol (HTTP)
HTTP is the foundation of web communication, permitting the transport of data across the internet using a request-response architecture. It uses TCP/IP and stands out by its statelessness, with each request being independent, increasing the web's scalability and flexibility. While it does not encrypt data which makes it usable with sensible data it still makes an nice easy to use option.
We decided to use this for our project because for communicating with the database it is easy to use and we are not usiong sensible data. If we were to use sensible data that we want to encrypt we can use HTTPS. We are only sending small amounts of data to our app and we are not transfering files to our app. This made HTTP it way more attractive option.
### File Transfer Protocol (FTP)
FTP is the classic protocol for transferring files between computers. It establishes a connection between two computers and it has 2 modes. Passive mode for recieving files. This leaves a port open on the computer. You also have an active mode. This is were the client opens a port towards an other computer. If you want to encrypt your data you can use FTPS.
When we started the project is thought of this as a option however since we are not only transfering videos but also stuff like titles and dicriptions i thought we were not going to enable it to its fullest potattional. On top of that we are also transfering only small amounts of videos and we switched the way we used videos on our project by hosting the videos on a service like youtube. This made FTP not usefull for our project.
### User Datagram Protocol (UDP)
UDP is s connectionless protocol that prioritizes speed over reliability. It sends datagrams to a computer without establishing a connection with the reciever. It is not stable so you need to keep in mind that it will not be 100% accurate. However it is really fast so this makes it a suitible option for applications where a tiny amount of dataloss is not an issue.
(to be added)
### Message Queue Telemetry Transport (MQTT)
MQTT is s lightweight messaging protocol designed for machine-to-machine communication in Internet of Things applications. It uses a publish subscribe model. This is were one device publishes data on a server and the other devices need to subscribe to that publisher to recieve the data. It is commonly used to transmot sensor data to a server.
(to be added)
### Real-time Streaming Protocols (RTSP)
RTSP is collection of protocols used for streaming media such as videos over networks. However it requires additional software for it to work properly. RTSP shines in controlling live streams allowing features like pause. It's often used in IPTV's and video conferencing applications.
Due to its limited support we are not uising it in our project. We were already having issues with other things that are not supported on android or mobile apps and we did not want to risk getting more issues while working on our project since we were already using up our limited time. It is a very interesting option though since it will enable more advanced videos. It also is realy complex which makes it a less atractive option since we are already learning a lot of new things and if we were to want to learn more things we would rather learn something with a low learning curve.
# Conclusion