Compare commits

...

158 Commits

Author SHA1 Message Date
SebasKoedam
5753f7047d finished all ui 2024-05-30 10:01:35 +02:00
SebasKoedam
7b72554110 poepies 2024-05-29 18:34:53 +02:00
SebasKoedam
59c906918e added style for help menu 2024-05-29 18:31:03 +02:00
SebasKoedam
7efdf3579e Added new style for fitness activity 2024-05-29 17:17:29 +02:00
SebasKoedam
447ef3a6af toolbar navigation button white 2024-05-29 16:30:24 +02:00
SebasKoedam
426725a632 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 into 59-als-student-wil-ik-dat-de-ui-in-mijn-app-overal-het-zelfde-is-en-in-het-nederlands-wordt 2024-05-29 16:14:12 +02:00
SebasKoedam
4b46738bf0 fixed the main menu bars and theme 2024-05-29 16:12:37 +02:00
SebasKoedam
34dc294d06 fixed the main menu bars and theme 2024-05-29 16:12:23 +02:00
Luca Warmenhoven
2426e7b2e2 Updated PersonalMotionPreviewElement 2024-05-29 16:11:43 +02:00
Luca Warmenhoven
6ffbb503c9 Added more logging for debugging functionality 2024-05-29 16:06:10 +02:00
Luca Warmenhoven
bd9ace61e9 Added more logging for debugging functionality 2024-05-29 15:55:37 +02:00
Luca Warmenhoven
60a45fd510 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	code/src/Fitbot/app/src/main/java/com/example/fitbot/ui/components/PersonalMotionPreviewElement.java
2024-05-29 15:39:34 +02:00
Luca Warmenhoven
a6977b057c Added more logging for debugging functionality 2024-05-29 15:39:13 +02:00
7e60d5e5e6 fixed type error causing bootloop 2024-05-29 15:35:29 +02:00
9ad44897ff optimization 2024-05-29 15:22:38 +02:00
0441133744 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-29 15:15:23 +02:00
c3329a4c52 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-29 15:15:14 +02:00
Niels Gras
4c8c9d9f32 Merge branch '57-als-gebruiker-wil-ik-een-uitleg-scherm-zodat-ik-kan-zien-wat-fitbot-inhoudt' into 'main'
Resolve "Als gebruiker wil ik een uitleg scherm zodat ik kan zien wat fitbot inhoudt."

Closes #57

See merge request propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66!13
2024-05-29 15:14:48 +02:00
Luca Warmenhoven
447a021b10 Added more logging for debugging functionality 2024-05-29 15:13:04 +02:00
49eb09b105 added logging 2024-05-29 15:12:27 +02:00
ea9a35030b qi.sdk unregister added 2024-05-29 15:12:18 +02:00
Niels Gras
940202d9f4 Edited help screen 2024-05-29 14:00:45 +02:00
Luca Warmenhoven
4983162ac9 Merge remote-tracking branch 'origin/main' 2024-05-29 13:41:00 +02:00
Luca Warmenhoven
95ed46d9ac cermit 2024-05-29 13:40:53 +02:00
SebasKoedam
d6fc5098dd Update database host to use IP address instead of localhost 2024-05-29 13:06:55 +02:00
SebasKoedam
b8e3e89bb2 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-29 13:04:59 +02:00
SebasKoedam
c362a41f06 added infrastructure documentation 2024-05-29 13:04:57 +02:00
Luca Warmenhoven
bd74b0b5aa Merge remote-tracking branch 'origin/main' 2024-05-29 12:17:48 +02:00
Luca Warmenhoven
d080f0af8d Updated incoming_request_handlers.js to match database querying 2024-05-29 12:17:33 +02:00
Niels
e4ee419e2d finished betoog 2024-05-28 21:39:25 +02:00
Niels
58c80ed60c Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 20:16:59 +02:00
Niels
f1570aaea9 added part of research 2024-05-28 20:16:56 +02:00
1a56a05409 Junk cleanup and new json formatting 2024-05-28 16:17:06 +02:00
cdd8ac9d49 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 16:11:09 +02:00
Luca Warmenhoven
3d01749aa2 Attempt to make good 2024-05-28 16:11:03 +02:00
004d216767 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 15:58:44 +02:00
Luca Warmenhoven
5789f4c0dd Attempt to make good 2024-05-28 15:58:25 +02:00
Luca Warmenhoven
5a226dd56b Attempt to make good 2024-05-28 15:56:28 +02:00
6961801a67 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 15:39:28 +02:00
Luca Warmenhoven
3c0e07336d Attempt to make good 2024-05-28 15:37:26 +02:00
48848de44d Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 15:28:21 +02:00
Luca Warmenhoven
c527289c68 Attempt to make good 2024-05-28 15:28:09 +02:00
83b233e275 dead code removal 2024-05-28 15:16:04 +02:00
Luca Warmenhoven
80ef0ac99e Pep crack cocaine 2024-05-28 15:06:54 +02:00
Luca Warmenhoven
565d19ec00 Pep crack cocaine 2024-05-28 15:04:17 +02:00
Luca Warmenhoven
62e1320b3c Pep crack cocaine 2024-05-28 15:00:48 +02:00
Luca Warmenhoven
31135d1aa7 poep 2024-05-28 14:36:48 +02:00
Luca Warmenhoven
4c9a256d6c Pep crack cocaine 2024-05-28 14:15:30 +02:00
bcfc622c90 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 14:08:19 +02:00
9397028c1b Added port config 2024-05-28 14:08:12 +02:00
Luca Warmenhoven
d9c05b2975 But crack 2024-05-28 14:08:12 +02:00
Luca Warmenhoven
8c1e4332aa Commit balls 2024-05-28 13:50:35 +02:00
Luca Warmenhoven
eb6ffcf4c8 Merge remote-tracking branch 'origin/main' 2024-05-28 13:47:09 +02:00
Luca Warmenhoven
976d5b1ef1 Gitter Committer Crack balls 2024-05-28 13:46:59 +02:00
Niels Gras
20906379d3 tekst to string 2024-05-28 13:04:58 +02:00
Niels Gras
1b955baf6b added help tekst 2024-05-28 13:01:42 +02:00
df8a7a6395 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 12:59:35 +02:00
f66f167812 Refactor package import in FitnessCycle.java 2024-05-28 12:59:31 +02:00
1a086a9f57 added issues about hardware 2024-05-28 12:59:04 +02:00
2be0efc37e Disabled websocket in favour of other protocol 2024-05-28 12:58:01 +02:00
Niels Gras
fcb5c7f61b Made the buttons functional and cleaned up start button in main 2024-05-28 12:44:48 +02:00
Niels Gras
c3cf6e3cf9 styled help activity 2024-05-28 12:33:01 +02:00
Luca Warmenhoven
d1e0c5b08e Crack butt 2024-05-28 12:12:34 +02:00
Luca Warmenhoven
29944bce57 Crack butt 2024-05-28 12:07:07 +02:00
Luca Warmenhoven
caa7599518 Commit war crimes in formal Yugoslavia 2024-05-28 11:53:28 +02:00
Luca Warmenhoven
652d7c501d Merge remote-tracking branch 'origin/main' 2024-05-28 11:47:46 +02:00
Luca Warmenhoven
b85219d013 Commit crack cocaine 2024-05-28 11:47:42 +02:00
SebasKoedam
774329699a chore: Remove unused sections and update professional skills in skillOntwikkelplan.md 2024-05-28 10:17:13 +02:00
SebasKoedam
7090bccdb8 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-28 10:10:29 +02:00
SebasKoedam
4a53ea1420 eerste versie onderzoek 2024-05-28 10:10:28 +02:00
fc47353e98 junk uit betoog gehaald 2024-05-28 00:02:18 +02:00
74d6cda049 Spelfouten en betoog afgemaakt 2024-05-28 00:00:37 +02:00
ebd6ae7a12 betoog 2024-05-27 23:20:05 +02:00
Niels
d7e22dac6e updated skillsontwikkelings plan and added assets folder for personal docs 2024-05-26 01:10:47 +02:00
Luca Warmenhoven
8d5cecce27 updated gay 2024-05-25 19:34:58 +02:00
Luca Warmenhoven
ff5d1ed31f killed my brain doing literature 2024-05-25 19:31:13 +02:00
SebasKoedam
8b02096a98 chore: Update image path in sprint report 2024-05-25 11:27:05 +02:00
SebasKoedam
d69701b60d added missing image 2024-05-25 11:16:35 +02:00
Niels Gras
a62b46fcf9 added retro image 2024-05-24 14:36:43 +02:00
SebasKoedam
856f0af4b2 chore: Update image path in sprint report 2024-05-24 14:32:42 +02:00
Niels Gras
5462a6fbcc Added help activity 2024-05-24 13:41:53 +02:00
dd91639fb2 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-24 12:27:11 +02:00
02c2cff330 updated lateralraises animation 2024-05-24 12:24:58 +02:00
1fb1d5d02d Added class and intergrated it into code 2024-05-24 12:24:48 +02:00
82731ee176 added library and videoview 2024-05-24 12:24:24 +02:00
Luca Warmenhoven
04bdf656f4 Merge remote-tracking branch 'origin/main' 2024-05-24 12:20:53 +02:00
Luca Warmenhoven
38e70e3b53 Fixed more shit 2024-05-24 12:20:49 +02:00
Niels Gras
a8e7f6d8b8 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-24 12:04:45 +02:00
Niels Gras
f96d6ec394 chore: Update navigation menu with Colors research page 2024-05-24 12:04:43 +02:00
Luca Warmenhoven
f5900bf50e Merge remote-tracking branch 'origin/main' 2024-05-24 11:52:17 +02:00
Luca Warmenhoven
04054c862b Fixed some shit and removed ugly ass shit 2024-05-24 11:52:12 +02:00
3ee81d0e48 fitnesscycle class it plays the animation a given amount of reps 2024-05-24 11:29:40 +02:00
Luca Warmenhoven
cb53000eb3 Added NodeJS Server files 2024-05-24 10:53:14 +02:00
fdfb216617 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-23 19:57:26 +02:00
1a62421c90 added comment to animation class 2024-05-23 19:56:39 +02:00
SebasKoedam
25f9f098b0 improved main and fitness layout 2024-05-23 18:09:43 +02:00
SebasKoedam
9795ccb490 removed unsed files 2024-05-23 18:09:19 +02:00
SebasKoedam
8cc571bb3b Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-23 15:51:34 +02:00
SebasKoedam
58f8ff0054 chore: Update activity_main.xml and misc.xml 2024-05-23 15:50:53 +02:00
b4a69ed975 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-23 15:31:45 +02:00
869164b2d6 docs about robotMovement 2024-05-23 15:31:30 +02:00
73f563249e fixed last error 2024-05-23 14:20:53 +02:00
3f6f61fb27 corrected pages 2024-05-23 14:09:01 +02:00
71871661ca Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-23 13:44:05 +02:00
062a793552 Updated pages 2024-05-23 13:43:55 +02:00
Niels
372beceeae spel fouten gefixt in persoonlijke reflectie 2024-05-22 17:20:35 +02:00
Niels
b0caed783f persoonlijke reflectie 2024-05-22 17:19:36 +02:00
9925fcd637 edited code for video 2024-05-22 15:50:43 +02:00
40cf9f37fc made video work using ffmpeg 2024-05-22 15:50:27 +02:00
Niels Gras
981b4670e3 Merge remote-tracking branch 'origin/main' 2024-05-22 15:06:37 +02:00
Niels Gras
390bd3c667 changed video format 2024-05-22 15:06:28 +02:00
6d79b0f762 kinda fix for main activity still needs better layout 2024-05-22 15:03:16 +02:00
Niels Gras
60747d07c5 Merge branch '55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik' into 'main'
Fixed crashing errors

Closes #55

See merge request propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66!11
2024-05-22 14:57:56 +02:00
Niels Gras
60fa1cec2c Fixed crashing errors 2024-05-22 14:47:01 +02:00
Niels Gras
54df52736f Merge branch '55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik' into 'main'
Resolve "Als gebruiker wil ik oefeningen te zien krijgen met een instructie video zodat ik weet wat ik moet doen"

Closes #55

See merge request propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66!9
2024-05-22 14:20:55 +02:00
Niels Gras
bc8763927b chore: Update background color in activity_fitness.xml 2024-05-22 14:20:26 +02:00
Niels Gras
5552865fd2 Merge branch '55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 into 55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik 2024-05-22 14:19:37 +02:00
Niels Gras
bcf394ef29 test 2024-05-22 14:12:29 +02:00
SebasKoedam
fdd67d3e7e stipje weggehaald 2024-05-22 11:54:21 +02:00
SebasKoedam
4a904be8f0 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-22 11:45:22 +02:00
SebasKoedam
904e4e98ed reflectie blok 1,2 en 3 skill ontwikkeling 2024-05-22 11:45:21 +02:00
Luca Warmenhoven
f72879d66e Merge remote-tracking branch 'origin/main' 2024-05-22 11:48:13 +03:00
Luca Warmenhoven
7064fa3b97 Updated PersonalMotionPreviewElement and FitnessActivity to match functionality 2024-05-22 11:48:02 +03:00
SebasKoedam
37ed64cd50 added daily tasks 2024-05-22 10:44:25 +02:00
Luca Warmenhoven
53d5e48b9b Merge remote-tracking branch 'origin/main'
# Conflicts:
#	code/src/Fitbot/app/src/main/java/com/example/fitbot/EndScreenActivity.java
#	code/src/Fitbot/app/src/main/java/com/example/fitbot/ui/activities/FitnessActivity.java
#	code/src/Fitbot/app/src/main/res/layout/activity_fitness.xml
2024-05-22 11:03:11 +03:00
Luca Warmenhoven
ccaf302558 store 2024-05-22 11:01:18 +03:00
Luca Warmenhoven
64412a849a store 2024-05-22 10:51:41 +03:00
Luca Warmenhoven
5432b0656e Added Skills Ontwikkelings Plan.docx 2024-05-22 10:42:34 +03:00
Luca Warmenhoven
03c14d12eb Merge remote-tracking branch 'origin/main' 2024-05-22 10:41:43 +03:00
Luca Warmenhoven
3826adb891 nonsense 2024-05-22 10:41:25 +03:00
f97686aa74 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-21 22:19:52 +02:00
cb3c4ca99f reflectieopdracht 2024-05-21 22:19:36 +02:00
d1f5f76eea Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-21 22:16:28 +02:00
851541923c junk removal 2024-05-21 22:16:23 +02:00
Niels
bbe3a8127c Expert sprint 2 2024-05-21 17:43:24 +02:00
Niels Gras
5d966ea3b9 feat: Add personal reflection documentation for each block 2024-05-21 15:52:46 +02:00
f288535c44 Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 2024-05-21 15:34:12 +02:00
183d5b826b Research sensors 2024-05-21 15:34:09 +02:00
Niels Gras
fc06974af1 feat: Update import statement for EndScreenActivity in FitnessActivity 2024-05-21 15:25:23 +02:00
Niels Gras
831fd06489 refactor: Move EndScreenActivity to ui.activities package 2024-05-21 15:24:02 +02:00
Niels Gras
9f87fb5e6f Merge branch '55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik' into 'main'
Resolve "Als gebruiker wil ik oefeningen te zien krijgen met een instructie video zodat ik weet wat ik moet doen"

Closes #55

See merge request propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66!4
2024-05-21 15:22:56 +02:00
Niels Gras
ab82bdce43 Fixed crashing errors 2024-05-21 15:20:41 +02:00
Niels Gras
1edaf096b2 feat: Add personal reflection documentation for each block 2024-05-21 14:26:00 +02:00
Niels Gras
af596ea67c Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 into 55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik 2024-05-21 14:21:05 +02:00
Niels Gras
d08e8dd50f added placeholder video 2024-05-21 14:20:22 +02:00
Niels Gras
f50f332664 added a ButtonNavigation class 2024-05-21 14:11:41 +02:00
8e92cbee7d Merge branch '51-als-gebruiker-wil-ik-dat-pepper-mee-beweegt-tijdens-oefeningen-zodat-ik-meer-motivatie-heb-om' 2024-05-21 13:50:50 +02:00
Niels Gras
d718046402 added video player and media player 2024-05-21 13:03:34 +02:00
bad3346475 fixed minsdk so it can actually be uploaded to robot 2024-05-21 12:54:20 +02:00
Niels Gras
e00b15480c Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 into 55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik 2024-05-21 12:49:43 +02:00
Niels Gras
a854c9b5e1 changed background 2024-05-21 12:48:43 +02:00
Luca Warmenhoven
0bdd1664dc crack cocaine and sport activities 2024-05-21 12:31:45 +02:00
Niels Gras
c398f8ff70 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 into 55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik 2024-05-21 12:14:43 +02:00
Niels Gras
3e791f8ac0 added skip button 2024-05-21 12:13:33 +02:00
Niels Gras
f87e4e5309 Fixed contrain 2024-05-17 16:06:02 +02:00
Niels Gras
a62c4e1b77 Fixed layout for fitness screen 2024-05-17 15:53:59 +02:00
Niels Gras
d0ed34ec95 Merge branch 'main' of ssh://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-4/muupooviixee66 into 55-als-gebruiker-wil-ik-oefeningen-te-zien-krijgen-met-een-instructie-video-zodat-ik-weet-wat-ik 2024-05-17 15:12:33 +02:00
Niels Gras
60bdf860d3 chore: Update activity_fitness.xml layout for Fitbot app 2024-05-17 15:11:42 +02:00
116 changed files with 3356 additions and 1884 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@
/.idea/modules.xml
/.idea/muupooviixee66.iml
/.idea/vcs.xml
/node_modules/

151
.idea/workspace.xml generated
View File

@@ -14,10 +14,10 @@
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="00599d5b-7eb5-44da-ad7f-98bf42384c16" name="Changes" comment="Final update onderzoek-formulier.md" />
<list default="true" id="00599d5b-7eb5-44da-ad7f-98bf42384c16" name="Changes" comment="Updated onderzoek-voorbeeld.md &amp; motion-tracking-system-analysis.md">
<list default="true" id="00599d5b-7eb5-44da-ad7f-98bf42384c16" name="Changes" comment="Crack butt">
<change afterPath="$PROJECT_DIR$/code/web/pepper_data_test.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/docs/documentation/research-questions/motion-tracking-system-analysis.md" beforeDir="false" afterPath="$PROJECT_DIR$/docs/documentation/research-questions/motion-tracking-system-analysis.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/code/web/incoming_request_handlers.js" beforeDir="false" afterPath="$PROJECT_DIR$/code/web/incoming_request_handlers.js" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -27,7 +27,6 @@
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[C:\Users\Niels\.android\avd\Pepper_1.9_API_29.avd]" />
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
@@ -50,6 +49,8 @@
<list>
<option value="Interface" />
<option value="Class" />
<option value="package.json" />
<option value="JavaScript File" />
</list>
</option>
</component>
@@ -75,6 +76,9 @@
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 5
}</component>
<component name="ProjectId" id="2fE3N2CwEPDo9wBtexBLxU20tCJ" />
<component name="ProjectLevelVcsManager">
<ConfirmationsSetting value="2" id="Add" />
@@ -83,42 +87,26 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="RunOnceActivity.cidr.known.project.marker" value="true" />
<property name="cidr.known.project.marker" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/code/src/Fitbot" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;Node.js.pepper_data_test.js.executor&quot;: &quot;Run&quot;,
&quot;git-widget-placeholder&quot;: &quot;main&quot;,
&quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;/Users/lucawarm/Jetbrains/Android Studio/muupooviixee66&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;preferences.lookFeel&quot;,
&quot;ts.external.directory.path&quot;: &quot;/Applications/WebStorm.app/Contents/plugins/javascript-plugin/jsLanguageServicesImpl/external&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="RunOnceActivity.cidr.known.project.marker" value="true" />
<property name="cidr.known.project.marker" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/code/src/Fitbot" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/code/src/app/src/main/java/com/fitbot" />
</key>
</component>
<component name="RunManager">
<component name="RunManager" selected="Node.js.pepper_data_test.js">
<configuration name="Fitbot" type="AndroidRunConfigurationType" factoryName="Android App">
<option name="DEPLOY" value="true" />
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
@@ -175,6 +163,14 @@
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
<method v="2" />
</configuration>
<configuration name="pepper_data_test.js" type="NodeJSConfigurationType" temporary="true" nameIsGenerated="true" path-to-js-file="$PROJECT_DIR$/code/web/pepper_data_test.js" working-dir="$PROJECT_DIR$/code/web">
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Node.js.pepper_data_test.js" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
@@ -202,6 +198,19 @@
<workItem from="1715765990621" duration="8538000" />
<workItem from="1715777647522" duration="725000" />
<workItem from="1715779408605" duration="3840000" />
<workItem from="1715957538891" duration="2000" />
<workItem from="1716126955744" duration="1102000" />
<workItem from="1716286107331" duration="6057000" />
<workItem from="1716308427931" duration="28000" />
<workItem from="1716318640952" duration="7000" />
<workItem from="1716363591734" duration="658000" />
<workItem from="1716538507910" duration="2194000" />
<workItem from="1716547378856" duration="243000" />
<workItem from="1716648462646" duration="8555000" />
<workItem from="1716674767699" duration="21000" />
<workItem from="1716889548355" duration="3475000" />
<workItem from="1716904079045" duration="2259000" />
<workItem from="1716977405893" duration="336000" />
</task>
<task id="LOCAL-00001" summary="Changes">
<created>1713528225837</created>
@@ -295,7 +304,87 @@
<option name="project" value="LOCAL" />
<updated>1715780873394</updated>
</task>
<option name="localTasksCounter" value="13" />
<task id="LOCAL-00013" summary="Merge">
<option name="closed" value="true" />
<created>1715951036170</created>
<option name="number" value="00013" />
<option name="presentableId" value="LOCAL-00013" />
<option name="project" value="LOCAL" />
<updated>1715951036170</updated>
</task>
<task id="LOCAL-00014" summary="nonsense">
<option name="closed" value="true" />
<created>1716363685668</created>
<option name="number" value="00014" />
<option name="presentableId" value="LOCAL-00014" />
<option name="project" value="LOCAL" />
<updated>1716363685669</updated>
</task>
<task id="LOCAL-00015" summary="Added Skills Ontwikkelings Plan.docx">
<option name="closed" value="true" />
<created>1716363757016</created>
<option name="number" value="00015" />
<option name="presentableId" value="LOCAL-00015" />
<option name="project" value="LOCAL" />
<updated>1716363757016</updated>
</task>
<task id="LOCAL-00016" summary="Added NodeJS Server files">
<option name="closed" value="true" />
<created>1716540796495</created>
<option name="number" value="00016" />
<option name="presentableId" value="LOCAL-00016" />
<option name="project" value="LOCAL" />
<updated>1716540796495</updated>
</task>
<task id="LOCAL-00017" summary="killed my brain doing literature">
<option name="closed" value="true" />
<created>1716658275320</created>
<option name="number" value="00017" />
<option name="presentableId" value="LOCAL-00017" />
<option name="project" value="LOCAL" />
<updated>1716658275320</updated>
</task>
<task id="LOCAL-00018" summary="updated gay">
<option name="closed" value="true" />
<created>1716658499589</created>
<option name="number" value="00018" />
<option name="presentableId" value="LOCAL-00018" />
<option name="project" value="LOCAL" />
<updated>1716658499589</updated>
</task>
<task id="LOCAL-00019" summary="Commit crack cocaine">
<option name="closed" value="true" />
<created>1716889664199</created>
<option name="number" value="00019" />
<option name="presentableId" value="LOCAL-00019" />
<option name="project" value="LOCAL" />
<updated>1716889664199</updated>
</task>
<task id="LOCAL-00020" summary="Commit war crimes in formal Yugoslavia">
<option name="closed" value="true" />
<created>1716890009616</created>
<option name="number" value="00020" />
<option name="presentableId" value="LOCAL-00020" />
<option name="project" value="LOCAL" />
<updated>1716890009616</updated>
</task>
<task id="LOCAL-00021" summary="Crack butt">
<option name="closed" value="true" />
<created>1716890828736</created>
<option name="number" value="00021" />
<option name="presentableId" value="LOCAL-00021" />
<option name="project" value="LOCAL" />
<updated>1716890828736</updated>
</task>
<task id="LOCAL-00022" summary="Crack butt">
<option name="closed" value="true" />
<created>1716891155110</created>
<option name="number" value="00022" />
<option name="presentableId" value="LOCAL-00022" />
<option name="project" value="LOCAL" />
<updated>1716891155110</updated>
</task>
<option name="localTasksCounter" value="23" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@@ -311,7 +400,6 @@
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="Changes" />
@@ -327,6 +415,15 @@
<MESSAGE value="Renamed files, added motion-tracking-system-analysis.md" />
<MESSAGE value="Updated onderzoek-voorbeeld.md and motion-tracking-system-analysis.md" />
<MESSAGE value="Updated onderzoek-voorbeeld.md &amp; motion-tracking-system-analysis.md" />
<option name="LAST_COMMIT_MESSAGE" value="Updated onderzoek-voorbeeld.md &amp; motion-tracking-system-analysis.md" />
<MESSAGE value="Merge" />
<MESSAGE value="nonsense" />
<MESSAGE value="Added Skills Ontwikkelings Plan.docx" />
<MESSAGE value="Added NodeJS Server files" />
<MESSAGE value="killed my brain doing literature" />
<MESSAGE value="updated gay" />
<MESSAGE value="Commit crack cocaine" />
<MESSAGE value="Commit war crimes in formal Yugoslavia" />
<MESSAGE value="Crack butt" />
<option name="LAST_COMMIT_MESSAGE" value="Crack butt" />
</component>
</project>

View File

@@ -4,7 +4,7 @@ void Connectivity::connectWiFi(char* ssid, char* pass){
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
Serial.println("connecting to wifi");
// Serial.println("connecting to wifi");
delay(1000);
}
Serial.println(WiFi.localIP());
@@ -20,4 +20,21 @@ void Connectivity::websocketSetup(char* ip, uint16_t port, char* adress){
void Connectivity::sendData(float roll, float pitch, float yaw){
String message = "{\"Sensor\": 1, \"roll\":\"" + String(roll) + "\",\"pitch\":\"" + String(pitch) + "\",\"yaw\":\"" + String(yaw) + "\"}";
webSocket.sendTXT(message);
}
/** Send a POST request to a server with provided data */
int Connectivity::httpPost(const char *serverAddress, const char *serverSubPath, const unsigned short serverPort,
const char *data, const size_t dataLength, const char *contentType)
{
if ( wifi_client.connect(serverAddress, serverPort)) {
wifi_client.printf("POST %s HTTP/1.1\r\n", serverSubPath);
wifi_client.printf("Content-Type: %s\r\n", contentType);
wifi_client.printf("Content-Length: %d\r\n", dataLength);
wifi_client.printf("Host: %s\r\n\n", serverAddress);
wifi_client.println(data);
wifi_client.stop();
return 0;
}
return 1;
}

View File

@@ -6,25 +6,25 @@
#include <ArduinoWiFiServer.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiGeneric.h>
#include <ESP8266WiFiGratuitous.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WiFiSTA.h>
#include <ESP8266WiFiScan.h>
#include <ESP8266WiFiType.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <WiFiServerSecure.h>
#include <WiFiUdp.h>
#include <WiFiClientSecure.h>
class Connectivity {
public:
void connectWiFi(char* ssid, char* pass);
void websocketSetup(char* ip, uint16_t port, char* adress);
void sendData(float roll, float pitch, float yaw);
int httpPost(const char *serverAddress, const char *serverSubPath, const unsigned short serverPort, const char *data, const size_t dataLength, const char *contentType);
private:
ESP8266WiFiMulti wifi;
WiFiClient wifi_client;
WebSocketsClient webSocket;
};
#endif

View File

@@ -1,62 +1,40 @@
#include "headerFile.h"
SensorManager::Rotation offset;
// SensorManager::Rotation offset;
void setup() {
Serial.begin(9600);
Serial.println("startup");
// Serial.begin(9600);
// Serial.println("startup");
//connect to internet and start sensor
connectivity.connectWiFi(ssid, pass);
sensorManager.sensorSetup();
//ws server address, port and URL
webSocket.begin("145.3.245.22", 8001, "");
// try every 500 again if connection has failed
webSocket.setReconnectInterval(500);
}
unsigned long lastTime = 0; // will store the last time the code was run
void loop() {
SensorManager::Rotation rotation = sensorManager.readLoop();
SensorManager::eulerAngles eulerRotation = sensorManager.getEulerAngles();
SensorManager::acceleration rotationAcceleration = sensorManager.getAcelleration();
// Subtract offset
rotation.i -= offset.i;
rotation.j -= offset.j;
rotation.k -= offset.k;
rotation.w -= offset.w;
// Convert quaternion to Euler angles in radians
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 yaw = atan2(2.0f * (rotation.w * rotation.k + rotation.i * rotation.j), 1.0f - 2.0f * (rotation.j * rotation.j + rotation.k * rotation.k));
// Convert to degrees
float rollDegrees = roll * 180.0f / PI;
float pitchDegrees = pitch * 180.0f / PI;
float yawDegrees = yaw * 180.0f / PI;
Serial.print(roll);
Serial.print(" ");
Serial.print(pitch);
Serial.print(" ");
Serial.print(yaw);
sendData(roll, pitch, yaw);
Serial.println();
webSocket.loop();
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim(); // remove any trailing whitespace
if (command == "setZeroPoint") {
setZeroPoint();
}
unsigned long currentTime = millis();
if (currentTime - lastTime >= 100) { // 100 ms has passed
memset(buffer, 0, BUFFER_SIZE);
sprintf(
buffer,
"{\"deviceId\": %d, \"rotationX\": %f, \"rotationY\": %f, \"rotationZ\": %f, \"accelerationX\": %f, \"accelerationY\": %f, \"accelerationZ\": %f, \"type\": %s}",
DEVICE_ID,
eulerRotation.roll,
eulerRotation.pitch,
eulerRotation.yaw,
rotationAcceleration.x,
rotationAcceleration.y,
rotationAcceleration.z,
"data");
// %d = int, %f = floatation, %s = string
connectivity.httpPost("192.168.137.45", "/", 3445, buffer, strlen(buffer), "application/json");
lastTime = currentTime;
}
}
void setZeroPoint() {
offset = sensorManager.readLoop();
}
void sendData(float roll, float pitch, float yaw){
String message = "{\"Sensor\": 1, \"roll\":\"" + String(roll) + "\",\"pitch\":\"" + String(pitch) + "\",\"yaw\":\"" + String(yaw) + "\"}";
webSocket.sendTXT(message);
}
//acceleration.X
//acceleration.Y
//acceleration.Z

View File

@@ -5,47 +5,67 @@
SensorManager::SensorManager() {}
void SensorManager::sensorSetup() {
Wire.setClockStretchLimit(150000L); // Default stretch limit 150mS
Wire.begin();
//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); //Increase I2C data rate to 400kHz
myIMU.calibrateAll(); //Turn on cal for Accel, Gyro, and Mag
myIMU.enableGyroIntegratedRotationVector(100); //send data every 100ms
myIMU.enableMagnetometer(100); //Send data update every 100ms
myIMU.saveCalibration(); //Saves the current dynamic calibration data (DCD) to memory
myIMU.requestCalibrationStatus(); //Sends command to get the latest calibration status
if (myIMU.calibrationComplete() == true) {
Serial.println("Calibration data successfully stored");
}
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
}
SensorManager::Rotation SensorManager::readLoop() {
//get sensordata
SensorManager::RotationQuintillions SensorManager::getQuintillions() {
if (myIMU.dataAvailable() == true) {
float i = myIMU.getQuatI();
float j = myIMU.getQuatJ();
float k = myIMU.getQuatK();
float w = myIMU.getQuatReal();
Rotation rotation = { i, j, k, w };
RotationQuintillions rotation = { i, j, k, w };
return rotation;
}
else {
} else {
float i = myIMU.getQuatI();
float j = myIMU.getQuatJ();
float k = myIMU.getQuatK();
float w = myIMU.getQuatReal();
Rotation rotation = { i, j, k, w };
RotationQuintillions rotation = { i, j, k, w };
return rotation;
}
}
//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));
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));
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 };
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

@@ -5,18 +5,32 @@
#include "SparkFun_BNO080_Arduino_Library.h"
class SensorManager {
public:
SensorManager();
void sensorSetup();
struct Rotation {
float i;
float j;
float k;
float w;
};
Rotation readLoop();
private:
BNO080 myIMU;
public:
SensorManager();
void sensorSetup();
struct eulerAngles {
float roll;
float pitch;
float yaw;
};
struct acceleration {
float x;
float y;
float z;
};
eulerAngles getEulerAngles();
acceleration getAcelleration();
bool sensorTap();
private:
struct RotationQuintillions {
float i;
float j;
float k;
float w;
};
RotationQuintillions getQuintillions();
BNO080 myIMU;
};
#endif

View File

@@ -8,6 +8,8 @@ Connectivity connectivity;
WebSocketsClient webSocket;
#define USE_SERIAL Serial
#define ssid "1235678i"
#define pass "12345678"
#define BUFFER_SIZE 1024
#define DEVICE_ID 1
char *buffer = (char *)malloc(sizeof(char) * BUFFER_SIZE);

View File

@@ -4,6 +4,8 @@
<option name="filePathToZoomLevelMap">
<map>
<entry key="../../../../../../../../layout/custom_preview.xml" value="0.35989583333333336" />
<entry key="../../../../../../.gradle/caches/transforms-3/9c4b978f8e84c8bb9ebef5f19e8c189e/transformed/qisdk-design-1.7.5/res/layout/activity_robot.xml" value="0.1" />
<entry key="../../../../../../.gradle/caches/transforms-3/9c4b978f8e84c8bb9ebef5f19e8c189e/transformed/qisdk-design-1.7.5/res/layout/view_always_top_speech_bar.xml" value="0.167877197265625" />
<entry key="..\:/Users/31687/muupooviixee66-1/code/src/Fitbot/app/src/main/res/drawable/button_background.xml" value="0.128" />
<entry key="..\:/Users/31687/muupooviixee66-1/code/src/Fitbot/app/src/main/res/drawable/rectangle.xml" value="0.128" />
<entry key="..\:/Users/31687/muupooviixee66-1/code/src/Fitbot/app/src/main/res/layout/activity_bicepvideo.xml" value="0.2015625" />
@@ -16,21 +18,31 @@
<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_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" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable-v24/ic_launcher_foreground.xml" value="0.25" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/box_background.xml" value="0.2555" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/darkred_button_gradient.xml" value="0.346" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/help2_background.xml" value="0.2395" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/help_background.xml" value="0.2395" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/ic_baseline_home_48.xml" value="0.25" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/ic_baseline_settings_48.xml" value="0.25" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/ic_baseline_star_rate_48.xml" value="0.25" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/ic_launcher_background.xml" value="0.25" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/rectangle.xml" value="0.2395" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/drawable/red_button_gradient.xml" value="0.346" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_bicepvideo.xml" value="0.22826086956521738" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_main.xml" value="0.176" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_end_screen.xml" value="0.4" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_fitness.xml" value="0.264" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_help.xml" value="0.4" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_main.xml" value="0.4" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_main_screen.xml" value="0.1" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_power_screen.xml" value="0.1" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/activity_sport_item.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/toolbar.xml" value="0.125" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/header.xml" value="0.264" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/layout/toolbar.xml" value="0.264" />
<entry key="..\:/Users/sebas/Documents/HvA/Reposetories/muupooviixee66/code/src/Fitbot/app/src/main/res/menu/main_menu.xml" value="0.4" />
<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_main.xml" value="0.1" />
<entry key="app/src/main/res/layout/activity_sport_item.xml" value="0.2341485507246377" />
@@ -40,6 +52,45 @@
</map>
</option>
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="androidx.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="12">
<item index="0" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="1" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="2" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="3" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
<item index="4" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
<item index="5" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="7" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="8" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="9" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="11" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="11">
<item index="0" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="1" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="2" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="5" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="7" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="8" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="9" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="10" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>

View File

@@ -7,7 +7,7 @@ android {
defaultConfig {
applicationId "com.example.fitbot"
minSdk 29
minSdk 23
targetSdk 29
versionCode 1
versionName "1.0"

View File

@@ -1,18 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.fitbot" >
package="com.example.fitbot">
<uses-feature android:name="com.softbank.hardware.pepper" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-feature
android:name="android.hardware.bluetooth"
android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
@@ -20,17 +24,19 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Fitbot" >
android:theme="@style/AppTheme">
<activity
android:name=".EndScreenActivity"
android:name=".ui.activities.HelpActivity"
android:exported="false" />
<activity
android:name=".ui.activities.EndScreenActivity"
android:exported="false" />
<activity
android:name=".ui.activities.FitnessActivity"
android:exported="true" />
<activity
android:name=".ui.activities.MainActivity"
android:exported="true" >
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

View File

@@ -1,34 +0,0 @@
/*
Copyright 2008 Nedim Jackman
This file is part of Wiiboard Simple
Wiiboard Simple is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Wiiboard Simple is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Wiiboard Simple. If not, see <http://www.gnu.org/licenses/>.
*/
package com.example.fitbot.bluetooth;
/**
* In very basic structure, all bluetooth devices have an address that the connection
* is associated with.
*/
public interface BluetoothDevice {
/**
* The fixed address of the device.
* Constant throughout the connection of the device.
*/
public String getBluetoothAddress();
}

View File

@@ -1,133 +0,0 @@
package com.example.fitbot.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.Context;
import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.UUID;
public class BluetoothManager {
private BluetoothAdapter bluetoothAdapter;
private Context context;
public BluetoothManager(Context context) {
this.context = context;
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public boolean isBluetoothSupported() {
return bluetoothAdapter != null;
}
public boolean isBluetoothEnabled() {
return bluetoothAdapter.isEnabled();
}
public void startDiscovery() {
if (!isBluetoothEnabled()) {
Log.e("BluetoothManager", "Bluetooth is not enabled");
return;
}
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
Log.d("BluetoothManager", "Cancelling current discovery process...");
}
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
context.registerReceiver(receiver, filter);
bluetoothAdapter.startDiscovery();
Log.d("BluetoothManager", "Starting discovery process...");
}
public final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getName() != null && device.getName().contains("Nintendo RVL-WBC-01")) {
Log.d("BluetoothManager", "Wii Balance Board found: " + device.getName() + " [" + device.getAddress() + "]");
connectToDevice(device);
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
context.unregisterReceiver(this);
Log.d("BluetoothManager", "Discovery finished.");
}
}
};
public void connectToDevice(BluetoothDevice device) {
new Thread(() -> {
BluetoothSocket socket = null;
final int MAX_RETRIES = 3;
final long RETRY_DELAY_MS = 1000;
boolean isConnected = false;
for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
socket = device.createRfcommSocketToServiceRecord(SPP_UUID);
bluetoothAdapter.cancelDiscovery();
byte[] pinBytes = getPinBytes(device.getAddress());
try {
Method setPinMethod = device.getClass().getDeclaredMethod("setPin", byte[].class);
setPinMethod.invoke(device, pinBytes);
Log.d("BluetoothManager", "PIN set successfully");
} catch (Exception e) {
Log.e("BluetoothManager", "Failed to set PIN", e);
}
socket.connect();
Log.d("BluetoothManager", "Connected to Wii Balance Board");
isConnected = true;
break;
} catch (IOException e) {
Log.e("BluetoothManager", "Connection attempt " + attempt + " failed", e);
if (attempt < MAX_RETRIES) {
try {
Thread.sleep(RETRY_DELAY_MS);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
break;
}
}
} finally {
if (!isConnected && socket != null) {
try {
socket.close();
} catch (IOException ex) {
Log.e("BluetoothManager", "Could not close the client socket", ex);
}
}
}
}
if (!isConnected) {
Log.e("BluetoothManager", "All connection attempts failed.");
}
}).start();
}
private byte[] getPinBytes(String address) {
String[] addrParts = address.split(":");
byte[] pin = new byte[addrParts.length];
for (int i = 0; i < addrParts.length; i++) {
pin[i] = (byte) Integer.parseInt(addrParts[addrParts.length - 1 - i], 16);
}
Log.i("BluetoothManager", "PIN: " + pin);
return pin;
}
}

View File

@@ -3,30 +3,44 @@ package com.example.fitbot.exercise;
import android.util.Log;
import com.example.fitbot.util.path.GesturePath;
import com.example.fitbot.util.server.IWebSocketHandler;
import com.example.fitbot.util.server.WebSocket;
import com.example.fitbot.util.processing.IMotionDataConsumer;
import com.example.fitbot.util.server.IWebServerHandler;
import com.example.fitbot.util.server.WebServer;
import java.util.Objects;
import java.util.function.Consumer;
public abstract class AbstractExercise implements IWebSocketHandler {
public class Exercise implements IWebServerHandler {
private EMuscleGroup muscleGroup;
private GesturePath path;
private GesturePath leftPath;
private GesturePath rightPath;
private String title;
private String description;
private float segmentsPerSecond;
// Static fields.
private static WebSocket webSocket;
private static AbstractExercise currentExercise = null;
private static WebServer webSocket;
private static Exercise currentExercise = null;
/**
* Constructor for the AbstractExercise class.
*
* @param muscleGroup The muscle group of the exercise.
* @param path The path of the exercise.
* @param leftPath The path of the left hand.
* @param rightPath The path of the right hand.
* @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 leftPath, GesturePath rightPath) {
this.muscleGroup = muscleGroup;
this.path = path;
this.title = title;
this.description = description;
this.leftPath = leftPath;
this.rightPath = rightPath;
}
/**
@@ -47,10 +61,9 @@ public abstract class AbstractExercise implements IWebSocketHandler {
}
try {
webSocket = WebSocket.createServer();
webSocket = WebServer.createServer();
Objects.requireNonNull(webSocket, "WebSocket server could not be created.");
webSocket.startListening();
webSocket.setEventHandler(this);
currentExercise = this;
} catch (Exception e) {
@@ -98,7 +111,27 @@ public abstract class AbstractExercise implements IWebSocketHandler {
/**
* Get the path of the exercise.
*/
public GesturePath getPath() {
return path;
public GesturePath[] getPath() {
return new GesturePath[]{leftPath, rightPath};
}
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
/**
* Get the speed of the exercise.
*/
public double getSegmentsPerSecond() {
return segmentsPerSecond;
}
@Override
public void onReceive(String message) {
}
}

View File

@@ -14,7 +14,7 @@ import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLConnection;
public class FitnessManager {
public class ExerciseManager {
private static final String HOST_ADDRESS = "http://145.92.8.132";
@@ -22,7 +22,20 @@ public class FitnessManager {
private static final String PROPERTY_VECTORS = "vector_data";
private static final String PROPERTY_NAME = "name";
private static final String PROPERTY_MUSCLE_GROUP = "muscle_group";
private static final String PROPERTY_SEGMENT_SPEED = "segment_speed";
private static final float DEFAULT_SEGMENT_SPEED = 1.0f;
/**
* Function for sending an HTTP request to the server.
*
* @param url The URL to send the request to.
* @param method The method to use for the request, e.g. GET or POST.
* @param contentType The content type of the request.
* @param body The body of the request.
*
* @return The response from the server.
*/
private static String sendHTTP(String url, String method, String contentType, String body) {
try {
URLConnection connection = new URL(url).openConnection();
@@ -50,7 +63,7 @@ public class FitnessManager {
* @param uniqueIdentifier The unique identifier of the exercise
* @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 Exercise retrieveExercise(String uniqueIdentifier) {
String response = sendHTTP(
HOST_ADDRESS + "/acquire", "GET", "application/json", "{\"kind\":\"" + uniqueIdentifier + "\"}"
);
@@ -58,17 +71,13 @@ public class FitnessManager {
if (response != null) {
try {
JsonObject content = JsonParser.parseString(response).getAsJsonObject();
Constructor<T> constructor = referenceClass.getConstructor(referenceClass);
T instance = null;
try {
instance = constructor.newInstance(
EMuscleGroup.parse(content.get(PROPERTY_MUSCLE_GROUP).getAsInt()),
gesturePathFromString(content.get(PROPERTY_VECTORS).getAsString())
);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
return new Exercise(
EMuscleGroup.parse(content.get(PROPERTY_MUSCLE_GROUP).getAsInt()),
content.get(PROPERTY_NAME).getAsString(),
content.get(PROPERTY_DESC).getAsString(),
gesturePathFromString(content.get(PROPERTY_VECTORS).getAsString()),
gesturePathFromString(content.get(PROPERTY_SEGMENT_SPEED).getAsString())
);
} catch (Exception e) {
e.printStackTrace();
}
@@ -79,7 +88,9 @@ public class FitnessManager {
/**
* Function for converting a string to a GesturePath object.
* The input string bytes will be directly converted into 3d vectors.
* Every coordinate is composed of 32 bits, so four characters per coordinate.
* Every scalar is composed of 32 bits (4 characters), meaning 96 bits per vector.
*
* Note: ASCII to Vector conversion is done in Big Endian format (most significant byte first).
*
* @param input The string to convert
* @return The GesturePath object
@@ -96,6 +107,7 @@ public class FitnessManager {
float[] xyz = new float[3];
for (int i = 0; i < bytes.length; i += 12) {
for (int j = 0; j < 3; j++) {
xyz[j] = Float.intBitsToFloat(
(bytes[i + j * 4] & 0xFF) << 24 |
(bytes[i + j * 4 + 1] & 0xFF) << 16 |

View File

@@ -1,43 +0,0 @@
package com.example.fitbot.speech;
import com.aldebaran.qi.sdk.QiContext;
import com.aldebaran.qi.sdk.builder.SayBuilder;
import com.aldebaran.qi.sdk.object.locale.Language;
import com.aldebaran.qi.sdk.object.locale.Locale;
import com.aldebaran.qi.sdk.object.locale.Region;
/**
* SpeechGenerator class for generating speech for the robot
*/
public class SpeechGenerator {
private static final Locale DUTCH_LOCALE = new Locale(Language.DUTCH, Region.NETHERLANDS);
private SayBuilder builder;
/**
* Function for making the robot say something with DUTCH_LOCALE as locale
* @param phrase The phrase to make the robot say
* @param ctx The QiContext to use
*/
public static void say(String phrase, QiContext ctx)
{
say(phrase, ctx, DUTCH_LOCALE);
}
/**
* Function for making the robot say something with a specific locale
* @param phrase The phrase to make the robot say
* @param ctx The QiContext to use
* @param locale The locale to use
*/
public static void say(String phrase, QiContext ctx, Locale locale)
{
SayBuilder
.with(ctx)
.withLocale(locale)
.withText(phrase)
.build()
.run();
}
}

View File

@@ -1,10 +1,10 @@
package com.example.fitbot;
package com.example.fitbot.ui.activities;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import com.example.fitbot.R;
import com.example.fitbot.ui.activities.FitnessActivity;
import com.example.fitbot.ui.activities.MainActivity;
public class EndScreenActivity extends AppCompatActivity {
@@ -13,12 +13,8 @@ public class EndScreenActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_end_screen);
Button homeButton = findViewById(R.id.homeButton);
homeButton.setOnClickListener(v -> {
Intent intent = new Intent(EndScreenActivity.this, MainActivity.class);
startActivity(intent);
finish();
});
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.homeButton, MainActivity.class);
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.continueButton, FitnessActivity.class);
}
}

View File

@@ -1,20 +1,80 @@
package com.example.fitbot.ui.activities;
import android.os.Bundle;
import android.util.Log;
import android.widget.VideoView;
import com.aldebaran.qi.sdk.QiContext;
import com.aldebaran.qi.sdk.QiSDK;
import com.aldebaran.qi.sdk.RobotLifecycleCallbacks;
import com.aldebaran.qi.sdk.design.activity.RobotActivity;
import com.aldebaran.qi.sdk.design.activity.conversationstatus.SpeechBarDisplayStrategy;
import com.example.fitbot.R;
import com.example.fitbot.exercise.EMuscleGroup;
import com.example.fitbot.exercise.Exercise;
import com.example.fitbot.ui.components.PersonalMotionPreviewElement;
import com.example.fitbot.util.ButtonNavigation;
import com.example.fitbot.util.FitnessCycle;
import com.example.fitbot.util.path.GesturePath;
import org.joml.Vector3f;
import java.util.concurrent.CompletableFuture;
public class FitnessActivity extends RobotActivity implements RobotLifecycleCallbacks {
PersonalMotionPreviewElement personalMotionPreviewElement;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
QiSDK.register(this, this);
setContentView(R.layout.activity_fitness);
// Remove the ugly ass bar on top of the view
setSpeechBarDisplayStrategy(SpeechBarDisplayStrategy.IMMERSIVE);
// Find the VideoView by its ID
VideoView videoView = findViewById(R.id.videoView);
FitnessCycle.playVideo(videoView, this);
ButtonNavigation.setupButtonNavigation(this, R.id.homeButton, MainActivity.class);
// Implement your logic when the robot focus is gained
GesturePath.Builder gesturePathBuilder = new GesturePath.Builder();
/* Generate a random path to test the tracking system */
for ( int i = 0; i < 40; i++)
{
gesturePathBuilder.addVector(
new Vector3f(
(float)Math.cos(Math.PI + (Math.PI / 40.0f) * i),
(float)Math.sin(Math.PI + (Math.PI / 40.0f) * i),
0
)
);
}
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(), gesturePathBuilder.build());
personalMotionPreviewElement.initialize(exercise);
});
}
@Override
public void onRobotFocusGained(QiContext qiContext) {
// Implement your logic when the robot focus is gained
// Find the VideoView by its ID
// CompletableFuture.runAsync(() -> FitnessCycle.executeMovement("bicepcurl", 10, qiContext));
Log.i("Motion", "qiContext provided");
personalMotionPreviewElement.provideQiContext(qiContext);
// FitnessCycle.playVideo(qiContext, videoView, this);
}
@Override
@@ -26,4 +86,11 @@ public class FitnessActivity extends RobotActivity implements RobotLifecycleCall
public void onRobotFocusRefused(String reason) {
// Implement your logic when the robot focus is refused
}
}
@Override
protected void onDestroy() {
super.onDestroy();
QiSDK.unregister(this, this);
this.personalMotionPreviewElement.onDestroy();
}
}

View File

@@ -0,0 +1,19 @@
package com.example.fitbot.ui.activities;
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 {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help);
ButtonNavigation.setupButtonNavigation(this, R.id.homeButton, MainActivity.class);
}
}

View File

@@ -2,35 +2,25 @@ package com.example.fitbot.ui.activities;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.bluetooth.BluetoothAdapter;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;
import com.example.fitbot.bluetooth.BluetoothDevice;
import com.example.fitbot.wiiboard.WiiBoard;
import com.example.fitbot.wiiboard.WiiBoardDiscoverer;
import com.example.fitbot.wiiboard.WiiBoardDiscoveryListener;
import com.example.fitbot.R;
import com.example.fitbot.util.ButtonNavigation;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_LOCATION_PERMISSION = 1;
private WiiBoardDiscoverer wiiBoardDiscoverer;
//Variables
// Variables
DrawerLayout drawerLayout;
NavigationView navigationView;
Toolbar toolbar;
@@ -38,53 +28,26 @@ public class MainActivity extends AppCompatActivity {
@SuppressLint("WrongViewCast")
@Override
protected void onCreate (Bundle savedInstanceState) {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main );
setContentView(R.layout.activity_main);
// Check if the device supports Bluetooth
if (BluetoothAdapter.getDefaultAdapter() == null) {
Log.i("WiiBoardDiscoverer", "Device doesn't support Bluetooth. Exiting.");
return;
}
// Set full screen mode
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
// Request location permissions for Bluetooth discovery on Android 6.0 and above
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
} else {
// Initialize WiiBoardDiscoverer
wiiBoardDiscoverer = new WiiBoardDiscoverer(this);
}
// Hide system UI
hideSystemUI();
setUpUi();
}
startButton = findViewById(R.id.startButton);
startButton.setOnClickListener(v -> {
Uri videoUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.bicepvideo);
Intent intent = new Intent(MainActivity.this, FitnessActivity.class);
intent.putExtra("videoUri", videoUri);
startActivity(intent);
});
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_LOCATION_PERMISSION && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted, initialize WiiBoardDiscoverer
wiiBoardDiscoverer = new WiiBoardDiscoverer(this);
} else {
// Handle the case where the user denies the location permission
Log.i("WiiBoardDiscoverer", "Location permission is required for Bluetooth discovery.");
}
}
@Override
protected void onResume() {
super.onResume();
if (wiiBoardDiscoverer != null) {
wiiBoardDiscoverer.startWiiBoardSearch();
}
}
@Override
protected void onPause() {
super.onPause();
if (wiiBoardDiscoverer != null) {
wiiBoardDiscoverer.stopWiiBoardSearch();
}
setUpUi(); // Set up the UI
}
private void setUpUi() {
@@ -94,32 +57,63 @@ 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);
});
// Hide the action bar
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
ButtonNavigation.setupButtonNavigation(this, R.id.startButton, FitnessActivity.class);
ButtonNavigation.setupButtonNavigation(this, R.id.helpButton, HelpActivity.class);
/*---Tool Bar---*/
// setSupportActionBar(toolbar);
setSupportActionBar(toolbar); // Make the toolbar act as the action bar
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(false); // Remove the title from the toolbar
}
/*---Navigation Drawer Menu---*/
navigationView.bringToFront();
navigationView.bringToFront(); // Make the navigation drawer menu clickable
ActionBarDrawerToggle toggle=new
ActionBarDrawerToggle(this,drawerLayout,toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
ActionBarDrawerToggle toggle = new // Create a toggle for the navigation drawer
ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
hideSystemUI();
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
hideSystemUI();
}
};
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
toggle.syncState(); // Synchronize the state of the navigation drawer
}
private void hideSystemUI() {
View decorView = getWindow().getDecorView();
// Hide the status bar and navigation bar
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
}
@Override
public void onBackPressed(){
if(drawerLayout.isDrawerOpen(GravityCompat.START)){
drawerLayout.closeDrawer(GravityCompat.START);
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
hideSystemUI();
}
else
{super.onBackPressed();
}
@Override
public void onBackPressed() { // Close the navigation drawer when the back button is pressed
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
}

View File

@@ -4,12 +4,14 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.aldebaran.qi.sdk.QiContext;
import com.example.fitbot.exercise.Exercise;
import com.example.fitbot.util.FitnessCycle;
import com.example.fitbot.util.path.GesturePath;
import com.example.fitbot.util.path.PathSegment;
import com.example.fitbot.util.processing.MotionData;
import com.example.fitbot.util.processing.MotionProcessor;
import org.joml.Matrix4f;
@@ -17,156 +19,214 @@ import org.joml.Vector2f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class PersonalMotionPreviewElement extends View {
private GesturePath path;
private double pathTime = 0.0D; // The timestamp at which the path is currently at.
private GesturePath[] paths;
private MotionProcessor motionProcessor;
private Path referencePath, performingPath;
private Paint referencePaint, performingPaint;
private Paint backgroundColor = new Paint();
private double pathTime = 0.0D; // The timestamp at which the path is currently at.
private final AtomicInteger exerciseProgress = new AtomicInteger(0); // The progress of the exercise. Ranges from 0 to 1000.
private QiContext qiContext;
private Exercise exercise;
private Path targetPath; // The path the user is supposed to follow.
private Path actualPath; // The path the user is currently following.
private final Paint referencePaint = new Paint();
private final Paint targetPaint = new Paint();
private final Paint backgroundColor = new Paint();
private Matrix4f modelMatrix = new Matrix4f(); // The model view matrix for the 3D to 2D transformation.
private Matrix4f viewMatrix = new Matrix4f()
.lookAt(new Vector3f(4, 4, 4), new Vector3f(0, 0, 0), new Vector3f(0, 1, 0)); // The view matrix for the 3D to 2D transformation.
private Matrix4f projectionMatrix = new Matrix4f(); // The projection matrix for the 3D to 2D transformation.
private final Vector4f objectPosition = new Vector4f(0, 0, 0, 1); // The location of the object in 3D space.
private ConcurrentLinkedQueue<Vector2f> vectors = new ConcurrentLinkedQueue<>();
private Vector2f[] axisVectors;
private static final String[] USER_PHRASES = {
"Veel success met de oefening!",
"Je kan het!",
"Veel plezier!"
};
private double timePassed = 0.0D; // The time that has passed since the start of the exercise, in seconds.
private long startingTime = 0L;
/**
* Constants for the preview path projection.
*/
private final float FOV = 70.0f; // The field of view of the preview path
private final float Z_NEAR = 0.1f; // The near 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 Vector2f screenDimensions = new Vector2f(); // Width and height dimensions of the screen
private Vector2f rotation = new Vector2f(); // Rotation vector (yaw, pitch)
/**
* Constructor for the PersonalMotionPreviewElement class.
*
* @param context The context in which this element is created.
* @param path The gesture path that will be drawn on the canvas.
*/
public PersonalMotionPreviewElement(Context context, GesturePath path) {
super(context);
Log.i("PersonalMotionPreviewElement", "Creating new PersonalMotionPreviewElement.");
this.backgroundColor = new Paint();
this.backgroundColor.setColor(0xFF000000); // Black
this.path = path;
this.motionProcessor = new MotionProcessor();
this.motionProcessor.startListening();
this.motionProcessor.setMotionDataEventHandler((processed, preprocessed, sampleIndex, sampleRate) -> {
// TODO: Implement the calculation of the `performingPath` based on the motion data
});
public PersonalMotionPreviewElement(Context context, AttributeSet attrs) {
super(context, attrs);
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.setColor(0xFFFF0000); // Red
this.referencePaint.setStyle(Paint.Style.FILL);
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);
this.referencePaint.setAntiAlias(true);
// Target paint is the filling of the target path.
this.targetPaint.setColor(-1);
this.targetPaint.setStyle(Paint.Style.STROKE);
this.targetPaint.setStrokeWidth(5.0f);
this.targetPaint.setAntiAlias(true);
}
/**
* Method that calculates the path that will be drawn on the
* canvas. This method will be called every time new motion data is received.
* 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.
*/
private void calculateDrawingPath(Vector3f transformedVector, MotionData motionData, int sampleIndex, double sampleRate) {
// Recalculate the personal path based on the new motion data
public void initialize(Exercise exercise) {
Log.i("PersonalMotionPreviewElement", "Creating new PersonalMotionPreviewElement.");
this.backgroundColor.setColor(0xFF000000); // Black
this.screenDimensions.x = this.getWidth();
this.screenDimensions.y = this.getHeight();
this.actualPath = new Path();
this.targetPath = new Path();
this.startingTime = System.nanoTime(); // Set the last time to the current time
this.exercise = exercise;
this.paths = exercise.getPath();
this.axisVectors = new Vector2f[] {
projectVertex(new Vector3f(-100.0f, 0, 0), getWidth(), getHeight()),
projectVertex(new Vector3f(100.0f, 0, 0), getWidth(), getHeight()),
projectVertex(new Vector3f(0, -100.0f, 0), getWidth(), getHeight()),
projectVertex(new Vector3f(0, 100.0f, 0), getWidth(), getHeight()),
projectVertex(new Vector3f(0, 0, -100.0f), getWidth(), getHeight()),
projectVertex(new Vector3f(0, 0, 100.0f), getWidth(), getHeight())
};
}
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.
* Also say something nice to the user :)
*
* @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();
// 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 + ")");
Vector2f parsed = projectVertex(processed, this.getWidth(), this.getHeight());
this.vectors.add(parsed);
// Remove the first element if the array is too big
if (this.vectors.size() > 100)
this.vectors.poll();
});
saySomethingNice();
}
/**
* Function to say something nice to the user :)
*/
private void saySomethingNice()
{
if (this.qiContext == null)
return;
FitnessCycle.say(USER_PHRASES[(int) Math.floor(Math.random() * USER_PHRASES.length)], this.qiContext);
}
/**
* Method for setting the gesture path that will be drawn on the canvas.
*
* @param path The gesture path to draw.
* @param exercise The exercise that the user is currently performing.
*/
public void setGesturePath(GesturePath path) {
this.path = path;
this.referencePath = getDrawablePath(path.getSegments());
public void setExercise(Exercise exercise) {
this.exercise = exercise;
}
/**
* Method for setting the rotation of the preview path.
*
* @param yaw The yaw rotation of the preview path.
* @param pitch The pitch rotation of the preview path.
*/
public void setRotation(float yaw, float pitch) {
this.rotation.set(Math.toRadians(yaw), Math.toRadians(pitch));
}
/**
* 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.
*
* @param point The point to cast to the screen.
* @param virtualWidth The width of the virtual screen.
* This is used to normalize the screen coordinates.
* @param virtualHeight The height of the virtual screen.
* @return The transformed vector in screen coordinates ranging from (0, 0) to (virtualWidth, virtualHeight).
*/
private Vector2f projectVertex(Vector3f point, int virtualWidth, int virtualHeight) {
modelMatrix
.identity()
.translate(-objectPosition.x, -objectPosition.y, -objectPosition.z);
Matrix4f modelViewMatrix = new Matrix4f()
.rotateX((float) Math.toRadians(rotation.x))
.rotateY((float) Math.toRadians(rotation.y))
.translate(cameraPosition);
// Transform the projection matrix to a perspective projection matrix
// Perspective transformation conserves the depth of the object
projectionMatrix
.identity()
.perspective((float) Math.toRadians(70), (float) virtualWidth / virtualHeight, .01f, 10000.0f);
Matrix4f projectionMatrix = new Matrix4f()
.perspective((float) Math.toRadians(FOV), (float) virtualWidth / virtualHeight, Z_NEAR, Z_FAR);
// Calculate Model-View-Projection matrix
Matrix4f MVP = new Matrix4f()
.set(projectionMatrix)
.mul(modelViewMatrix);
// Convert to screen coordinates
// Convert world coordinates to screen-space using MVP matrix
Vector4f screenCoordinates = new Vector4f(point, 1.0f)
.mul(MVP);
.mul(this.projectionMatrix)
.mul(this.viewMatrix)
.mul(this.modelMatrix);
// Normalize screen coordinates from (-1, 1) to (0, virtualWidth) and (0, virtualHeight)
float normalizedX = (screenCoordinates.x / screenCoordinates.w + 1.0f) * 0.5f * virtualWidth;
float normalizedY = (1.0f - screenCoordinates.y / screenCoordinates.w) * 0.5f * virtualHeight;
return new Vector2f(normalizedX, normalizedY);
}
/**
* 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.
*
* @param segments The path segments in the path.
* These segments will be connected by bezier curves, which
* all have unique curvature values.
* @return The generated path object.
*/
private Path getDrawablePath(PathSegment... segments) {
Path calculatedPath = new Path();
// Starting point
Vector2f origin = projectVertex(segments[0].getStart(), getWidth(), getHeight());
calculatedPath.moveTo(origin.x, origin.y);
// Draw the path segments
for (PathSegment segment : segments) {
Vector2f startProjected = projectVertex(segment.getStart(), getWidth()/2, getHeight());
Vector2f endProjected = projectVertex(segment.getEnd(), getWidth()/2, getHeight());
calculatedPath.lineTo(startProjected.x, startProjected.y);
calculatedPath.lineTo(endProjected.x, endProjected.y);
}
return calculatedPath;
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundColor);
// Draw the sport preview canvas
canvas.drawPath(referencePath, referencePaint);
canvas.drawPath(performingPath, performingPaint);
this.setBackgroundColor(0xFF000000); // Black
if (this.exercise == null)
return;
for (int i = 0; i < axisVectors.length/2; i++)
{
canvas.drawLine(axisVectors[i*2].x, axisVectors[i*2].y, axisVectors[i*2+1].x, axisVectors[i*2+1].y, this.targetPaint);
}
for ( Vector2f point : this.vectors)
{
canvas.drawRect(point.x, point.y, point.x + 5, point.y + 5, this.referencePaint);
}
/*
// 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();
timePassed = (System.nanoTime() - startingTime) / 1E9D;
}
}

View File

@@ -1,6 +1,7 @@
package com.example.fitbot;
//usage: PlayAnimation(animationfile, Qicontext);
// https://qisdk.softbankrobotics.com/sdk/doc/pepper-sdk/ch4_api/movement/reference/animation.html
import android.support.v7.app.AppCompatActivity;
package com.example.fitbot.util;
import com.aldebaran.qi.sdk.QiContext;
import com.aldebaran.qi.sdk.builder.AnimateBuilder;
@@ -8,15 +9,9 @@ import com.aldebaran.qi.sdk.builder.AnimationBuilder;
import com.aldebaran.qi.sdk.object.actuation.Animate;
import com.aldebaran.qi.sdk.object.actuation.Animation;
public class Animations extends AppCompatActivity {
public class Animations {
public static void Animate(String AnimationFile, QiContext ctx)
{
PlayAnimation(AnimationFile, ctx);
}
public static void PlayAnimation(String AnimationFile, QiContext ctx)
{
int resId = ctx.getResources().getIdentifier(AnimationFile, "raw", ctx.getPackageName());
@@ -30,5 +25,4 @@ public class Animations extends AppCompatActivity {
animate.async().run();
}
}

View File

@@ -0,0 +1,26 @@
package com.example.fitbot.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
public class ButtonNavigation {
/**
* Sets up a button to navigate to a different activity when clicked.
*
* @param currentActivity The activity that contains the button
* @param buttonId The ID of the button
* @param targetActivity The activity to navigate to
*/
public static void setupButtonNavigation(Activity currentActivity, int buttonId, Class<? extends Activity> targetActivity) {
Button button = currentActivity.findViewById(buttonId);
button.setOnClickListener(v -> {
Intent intent = new Intent(currentActivity, targetActivity);
currentActivity.startActivity(intent);
currentActivity.finish();
});
}
}

View File

@@ -0,0 +1,108 @@
package com.example.fitbot.util;
import android.content.Context;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.VideoView;
import com.aldebaran.qi.sdk.builder.SayBuilder;
import com.aldebaran.qi.sdk.object.locale.Language;
import com.aldebaran.qi.sdk.object.locale.Locale;
import com.aldebaran.qi.sdk.object.locale.Region;
import com.example.fitbot.R;
import com.aldebaran.qi.sdk.QiContext;
import com.aldebaran.qi.sdk.builder.AnimateBuilder;
import com.aldebaran.qi.sdk.builder.AnimationBuilder;
import com.aldebaran.qi.sdk.object.actuation.Animate;
import com.aldebaran.qi.sdk.object.actuation.Animation;
import java.util.concurrent.atomic.AtomicInteger;
public class FitnessCycle extends AppCompatActivity {
private static final Locale DUTCH_LOCALE = new Locale(Language.DUTCH, Region.NETHERLANDS);
/**
* Function for executing a movement animation a certain number of times
* on the robot
*
* @param Exercise The name of the exercise to perform
* @param Reps The number of repetitions to perform
* @param qiContext The QiContext to use
*/
public static void executeMovement(String Exercise, int Reps, QiContext qiContext) {
AtomicInteger repCount = new AtomicInteger(0);
Animation animation = AnimationBuilder.with(qiContext)
.withResources(qiContext.getResources().getIdentifier(Exercise, "raw", qiContext.getPackageName()))
.build();
Animate animate = AnimateBuilder.with(qiContext)
.withAnimation(animation)
.build();
// Add a listener for when a label is reached
animate.addOnLabelReachedListener((label, time) -> {
// Increment repCount when the end of a repetition is reached
if ("end".equals(label)) {
repCount.incrementAndGet();
}
});
// Run the animation the desired number of times
for (int i = 0; i < Reps; i++) {
animate.run();
}
}
/**
* Function for making the robot say something with DUTCH_LOCALE as locale
* @param phrase The phrase to make the robot say
* @param ctx The QiContext to use
*/
public static void say(String phrase, QiContext ctx)
{
say(phrase, ctx, DUTCH_LOCALE);
}
/**
* Function for making the robot say something with a specific locale
* @param phrase The phrase to make the robot say
* @param ctx The QiContext to use
* @param locale The locale to use
*/
public static void say(String phrase, QiContext ctx, Locale locale)
{
SayBuilder
.with(ctx)
.withLocale(locale)
.withText(phrase)
.build()
.run();
}
/**
* Function for playing a video in a VideoView
*
* @param videoView The VideoView to play the video in
* @param context The context to use
*/
public static void playVideo(VideoView videoView, Context context) {
// Set up the video player
if (videoView != null) {
Uri videoUri = Uri.parse("android.resource://" + context.getPackageName() + "/" + R.raw.bicepvideo);
videoView.setVideoURI(videoUri);
videoView.setOnCompletionListener(mp -> {
// Repeat the video when it finishes playing
videoView.start();
});
videoView.start();
} else {
Log.e("FitnessActivity", "VideoView is null. Check your layout XML.");
}
}
}

View File

@@ -11,17 +11,12 @@ public class GesturePath {
// The vectors that make up the path.
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.
*
* @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)
throw new IllegalArgumentException("A path must have at least two points.");
@@ -59,9 +54,11 @@ public class GesturePath {
if ( segments.length == 1)
return segments[0];
return Arrays
.stream(segments)
.reduce(segments[0], (a, b) -> PathSegment.closer(a, b, reference));
PathSegment closest = segments[0];
for ( int i = 1; i < segments.length; i++)
closest = PathSegment.closer(closest, segments[i], reference);
return closest;
}
/**

View File

@@ -11,6 +11,6 @@ public interface IMotionDataConsumer {
* @param sampleIndex The index of the current sample
* @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);
}

View File

@@ -8,6 +8,7 @@ public class MotionData {
// Data of the motion sensor
public Vector3f acceleration, rotation;
public int sensorId;
// Delimiter for the data received from the motion sensor
private static final String DATA_DELIMITER = ";";
@@ -21,10 +22,10 @@ public class MotionData {
* @param rotationX The rotation in the X axis in degrees.
* @param rotationY The rotation in the Y 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) {
this.acceleration = new Vector3f(accelerationX, accelerationY, accelerationZ);
this.rotation = new Vector3f(rotationX, rotationY, rotationZ);
public MotionData(float accelerationX, float accelerationY, float accelerationZ, float rotationX, float rotationY, float rotationZ, int sensorId) {
this(new Vector3f(accelerationX, accelerationY, accelerationZ), new Vector3f(rotationX, rotationY, rotationZ), sensorId);
}
/**
@@ -33,9 +34,10 @@ public class MotionData {
* @param acceleration The acceleration vector in m/s^2.
* @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.rotation = rotation;
this.sensorId = sensorId;
}
/**
@@ -50,7 +52,7 @@ public class MotionData {
Objects.requireNonNull(data); // Ensure data is not null
String[] parts = data.split(DATA_DELIMITER);
if (parts.length != 6)
if (parts.length != 7)
return null;
return new MotionData(
@@ -59,7 +61,8 @@ public class MotionData {
Float.parseFloat(parts[2]),
Float.parseFloat(parts[3]),
Float.parseFloat(parts[4]),
Float.parseFloat(parts[5])
Float.parseFloat(parts[5]),
Integer.parseInt(parts[6])
);
}
}

View File

@@ -3,10 +3,14 @@ package com.example.fitbot.util.processing;
import android.util.Log;
import com.example.fitbot.util.path.GesturePath;
import com.example.fitbot.util.server.IWebSocketHandler;
import com.example.fitbot.util.server.WebSocket;
import com.example.fitbot.util.server.WebServer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.jetbrains.annotations.NotNull;
import org.joml.Matrix3d;
import org.joml.Vector3d;
import org.joml.Vector3f;
import java.util.ArrayList;
@@ -17,14 +21,16 @@ public class MotionProcessor {
public static final String DELIMITER = ";";
private final List<MotionData> preprocessedData = new ArrayList<>(); // Preprocessed motion data
private final List<Vector3f> relativePath = new ArrayList<>(); // Relative path of the motion data
private final List<Vector3f> relativeLeftPath = new ArrayList<>(); // Relative path of the left motion data
private final List<Vector3f> relativeRightPath = new ArrayList<>(); // Relative path of the motion data
private Vector3f ZERO = new Vector3f(0, 0, 0);
private float sampleRate = 1.0F; // samples/second
private IMotionDataConsumer motionDataConsumer = (p1, p2, p3, p4) -> {};
private GesturePath path;
private WebSocket socket;
private final float sampleRate = 1.0f / 10.0F; // samples/second
private IMotionDataConsumer motionDataConsumer = (p1, p2, p3, p4, p5) -> { };
private WebServer server;
public MotionProcessor() {}
@@ -37,20 +43,14 @@ public class MotionProcessor {
*/
public void startListening() {
// Create socket server
this.socket = WebSocket.createServer();
this.server = WebServer.createServer();
Log.i("MotionProcessor", "Listening for incoming connections.");
// Check if the socket
if (socket != null) {
if (server != null) {
// Update event handler to match our functionality.
socket.setEventHandler(new IWebSocketHandler() {
@Override
public void onMessageReceived(WebSocket.Message message, WebSocket.MessageReply replier) {
parsePacket(message.message);
}
});
socket.startListening();
server.setEventHandler(this::parsePacket);
}
}
@@ -60,44 +60,58 @@ public class MotionProcessor {
* the WebSocket server.
*/
public void stopListening() {
if (socket != null) {
socket.stop();
if (server != null) {
server.stop();
}
}
/**
* Function for parsing arbitrary packet data.
*
* @param data The data to parse.
*/
public void parsePacket(@NotNull String data) {
// If the message starts with 'data', it's a data packet.
if ( data.startsWith("data")) {
Log.i("MotionProcessor", "Received data packet: " + data.split(" ")[1]);
MotionData parsedData = MotionData.decode(data.split(" ")[1]);
if (parsedData != null) {
addMotionData(parsedData);
}
// Otherwise check if it starts with 'calibrate', this is the ZERO point.
} else if ( data.startsWith("zero")) { // message to calibrate device
String[] vectorData = data.split(" ")[1].split(DELIMITER);
ZERO = new Vector3f(
Float.parseFloat(vectorData[0]),
Float.parseFloat(vectorData[1]),
Float.parseFloat(vectorData[2])
);
Log.i("MotionProcessor", "Device calibrated at " + ZERO.toString());
} else if ( data.startsWith("sampleRate")) {
this.sampleRate = Float.parseFloat(data.split(" ")[1]);
}
}
/**
* Function for setting the gesture path of the processor.
*
* @param path The path to set.
*/
public void setGesturePath(GesturePath path) {
this.path = path;
try {
Log.i("MotionProcessor", "Received packet data: " + data);
JsonElement json = JsonParser.parseString(data);
if (!json.isJsonObject())
return;
JsonObject object = json.getAsJsonObject();
String[] required = {
"rotationX", "rotationY", "rotationZ",
"accelerationX", "accelerationY", "accelerationZ",
"type",
"deviceId"
};
// Ensure all properties are present in the received JSON object
for (String s : required) {
if (!object.has(s))
return;
}
// Parse the data
Vector3f rotation = new Vector3f(object.get("rotationX").getAsFloat(), object.get("rotationY").getAsFloat(), object.get("rotationZ").getAsFloat());
Vector3f acceleration = new Vector3f(object.get("accelerationX").getAsFloat(), object.get("accelerationY").getAsFloat(), object.get("accelerationZ").getAsFloat());
int deviceId = object.get("deviceId").getAsInt();
String type = object.get("type").getAsString();
MotionData motionData = new MotionData(rotation, acceleration, deviceId);
if (type.equals("calibrate")) {
ZERO = getRelativeVector(motionData);
return;
}
addMotionData(motionData);
} catch (Exception e) {
Log.i("MotionProcessor", "Failed to parse packet data.");
}
}
/**
@@ -106,29 +120,35 @@ public class MotionProcessor {
* @param data The motion data to add.
*/
public void addMotionData(MotionData data) {
preprocessedData.add(data);
Vector3f previous = this.relativePath.isEmpty() ? ZERO : this.relativePath.get(this.relativePath.size() - 1);
List<Vector3f> target;
if (data.sensorId == 0)
target = relativeLeftPath;
else target = relativeRightPath;
Vector3f previous = target.isEmpty() ? ZERO : target.get(target.size() - 1);
Vector3f relativeVector = getRelativeVector(data).add(previous);
this.relativePath.add(relativeVector);
motionDataConsumer.accept(relativeVector, data, this.relativePath.size(), this.sampleRate);
target.add(relativeVector);
motionDataConsumer.accept(relativeVector, data, target.size(), this.sampleRate, data.sensorId);
}
/**
* Function for updating the relative path.
*
* @param relativePath The new relative path.
* @param relativeRightPath The new relative path.
*/
public void setRelativePath(List<Vector3f> relativePath) {
this.relativePath.clear();
this.relativePath.addAll(relativePath);
public void setRelativePaths(List<Vector3f> relativeLeftPath, List<Vector3f> relativeRightPath) {
this.relativeRightPath.clear();
this.relativeLeftPath.clear();
this.relativeLeftPath.addAll(relativeLeftPath);
this.relativeRightPath.addAll(relativeRightPath);
}
/**
* Function for setting the motion data receiver.
*
* @param consumer The consumer to set.
*/
public void setMotionDataEventHandler(IMotionDataConsumer consumer) {
if ( consumer != null)
if (consumer != null)
this.motionDataConsumer = consumer;
}
@@ -146,12 +166,16 @@ public class MotionProcessor {
// Rotate the acceleration vector back by the rotation vector to make it
// perpendicular to the gravity vector, then apply double integration to get the relative position.
// s = 1/2 * a * t^2
return motionData.acceleration
.rotateX(-motionData.rotation.x)
.rotateY(-motionData.rotation.y)
// Step 2: Create rotation matrices for each axis
// Step 4: Rotate the acceleration vector
return motionData.rotation
.mul(5);
/*return motionData.acceleration
.rotateZ(-motionData.rotation.z)
.div(2)
.mul(sampleRate * sampleRate);
.rotateY(-motionData.rotation.y)
.rotateX(-motionData.rotation.x)
.mul(sampleRate * sampleRate / 2);*/
}
/**
@@ -163,48 +187,21 @@ public class MotionProcessor {
*/
public List<Double> getErrors(GesturePath referencePath) {
// Return the errors of the relative path compared to the reference path.
return relativePath
.stream()
.map(referencePath::getError)
.collect(Collectors.toList());
}
/**
* Function for getting the error offsets of the motion data compared to the
* reference path.
*
* @return A list of error offsets of the motion data compared to the reference path.
* If no path is set, an empty list will be returned.
*/
public List<Double> getErrors() {
if ( path == null)
return new ArrayList<>();
return getErrors(path);
List<Double> errors = new ArrayList<>();
for (Vector3f vector : relativeRightPath) {
errors.add(referencePath.getError(vector));
}
return errors;
}
/**
* Function for getting the error of the motion data compared to the reference path.
*
* @param path The path to compare the motion data to.
* @param path The path to compare the motion data to.
* @param referencePoint The reference point to compare the motion data to.
* @return The error of the motion data compared to the reference path.
*/
public double getError(GesturePath path, Vector3f referencePoint)
{
return path.getError(referencePoint);
}
/**
* Function for getting the error of the provided vector and the set path.
* If no path is set, the error will be 0.
*
* @param referencePoint The reference point to compare the path data to.
* @return The error of the motion data compared to the reference path.
*/
public double getError(Vector3f referencePoint) {
if ( path == null)
return 0;
public double getError(GesturePath path, Vector3f referencePoint) {
return path.getError(referencePoint);
}
@@ -215,24 +212,12 @@ public class MotionProcessor {
* @param referencePath The reference path to compare the motion data to.
* @return The average error of the motion data compared to the reference path.
*/
public double getAverageError(GesturePath referencePath) {
return getErrors(referencePath)
.stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0.0D);
}
/**
* Function for calculating the average error of the motion data
* compared to the reference path.
*
* @return The average error of the motion data compared to the reference path.
*/
public double getAverageError() {
if ( path == null)
return 0;
return getAverageError(path);
public double getAverageError(GesturePath referencePath, int sensorId) {
double error = 0;
for (Double e : getErrors(referencePath)) {
error += e;
}
return error / Math.max(1, (sensorId == 0 ? relativeLeftPath : relativeRightPath).size());
}
/**
@@ -241,8 +226,7 @@ public class MotionProcessor {
* @param referencePath The reference path to compare the motion data to.
*/
public void logStatistics(GesturePath referencePath) {
Log.i("MotionProcessor", "Average path error: " + getAverageError(referencePath));
Log.i("MotionProcessor", "Path length: " + relativePath.size());
Log.i("MotionProcessor", "Path length: " + relativeRightPath.size());
Log.i("MotionProcessor", "Sample rate: " + sampleRate);
Log.i("MotionProcessor", "Calibration point: " + ZERO.toString());
}

View File

@@ -0,0 +1,11 @@
package com.example.fitbot.util.server;
import java.net.Socket;
/**
* Interface for handling WebSocket events.
*/
public interface IWebServerHandler {
void onReceive(String body);
}

View File

@@ -1,18 +0,0 @@
package com.example.fitbot.util.server;
import java.net.Socket;
/**
* Interface for handling WebSocket events.
*/
public interface IWebSocketHandler {
// Function for handling the connection of the WebSocket.
default void onConnected(Socket socket) {}
default void onDisconnected(Socket socket) {}
default void onMessageReceived(WebSocket.Message message, WebSocket.MessageReply replier) {}
default void onError(Socket socket, String error) {}
}

View File

@@ -0,0 +1,143 @@
package com.example.fitbot.util.server;
import android.util.Log;
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;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
public class WebServer implements Runnable {
private ServerSocket serverSocket;
protected IWebServerHandler eventHandler = (input) -> {}; // No-op.
private Thread thread;
private AtomicBoolean forceClose = new AtomicBoolean(false);
/**
* Constructor for creating a new WebSocket server.
*/
private WebServer() {
}
/**
* Function for creating a new WebSocket server given the provided port.
*
* @return A WebSocket connection, or null if something went wrong.
*/
public static WebServer createServer() {
try {
WebServer server = new WebServer();
server.serverSocket = new ServerSocket();
server.serverSocket.bind(new InetSocketAddress(3445));
server.serverSocket.setSoTimeout(0);
Log.i("WebServer", "Server created: " + server.serverSocket.getLocalSocketAddress() + ", " + server.serverSocket.getLocalPort());
server.thread = new Thread(server);
server.thread.start();
return server;
} catch (IOException error) {
String cause = error.getMessage() == null ? "Unknown reason" : error.getMessage();
Log.e("WebServer", cause);
return null;
}
}
@Override
public void run() {
// Listen for new connections until the socket closes.
while (this.isConnected() && !this.forceClose.get()) {
try {
// 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));
StringBuilder builder = new StringBuilder();
String line;
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");
if ( data.length > 1) { // Check if the data is valid.
this.eventHandler.onReceive(data[1]);
}
} catch (IOException error) {
String reason = error.getMessage() == null ? "Unknown reason" : error.getMessage();
Log.e("WebServerConnectionHandler", "Error listening to Socket connections: " + reason);
break;
}
}
}
/**
* Method for stopping the WebSocket server.
*/
public void stop() {
try {
this.serverSocket.close();
this.forceClose.set(true);
} catch (IOException error) {
String cause = error.getMessage() == null ? "Unknown reason" : error.getMessage();
Log.e("WebServer", cause);
}
}
/**
* Method for setting the event handler for this WebSocket server.
*
* @param handler The handler to use. This handler will parse all events
* that occur in this WebSocket connection. The events are the followed:
* - onMessageReceived(Socket, String)
* - onConnected(Socket)
* - onDisconnected(Socket)
* - onError(Socket, String)
*/
public void setEventHandler(IWebServerHandler handler) {
this.eventHandler = handler;
}
/**
* Method for getting the ServerSocket connection
*
* @return The ServerSocket connection.
*/
public ServerSocket getSocket() {
return this.serverSocket;
}
/**
* Method for checking whether this WebSocket connection is connected.
*
* @return The connection status of the WebSocket.
*/
public boolean isConnected() {
return !this.serverSocket.isClosed();
}
}

View File

@@ -1,150 +0,0 @@
package com.example.fitbot.util.server;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class WebSocket {
private ServerSocket serverSocket;
private WebSocketConnectionHandler connectionHandler;
private final Set<Socket> clients = Collections.synchronizedSet(new HashSet<>());
protected IWebSocketHandler eventHandler = new IWebSocketHandler() {}; // NO-OP event handler.
/**
* Constructor for creating a new WebSocket server.
*/
private WebSocket() {}
/**
* Function for creating a new WebSocket server given the provided port.
* @return A WebSocket connection, or null if something went wrong.
*/
public static @Nullable WebSocket createServer() {
try {
WebSocket webSocket = new WebSocket();
webSocket.serverSocket = new ServerSocket();
webSocket.serverSocket.bind(webSocket.serverSocket.getLocalSocketAddress());
Log.i("WebSocket -- Creating new WebSocket server", "Server created: " + webSocket.serverSocket.getLocalSocketAddress() + ", " + webSocket.serverSocket.getLocalPort());
return webSocket;
} catch (IOException error)
{
String cause = error.getMessage() == null ? "Unknown reason" : error.getMessage();
Log.e("WebSocket -- Creating new WebSocket server", cause);
return null;
}
}
/**
* Method for listening for incoming connections.
*/
public void startListening() {
this.connectionHandler = new WebSocketConnectionHandler(this);
this.connectionHandler.listen();
}
/**
* Method for stopping the WebSocket server.
*/
public void stop() {
try {
this.serverSocket.close();
this.connectionHandler.stop();
} catch (IOException error) {
String cause = error.getMessage() == null ? "Unknown reason" : error.getMessage();
Log.e("WebSocket -- Closing server connection", cause);
}
}
/**
* Method for setting the event handler for this WebSocket server.
* @param handler The handler to use. This handler will parse all events
* that occur in this WebSocket connection. The events are the followed:
* - onMessageReceived(Socket, String)
* - onConnected(Socket)
* - onDisconnected(Socket)
* - onError(Socket, String)
*/
public void setEventHandler(IWebSocketHandler handler) {
this.eventHandler = handler;
}
/**
* Method for getting the ServerSocket connection
* @return The ServerSocket connection.
*/
public ServerSocket getSocket() {
return this.serverSocket;
}
/**
* Method for checking whether this WebSocket connection is connected.
* @return The connection status of the WebSocket.
*/
public boolean isConnected() {
return !this.serverSocket.isClosed();
}
/**
* Class representing a message received from a WebSocket connection.
*/
public static class Message {
// Enumerable representing message type (opcode).
public enum Opcode {
CONTINUING((byte) 0x0),
TEXT((byte) 0x1),
BINARY((byte) 0x2),
RES0((byte) 0x3), RES1((byte) 0x4), RES2((byte) 0x5), RES3((byte) 0x6), RES4((byte) 0x7),
CLOSE_CONNECTION((byte) 0x8),
PING((byte) 0x9),
PONG((byte) 0xA),
RES5((byte) 0xB), RES6((byte) 0xC), RES7((byte) 0xD), RES8((byte) 0xE), RES9((byte) 0xF);
byte opcode;
Opcode(final byte opcode) {
this.opcode = opcode;
}
/**
* Method for decoding the opcode of a message.
* @param opcode The opcode to decode.
* @return The message type.
*/
public static Opcode decode(byte opcode) {
return Opcode.values()[opcode & 0xF];
}
// Returns the opcode of this message type.
public byte getOpcode() { return this.opcode; }
}
public String message;
public WebSocketConnection connection;
/**
* Constructor for a WebSocket message.
* @param message The message that was sent
* @param connection The connection where the message came from.
*/
public Message(WebSocketConnection connection, String message) {
this.message = message;
this.connection = connection;
}
}
/**
* Interface for a message reply.
* This can be used for when a message has been received from a client
* to reply back to the client.
*/
public interface MessageReply {
void reply(String message);
}
}

View File

@@ -1,35 +0,0 @@
package com.example.fitbot.util.server;
import java.net.Socket;
public class WebSocketConnection {
private final WebSocket origin;
private final Socket socket;
/**
* Constructor for creating an arbitrary WebSocket connection (Client)
* @param connection The server connection
* @param socket The client socket
*/
public WebSocketConnection(WebSocket connection, Socket socket) {
this.origin = connection;
this.socket = socket;
}
/**
* Getter method for retrieving the WebSocket connection
* @return The WebSocket instance.
*/
public WebSocket getOrigin() {
return origin;
}
/**
* Getter method for retrieving the Client Socket connection.
* @return The Socket connection.
*/
public Socket getSocket() {
return socket;
}
}

View File

@@ -1,217 +0,0 @@
package com.example.fitbot.util.server;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WebSocketConnectionHandler implements Runnable {
private final WebSocket theSocket;
private List<Socket> clients = Collections.synchronizedList(new ArrayList<>());
private Thread thread;
private boolean forceClose = false;
/**
* Constructor for WebSocketConnectionHandler.
* This class handles all new incoming Socket connections.
*
* @param webSocket The socket to check for new connections.
*/
protected WebSocketConnectionHandler(WebSocket webSocket) {
this.theSocket = webSocket;
}
@Override
public void run() {
// Listen for new connections until the socket closes.
while (theSocket.isConnected()) {
try {
// Find a new connection
Socket newSocket = this.theSocket.getSocket().accept();
this.theSocket.eventHandler.onConnected(newSocket);
clients.add(newSocket);
InputStream streamIn = newSocket.getInputStream();
OutputStream streamOut = newSocket.getOutputStream();
// Check if the connection was successfully upgraded to WebSocket
if (upgradeConnection(streamIn, streamOut)) {
applyMessageDecoder(streamIn);
}
} catch (IOException error) {
String reason = error.getMessage() == null ? "Unknown reason" : error.getMessage();
Log.e("WebSocketConnectionHandler", "Error listening to Socket connections: " + reason);
break;
}
}
}
/**
* Method for upgrading a HTTP connection to a WebSocket connection.
* This checks whether the client sent a GET header and sends back
* the required headers to upgrade the connection.
* @param streamIn The InputStream of the client socket connection.
* @param streamOut The OutputStream of the client socket connection.
* @return Whether or not the connection was successfully upgraded.
*/
private boolean upgradeConnection(InputStream streamIn, OutputStream streamOut) {
Scanner scanner = new Scanner(streamIn, "UTF-8");
String data = scanner.useDelimiter("\\r\\n\\r\\n").next();
Matcher header = Pattern.compile("^GET").matcher(data);
// Check if the header contains the GET keyword
// If this is the case, upgrade the HTTP connection to WebSocket.
if (!header.find())
return false;
Matcher match = Pattern.compile("Sec-WebSocket-Key: (.*)").matcher(data);
match.find(); // Get next match
try {
String SECAccept = Base64.getEncoder().encodeToString(
MessageDigest.getInstance("SHA-1").digest((match.group(1) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes(StandardCharsets.UTF_8)));
byte[] response = (
"HTTP/1.1 101 Switching Protocols\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: websocket\r\n" +
"Sec-WebSocket-Accept: " +
SECAccept + "\r\n\r\n").getBytes(StandardCharsets.UTF_8);
streamOut.write(response, 0, response.length);
} catch (IOException | NoSuchAlgorithmException error) {
Log.e("WebSocketConnectionHandler", "Failed upgrading HTTP to WebSocket connection" + error.getMessage());
return false;
}
return true;
}
/**
* Method for applying a message decoder for whenever a socket receives data.
* This method attemps to decode a message received from a WebSocket connection.
* This message is in the
* @param streamIn The message stream to decode.
*/
private void applyMessageDecoder(InputStream streamIn) {
// TODO: Implement
}
/**
* Method for decoding an encoded WebSocket message
* @param bytes The message to decode, in UTF-8 format.
* @return The decoded message.
* @throws IllegalArgumentException When the `frame` content is in an incorrect format.
*/
public static String decodeWebSocketMessage(byte[] bytes) {
// Check if the packet isn't corrupted
if (bytes.length <= 2 || (bytes[0] & 0b1110) != 0)
throw new IllegalArgumentException("Attempted to decode corrupted WebSocket frame data");
WebSocket.Message.Opcode opcode = WebSocket.Message.Opcode.decode((byte) (bytes[0] & 0b11110000));
byte payloadLength = (byte) (bytes[1] & 0b01111111); // Payload size (7 bits)
boolean fin = (bytes[0] & 0b1) != 0; // Whether this is the whole message
boolean masked = (bytes[1] & 0b10000000) != 0; // Whether the 9th bit is masked
long extendedPayloadLength = 0;
int byteOffset = 2;
// Check whether the payload length is 16-bit
if (payloadLength == 126) {
// 16-bit extended payload length (byte 2 and 3)
extendedPayloadLength = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF);
byteOffset += 2;
// Check whether payload length is 64-bit
} else if (payloadLength == 127) {
// 64-bit extended payload length
for (int i = 0; i < 8; i++)
extendedPayloadLength |= (long) (bytes[2 + i] & 0xFF) << ((7 - i) * 8);
byteOffset += 8;
} else {
extendedPayloadLength = payloadLength;
}
byte[] maskingKey = null;
byte[] payloadData = new byte[(int) extendedPayloadLength];
// Check if the MASK bit was set, if so, copy the key to the `maskingKey` array.
if (masked) {
maskingKey = new byte[4];
System.arraycopy(bytes, byteOffset, maskingKey, 0, 4); // move mask bytes
byteOffset += 4;
}
// Copy payload bytes into `payloadData` array.
System.arraycopy(bytes, byteOffset, payloadData, 0, payloadData.length);
// If mask is present, decode the payload data with the mask.
if (masked)
for (int i = 0; i < payloadData.length; i++)
payloadData[i] ^= maskingKey[i % 4];
// Convert payload data to string
return new String(payloadData, StandardCharsets.UTF_8);
}
/**
* Method for checking whether the connection handler is actively listening.
* @return Whether it's listening.
*/
public boolean isActive() {
return this.thread.isAlive();
}
/**
* Method for listening to all new incoming socket connections.
*/
public void listen() {
this.thread = new Thread(this);
this.thread.start();
Log.i("WebSocketConnectionHandler", "Listening started.");
}
/**
* Method for stopping the connection handler.
*/
public void stop() {
// Close the socket connection if not already closed
if (!this.theSocket.getSocket().isClosed()) {
try {
this.theSocket.getSocket().close();
} catch (IOException error) {
Log.e("WebSocketConnectionHandler", "Failed to close the socket connection: " + error.getMessage());
}
}
// Interrupt the thread
this.thread.interrupt();
// Close all connections
this.clients.forEach(client -> {
try {
client.close();
} catch (IOException error) {
Log.e("WebSocketConnectionHandler", "Failed to close client: " + error.getMessage());
}
});
this.clients.clear();
Log.i("WebSocketConnectionHandler", "Listening stopped.");
}
}

View File

@@ -1,48 +0,0 @@
package com.example.fitbot.wiiboard;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Method;
public class WiiBoard {
private static final String TAG = "WiiBoard";
public static void connectToExtension(String address) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
BluetoothSocket socket = null;
final int maxTries = 3;
int currentTry = 0;
while (currentTry < maxTries) {
try {
// Use reflection to create a BluetoothSocket without UUID
Method m = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
socket = (BluetoothSocket) m.invoke(device, 1);
bluetoothAdapter.cancelDiscovery();
socket.connect();
Log.i(TAG, "Connected to WiiBoard");
// Handle your communication here
return; // Exit the method upon successful connection
} catch (Exception e) { // Catching Exception to handle reflection exceptions too
Log.e(TAG, "Attempt " + (currentTry + 1) + " failed to connect", e);
currentTry++;
try {
// Wait a bit before retrying
Thread.sleep(1000);
} catch (InterruptedException ie) {
Log.e(TAG, "Interrupted while waiting to retry connection", ie);
}
}
}
Log.e(TAG, "Could not connect to WiiBoard after " + maxTries + " attempts.");
}
}

View File

@@ -1,66 +0,0 @@
package com.example.fitbot.wiiboard;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
public class WiiBoardDiscoverer {
private BluetoothAdapter bluetoothAdapter;
private Context context;
private String discoveredAddress;
private boolean isSearching;
private final BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String name = device.getName();
if ("Nintendo RVL-WBC-01".equals(name)) {
discoveredAddress = device.getAddress();
Log.i("WiiBoardDiscoverer", "Discovered " + name + " " + discoveredAddress + ".");
isSearching = false;
bluetoothAdapter.cancelDiscovery();
context.unregisterReceiver(this); // Important to unregister
WiiBoard.connectToExtension(discoveredAddress);
}
}
}
};
public WiiBoardDiscoverer(Context context) {
this.context = context;
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Log.i("WiiBoardDiscoverer", "Device doesn't support Bluetooth. Exiting.");
System.exit(0);
}
}
public void startWiiBoardSearch() {
if (!isSearching && !bluetoothAdapter.isDiscovering()) {
isSearching = true;
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(receiver, filter);
bluetoothAdapter.startDiscovery();
Log.i("WiiBoardDiscoverer", "WiiBoard Discovery Started");
}
}
public void stopWiiBoardSearch() {
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
isSearching = false;
try {
context.unregisterReceiver(receiver);
} catch (IllegalArgumentException e) {
// This can happen if the receiver was not registered or already unregistered
Log.i("WiiBoardDiscoverer", "Receiver was not registered or already unregistered");
}
}
}

View File

@@ -1,13 +0,0 @@
package com.example.fitbot.wiiboard;
/**
* Implement this interface to be notified of WiiBoards that are connected to. Register your
* listener with an instance of WiiBoardDiscoverer.
*/
public interface WiiBoardDiscoveryListener {
/**
* Is called by a WiiBoardDiscoverer when a WiiBoard has been found and successfully connected to.
*/
public void wiiBoardDiscovered(WiiBoard wiiboard);
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/darkBlue" />
<stroke android:width="4dp" android:color="@color/white" />
<corners android:radius="8dp" />
</shape>

View File

@@ -2,11 +2,11 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:radius="20dp"
android:radius="15dp"
/>
<gradient
android:startColor="#660000"
android:endColor="#990000"
android:startColor="#990000"
android:endColor="#FF0000"
android:angle="90"/>
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/midBlue" />
<stroke android:width="2dp" android:color="#FF0000" />
<corners android:radius="10dp" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/lightBlue" />
<stroke android:width="2dp" android:color="#FF0000" />
<corners android:radius="20dp" />
</shape>

View File

@@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="?attr/colorControlNormal"
android:viewportHeight="24" android:viewportWidth="24"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview_background_shape">
<stroke android:width="2dp" android:color="#ff207d94" />
<padding android:left="2dp"
android:top="2dp"
android:right="2dp"
android:bottom="2dp" />
<corners android:radius="45dp" />
<solid android:color="#F0F0F0" />
</shape>

View File

@@ -9,4 +9,5 @@
android:startColor="#990000"
android:endColor="#FF0000"
android:angle="90"/>
</shape>

View File

@@ -1,79 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/red"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".EndScreenActivity">
android:background="@color/darkBlue"
tools:context=".ui.activities.HelpActivity">
<View
android:id="@+id/myRectangleView"
android:layout_width="720dp"
android:layout_height="270dp"
android:layout_marginStart="320dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="320dp"
android:layout_marginBottom="25dp"
android:background="@drawable/rectangle"
app:layout_constraintBottom_toTopOf="@+id/homeButton"
app:layout_constraintEnd_toEndOf="parent"
<LinearLayout
android:layout_width="800dp"
android:layout_height="450dp"
android:layout_marginStart="80dp"
android:layout_marginTop="24dp"
android:background="@drawable/help2_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:background="@drawable/help_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewTitleEndScreen"
style="@style/TextStyleTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/klaar" />
</LinearLayout>
<LinearLayout
android:layout_width="700dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:background="@drawable/help_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewDescriptionEndScreen"
style="@style/TextStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/voltooid" />
</LinearLayout>
<LinearLayout
android:layout_width="700dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:background="@drawable/help_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewScoreEndScreen"
style="@style/TextStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/score"
android:textAlignment="center"/>
</LinearLayout>
</LinearLayout>
<Button
android:id="@+id/homeButton"
style="@style/ButtonStyle"
android:layout_width="278dp"
android:layout_height="117dp"
android:layout_marginStart="501dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="501dp"
android:layout_marginBottom="50dp"
android:text="Home"
app:layout_constraintBottom_toTopOf="@+id/continueButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/myRectangleView" />
<Button
android:id="@+id/continueButton"
style="@style/ButtonStyle"
android:layout_width="280dp"
android:layout_height="120dp"
android:layout_marginStart="500dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="500dp"
android:layout_marginBottom="140dp"
android:text="Continue"
android:id="@+id/homeButtonEndScreen"
android:layout_width="150dp"
android:layout_height="75dp"
android:layout_marginEnd="280dp"
android:background="@drawable/red_button_gradient"
android:drawableTop="@drawable/ic_baseline_home_48"
android:drawableTint="@color/white"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/homeButton" />
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/gefeliciteerdText"
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_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/myRectangleView" />
<Button
android:id="@+id/startButtonEndScreen"
android:layout_width="150dp"
android:layout_height="75dp"
android:layout_marginStart="280dp"
android:background="@drawable/red_button_gradient"
android:text="@string/start"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="30sp"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/workoutText"
style="@style/TextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="u heeft de work out voltooid"
app:layout_constraintBottom_toBottomOf="@+id/myRectangleView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/myRectangleView" />
</android.support.constraint.ConstraintLayout>

View File

@@ -1,25 +1,56 @@
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#232323"
android:background="@color/darkBlue"
android:fitsSystemWindows="true"
tools:context=".ui.activities.FitnessActivity"
tools:openDrawer="start">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="900dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="30dp"
android:padding="15dp"
android:background="@drawable/help2_background"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.example.fitbot.ui.components.PersonalMotionPreviewElement
android:id="@+id/personalMotionPreviewElement"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<VideoView
android:id="@+id/videoView"
android:layout_width="400dp"
android:layout_height="400dp"
android:layout_marginStart="20dp"
/>
</LinearLayout>
<com.example.fitbot.ui.components.PersonalMotionPreviewElement
android:id="@+id/personalMotionPreviewElement"
android:layout_width="400dp"
android:layout_height="400dp"
android:layout_marginStart="20dp"
/>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
<Button
android:id="@+id/homeButtonFitness"
android:layout_width="150dp"
android:layout_height="75dp"
android:layout_marginStart="404dp"
android:background="@drawable/red_button_gradient"
android:drawableTop="@drawable/ic_baseline_home_48"
android:drawableTint="@color/white"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="SpeakableTextPresentCheck" />
</android.support.constraint.ConstraintLayout>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/darkBlue"
tools:context=".ui.activities.HelpActivity">
<Button
android:id="@+id/homeButtonHelp"
android:layout_width="150dp"
android:layout_height="75dp"
android:layout_marginStart="404dp"
android:layout_marginBottom="10dp"
android:background="@drawable/red_button_gradient"
android:drawableTop="@drawable/ic_baseline_home_48"
android:drawableTint="@color/white"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<LinearLayout
android:layout_width="800dp"
android:layout_height="450dp"
android:layout_marginStart="80dp"
android:layout_marginTop="24dp"
android:background="@drawable/help2_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:background="@drawable/help_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewTitleHelp"
style="@style/TextStyleTitle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/help" />
</LinearLayout>
<LinearLayout
android:layout_width="700dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:background="@drawable/help_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewStartHelp"
style="@style/TextStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/uitlegStart" />
</LinearLayout>
<LinearLayout
android:layout_width="700dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp"
android:background="@drawable/help_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textViewHomeHelp"
style="@style/TextStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/uitlegHome" />
</LinearLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

View File

@@ -4,91 +4,110 @@
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#232323"
android:fitsSystemWindows="true"
tools:context=".ui.activities.MainActivity"
tools:openDrawer="start">
<LinearLayout
<android.support.constraint.ConstraintLayout
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="horizontal">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
layout="@layout/toolbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="524dp"
android:layout_height="77dp"
android:layout_marginStart="378dp"
android:layout_marginTop="80dp"
android:text="@string/welkom_bij_fitbot"
android:textColor="@color/white"
android:textSize="64sp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="208dp"
android:layout_marginTop="120dp"
android:background="@drawable/box_background"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/textView3"
android:layout_width="510dp"
android:layout_height="39dp"
android:layout_marginStart="385dp"
android:layout_marginTop="0dp"
android:text="@string/robot_helpt"
android:textColor="@color/white"
android:textSize="32sp" />
<TextView
android:id="@+id/textViewWelkom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/welkom_bij_fitbot"
android:textColor="@color/white"
android:textSize="64sp" />
<TextView
android:id="@+id/textViewFit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/robot_helpt"
android:textColor="@color/white"
android:textSize="32sp"
android:translationX="8dp" />
</LinearLayout>
<Button
android:id="@+id/startButton"
android:layout_width="300dp"
android:layout_height="150dp"
android:layout_marginStart="490dp"
android:layout_marginTop="100dp"
android:id="@+id/startButtonMain"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_marginStart="368dp"
android:layout_marginTop="312dp"
android:background="@drawable/red_button_gradient"
android:text="@string/start"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="80sp"
android:textAllCaps="false"
android:background="@drawable/red_button_gradient"/>
android:gravity="center"
android:textAlignment="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/helpButton"
android:layout_width="160dp"
android:layout_height="80dp"
android:layout_marginStart="560dp"
android:layout_marginTop="20dp"
android:id="@+id/helpButtonMain"
android:layout_width="100dp"
android:layout_height="50dp"
android:layout_marginStart="420dp"
android:layout_marginTop="424dp"
android:background="@drawable/darkred_button_gradient"
android:text="@string/help"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="40sp"
android:textAllCaps="false"
android:background="@drawable/darkred_button_gradient"/>
android:gravity="center"
android:textAlignment="center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="375dp"
android:layout_height="375dp"
android:layout_marginStart="0dp"
android:layout_marginTop="-180dp"
app:srcCompat="@drawable/robot_logo_inverted"
android:contentDescription="@string/todo" />
android:id="@+id/imageViewRobotLogo"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="340dp"
android:contentDescription="@string/robot_logo"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/robot_logo_inverted" />
<!-- <Button-->
<!-- android:id="@+id/menu_switch_btn"-->
<!-- android:layout_width="200dp"-->
<!-- android:layout_height="50dp"-->
<!-- android:clickable="true"-->
<!-- android:text="Go to Sport Menu"-->
<!-- app:layout_constraintBottom_toBottomOf="parent"-->
<!-- app:layout_constraintLeft_toLeftOf="parent"-->
<!-- android:focusable="true" />-->
</LinearLayout>
</android.support.constraint.ConstraintLayout>
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/darkBlue"
app:headerLayout="@layout/header"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
app:menu="@menu/main_menu" />
</android.support.v4.widget.DrawerLayout>

View File

@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="200dp"
android:orientation="vertical"
android:orientation="horizontal"
android:background="@drawable/ic_launcher_background"
android:layout_gravity="top"
android:padding="10dp">
@@ -25,6 +24,7 @@
android:layout_marginTop="60dp"
android:text="FitBot"
android:textSize="48sp"
android:textColor="@color/darkBlue"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent" />

View File

@@ -4,6 +4,5 @@
android:layout_height="wrap_content"
android:background="#00000000"
android:elevation="8dp"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
android:theme="@style/ToolbarNav">
</android.support.v7.widget.Toolbar>

View File

@@ -12,20 +12,14 @@
<group android:checkableBehavior="single">
<item android:title="Options">
<menu>
<item
android:id="@+id/nav_settings"
android:icon="@drawable/ic_baseline_settings_48"
android:title="Settings" />
<item
android:id="@+id/nav_rate"
android:icon="@drawable/ic_baseline_star_rate_48"
android:title="Rate" />
</menu>
</item>
<item
android:id="@+id/nav_settings"
android:icon="@drawable/ic_baseline_settings_48"
android:title="Settings" />
<item
android:id="@+id/nav_rate"
android:icon="@drawable/ic_baseline_star_rate_48"
android:title="Rate" />
</group>

View File

@@ -2,7 +2,11 @@
<Animation xmlns:editor="http://www.ald.softbankrobotics.com/animation/editor" typeVersion="2.0" editor:fps="25">
<editor:clip editor:fps="25" editor:startFrame="24" editor:endFrame="79"/>
<ActuatorCurve fps="25" actuator="LShoulderPitch" mute="false" unit="degree">
<Key value="90.5273514" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="90.5273514" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="90.5273514" frame="10">
@@ -14,7 +18,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="LShoulderRoll" mute="false" unit="degree">
<Key value="6.67969275" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="89.5" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="6.67969275" frame="10">
@@ -26,7 +34,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="LElbowYaw" mute="false" unit="degree">
<Key value="-69.7851486" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-69.7851486" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-69.7851486" frame="10">
@@ -38,7 +50,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="LElbowRoll" mute="false" unit="degree">
<Key value="-29.7070332" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-29.7070332" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-29.7070332" frame="10">
@@ -50,7 +66,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="LWristYaw" mute="false" unit="degree">
<Key value="-1.76023543" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-1.76023543" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-1.76023543" frame="10">
@@ -62,7 +82,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="LHand" mute="false" unit="dimensionless">
<Key value="0.589630966" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="0.589630966" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="0.589630966" frame="10">
@@ -74,7 +98,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="RShoulderPitch" mute="false" unit="degree">
<Key value="90.5273438" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="90.5273438" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="90.5273438" frame="10">
@@ -86,7 +114,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="RShoulderRoll" mute="false" unit="degree">
<Key value="-6.59180212" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-89.5" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="-6.59180212" frame="10">
@@ -98,7 +130,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="RElbowYaw" mute="false" unit="degree">
<Key value="70.2246094" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="70.2246094" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="70.2246094" frame="10">
@@ -110,7 +146,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="RElbowRoll" mute="false" unit="degree">
<Key value="29.7070332" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="29.7070332" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="29.7070332" frame="10">
@@ -122,7 +162,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="RWristYaw" mute="false" unit="degree">
<Key value="1.57964516" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="1.57964516" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="1.57964516" frame="10">
@@ -134,7 +178,11 @@
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="RHand" mute="false" unit="dimensionless">
<Key value="0.588752136" frame="0">
<Tangent side="right" abscissaParam="2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="0.588752136" frame="7">
<Tangent side="left" abscissaParam="-2.33333333" ordinateParam="0" editor:interpType="bezier_auto"/>
<Tangent side="right" abscissaParam="1" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
<Key value="0.588752136" frame="10">
@@ -145,4 +193,19 @@
<Tangent side="left" abscissaParam="-20" ordinateParam="0" editor:interpType="bezier_auto"/>
</Key>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="HeadYaw" mute="false" unit="degree">
<Key value="-0.439454377" frame="0"/>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="HeadPitch" mute="false" unit="degree">
<Key value="-12.1289139" frame="0"/>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="HipRoll" mute="false" unit="degree">
<Key value="-0.26367262" frame="0"/>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="HipPitch" mute="false" unit="degree">
<Key value="-1.49414492" frame="0"/>
</ActuatorCurve>
<ActuatorCurve fps="25" actuator="KneePitch" mute="false" unit="degree">
<Key value="0" frame="0"/>
</ActuatorCurve>
</Animation>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="PersonalMotionPreviewElement">
</declare-styleable>
</resources>

View File

@@ -7,4 +7,11 @@
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
<color name="darkBlue">#1C1C27</color>
<color name="midBlue">#24242F</color>
<color name="lightBlue">#2C2C37</color>
<color name="invertedBackground">#FFFFFF</color>
<color name="invertedTextColor">#000000</color>
<color name="invertedIconTint">#000000</color>
</resources>

View File

@@ -4,11 +4,23 @@
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Open navigation close</string>
<string name="welkom_bij_fitbot">Welkom bij FitBot</string>
<string name="robot_helpt">de robot die helpt om fit te blijven</string>
<string name="start">Start</string>
<string name="help">Help</string>
<string name="todo">TODO</string>
<color name="red">#f22b1d</color>
<string name="robot_logo" />
<string name="home">Home</string>
<string name="skip">Skip</string>
<string name="complete">Complete</string>
<string name="uitlegStart">Druk op Start om de oefening te beginnen</string>
<string name="uitlegHome">Ga terug naar het begin scherm door op het huisje te klikken</string>
<string name="klaar">Klaar!</string>
<string name="voltooid">U heeft de oefeningen voltooid, druk op start om nog een sessie te beginnen</string>
<string name="score">Score:</string>
</resources>

View File

@@ -2,11 +2,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:statusBarColor">#00000000</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:colorBackground">@color/darkBlue</item>
</style>
<style name="ToolbarNav" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:textColorSecondary">@color/white</item>
</style>
<style name="ButtonStyle">
@@ -19,10 +19,16 @@
</style>
<style name="TextStyle">
<item name="android:textSize">36sp</item>
<item name="android:textColor">#000000</item>
<item name="android:textSize">25sp</item>
<item name="android:textColor">#FFFFFF</item>
<item name= "android:textStyle">bold</item>
<item name="android:padding">6dp</item>
</style>
<style name="TextStyleTitle">
<item name="android:textSize">50sp</item>
<item name="android:textColor">#D3D3D3</item>
<item name= "android:textStyle">bold</item>
<item name="android:padding">6dp</item>
</style>
</resources>

View File

@@ -1,3 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Fitbot" parent="Theme.AppCompat.Light.NoActionBar">

View File

@@ -1,36 +0,0 @@
package com.example.fitbot;
import static org.junit.Assert.assertEquals;
import com.example.fitbot.util.server.WebSocketConnectionHandler;
import org.junit.Test;
/**
* Created on 07/05/2024 at 18:27
* by Luca Warmenhoven.
*/
public class WebSocketMessageParsingTest {
@Test
public void parseWebSocketMessage() {
String reference = "abcdef";
final byte[] encoded = {
(byte) 129, (byte) 134, (byte) 167,
(byte) 225, (byte) 225, (byte) 210,
(byte) 198, (byte) 131, (byte) 130,
(byte) 182, (byte) 194, (byte) 135
};
String decoded = "";
try {
decoded = WebSocketConnectionHandler.decodeWebSocketMessage(encoded);
} catch (Exception e) {
System.err.println("Error occurred whilst attempting to parse input" + e.getMessage());
}
assertEquals(reference, decoded);
}
}

View File

@@ -1,11 +1,71 @@
/**
*
* @param {Request} request The incoming request
* @param {Response} response The response to send back
* @param {Express} app Express app instance
* @param {Pool} pool MariaDB pool instance
*/
function handleIncoming(request, response, app, pool)
{
let query = 'SELECT * FROM Exercise WHERE ExerciseID = ?';
let parameters = [];
if (!request.hasOwnProperty('uid') || typeof request.uid !== 'number')
{
query = 'SELECT * FROM Exercise';
} else parameters.push(request.uid);
// Acquire database connection
pool.getConnection()
.then(conn => {
conn.query(query, parameters)
.then(rows => {
if (rows.length === 0)
{
response
.status(404)
.send(JSON.stringify({error: 'Exercise not found'}));
}
else
{
// Send back the data in the right format
let converted = rows.map(row => {
return {
name: row.Name,
description: row.Description,
muscleGroup: row.MuscleGroup,
imageUrl: row.ImageURL,
videoUrl: row.VideoURL
};
});
response
.status(200)
.send(JSON.stringify(converted));
}
})
.catch(error => {
console.log(error);
response
.status(500)
.send(JSON.stringify({error: 'Internal server error (Querying)'}));
})
.finally(() => {
conn.end();
});
})
.catch(error => {
console.log(error);
response
.status(500)
.send(JSON.stringify({error: 'Internal server error (Connection)'}));
});
// Om iets met de database te doen, is het handig om een functie te maken
// die een `app` parameter en een `pool` parameter accepteert.
// Deze moet dan geëxporteerd worden om deze te kunnen gebruiken in `server.js`.
// Dit is een voorbeeld van hoe je dat zou kunnen doen:
// module.exports = function(app, pool) { ... }
}
// Export the function that registers the incoming request handlers
module.exports = function(app, pool) {
app.post('/', (req, res) => handleIncoming(req, res, app, pool));
};

View File

@@ -0,0 +1,24 @@
const address = 'http://145.92.8.135:3445/';
const data = {
rotationX: 1,
rotationY: .4,
rotationZ: .1,
accelerationX: 1,
accelerationY: 2,
accelerationZ: 4,
deviceId: 1,
type: 'data'
};
for ( let i = 0; i < 10; i++)
{
setTimeout(() => {
console.log("Sending data");
fetch(address, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
}, i * 1000);
}

View File

@@ -1,25 +1,27 @@
const mariadb = require('mariadb');
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.json());
const serverPort = 3000;
const databaseCredentials = {
host: 'localhost',
host: '127.0.0.1',
user: 'fitbot',
password: 'fitbot123',
database: 'fitbot',
connectionLimit: 5,
allowUnauthorized: true
}
};
// Create connection pool
const pool = mariadb.createPool(databaseCredentials);
// Register incoming HTTP request handlers
require('incoming_request_handlers')(app, pool);
require('./incoming_request_handlers')(app, pool);
// Start server
app.listen(port, () => {
app.listen(serverPort, () => {
console.log(`Server running on port ${serverPort}`);
})
});

View File

@@ -18,14 +18,21 @@ nav:
- Android Studio: documentation/android/androidStudio
- app setup: documentation/android/appSetup
- video view: documentation/android/Videoview
- 🧠 Brianstorm:
- java classes: documentation/android/javaClasses
- robot motion tracking: documentation/android/robot_motion_tracking_system
- 🧠 Research:
- Ideas: documentation/brainstorm/ideas
- Motion tracking system analysis: documentation/research-questions/motion-tracking-system-analysis
- position tracking : documentation/research-questions/position-tracking-research
- robot comparison : documentation/robots/Comparisons
- Colors research : documentation/brainstorm/colorsforlayout
- 🗄️ Database:
- EERD: documentation/database/EERD
- ERD: documentation/database/ERD
- Infrastructure: documentation/database/infrastructure
- 📦 Hardware:
- Hardware: documentation/hardware/sensors
- Sensors: documentation/hardware/sensors
- Pcb : documentation/hardware/pcb
- 🤖 Pepper:
- Pepper Setup: documentation/pepper/pepperSetup
- Pepper movement: documentation/android/robotmovement
@@ -43,5 +50,8 @@ nav:
- phpMyAdmin:
- phpMyAdmin: documentation/raspberryPi/phpMyAdmin/phpMyAdmin
- phpMyAdmin Setup: documentation/raspberryPi/phpMyAdmin/phpMyAdminSetup
- 💻 Code documentation:
- Vector3 : documentation/android/code_documentation/Vector3
- Websocket : documentation/android/code_documentation/WebSocket

View File

@@ -2,7 +2,7 @@
We wanted to show the various exercises in a video that everyone could replicate. We did not want to implement a YouTube function because we wanted to have our own videos rather than relying on YouTube. To begin, we need an empty activity file, which you can create using the Android Studio IDE. Then, navigate to the XML file you just created and the go-to widgets, and add the VideoView element.
![VideoView](VideoViewWidget.png)
![VideoView](..\assets\VideoViewWidget.png)
If you drag that into your activity, you can change the layout, but it will not function directly. To make it play videos, we need to write some Java code first.
```java

View File

@@ -46,4 +46,8 @@ animate.async().run();
```
If you run this on the robot the animation should play.
If you run this on the robot the animation should play.
## Additional stuff
every 25 is 1 second so 100 is 4 seconds.
![alt text](../assets/robotanimationtimer.png)

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -2,7 +2,7 @@
### Vision changes
As we become older, our vision worsens. We need to keep this in mind because our target audience includes elderly people. Beginning around the age of 40 we are already seeing some issues with our sight. It might become harder to focus on text, hence the need for reading glasses. This is an issue to keep in mind when designing our app, we want to resolve this by using images or bigger text so that it becomes easier to read. We are planing to avoid redundant text. We also see issues with light. With aging our pupils will shrink, this will result in lower light sensitivity and the increased sensitivity to glare. We need to use warmer colors to reduce the brightness on the eye and make our app able to be used when the brightness of the screen is low to resolve this issue. However, one of the biggest issues is with contrast. The older we get, the less able we are able to make out of low contrast patterns. This is really important to keep in mind, some combinations can be really hard to see for elderly people. I'll show you how by providing an example.
![contrast](contrastcolors.png)
![contrast](../assets/contrastcolors.png)
This image shows what elderly people may experience while reading or using an app. We must keep this in mind as we design our app.
### color psychology
Colors can be an effective way to influence emotions and feelings. They may influence you without your knowledge. We can use this to influence those who use our app. Colors have a powerful ability to influence emotions. Every color has a unique effect on our minds. For example, blue has a calming and trustworthy effect on our minds. While blue may not be appropriate for our project, it may prove useful when using a more serious app. We can see PayPal using this trend because it is a banking app that must be trusted. Because blue influences those who use PayPal, it will have a positive impact on their customers. We also want to positively influence our people.
@@ -15,14 +15,14 @@ Colors can be an effective way to influence emotions and feelings. They may infl
Red is an interesting color because it increases excitement, activity, aggression, bravery, and youthfulness. People associate the color red with boldness, fire, competition, love, energy, speed, power, youth, and so much more. These emotions are useful when developing a fitness app, but even a different shade of red affects emotions and effectiveness. Lighter shades highlight the energetic qualities of red. Darker shades emphasize power. This makes red a powerful color and for us and an interesting option because Strava, a fitness app focused on running, uses the same colors.
![palettes of red](redpalette.png)
![palettes of red](../assets/redpalette.png)
<span style="color:ORANGE">
<strong> ORANGE: </strong>
</span>
Orange is a warm color that is a combination of red and yellow, making it a good middle ground between the two. Orange is an interesting color for our project because it promotes emotions like playful, warm, friendly, social, gregarious, cheerful, vibrant, confident, and successful. As we can see, there is a good balance of red and yellow emotions. People associate the color orange with extroversion, adventure, celebration, courage, confidence, good health, friendship, and success. This makes it a suitable choice for our project because it triggers most of the emotions we wanted. It is not as aggressive as red, but it basically has the same effect. Deeper oranges are warmer, while lighter tints make it feel more like yellow. We should consider orange for our app because it stimulates the desired emotions.
![palettes of orange](orangepalette.png)
![palettes of orange](../assets/orangepalette.png)
<span style="color:yellow">
<strong> YELLOW: </strong>
@@ -30,7 +30,7 @@ Orange is a warm color that is a combination of red and yellow, making it a good
Yellow belongs in the same park as red because they are both warm colors. Yellow boosts emotions such as warmth, cheerfulness, happiness, energy, clarity, and attention, making it a good choice for us to look at. People associate the color or yellow with. Sunshine, creativity, imagination, hope, joy, the future, and spirituality. The various shades affect yellow in different ways, and bright sharp yellows can be tiring and cause headaches. Lighter shades appeal to the happiness aspect, reminding users of summer and the sun. Darker shades, such as gold, add weight. This makes yellow an interesting color option for our app.
![palettes of yellow](yellowpalette.png)
![palettes of yellow](../assets/yellowpalette.png)
<span style="color:green">
<strong> GREEN: </strong>
@@ -39,28 +39,28 @@ Yellow belongs in the same park as red because they are both warm colors. Yellow
Green is on the opposite side of the spectrum from red and yellow. Green is a colder color, which gives it a different effect. Green enhances emotions such as restful, natural, stable, healthy, and prosperity. This can make it a viable option, especially because it gives people a sense of good health. People associate color green with. Freshness, ecology, nature, health, balance, fertility, growth, renewal, healing, money, and good luck. This is interesting because it not only provides people with the feeling of being healthy, but also of being outside in nature, which may help elderly people feel less isolated. However, the shades of green also make people feel different. Pale greens are soothing. Dark greens can improve concentration. However, because we do not rely on concetration, it will have little impact on our project.
![palletes of green](greenpalette.png)
![palletes of green](../assets/greenpalette.png)
<span style="color:BLUE">
<strong> BLUE: </strong>
</span>
Blue is also a colder color, so it takes the same path as green, giving it a more calming effect. However, it is not comparable to green because they influnce other emotions. Blue enhances emotions like calm, security, peace, patience, loyalty, trust, and sadness. It has the same soothing effect as green, but it does not give people the feeling of being healthy. It gives people trust and peace, which are interesting emotions, but they are not beneficial to us. People associate the color blue with stability, protection, trust, loyalty, patience, perseverance, security, peace, loyalty, sadness and depression, and masculinity. This further confirms that blue gives people a sense of security, which is not important for us because we want people to start exercising. Pale blue is cooling and relaxing, but it should not be used inappropriately because it can make people feel sad and depressed. Indigo is useful in situations where fear prevents activity. Indigo may be useful for a cool-down exercise or if someone is afraid of exercising.
![palletes of blue](bluepalette.png)
![palletes of blue](../assets/bluepalette.png)
<span style="color:Black">
<strong> BLACK: </strong>
</span>
Black is not a color but we can use this as the main tone for our app. However since old people tend to have issues when there isnt much light and black is the absence of light we are not very likely to sue it. Black boost emotions like Mysterious, elegant, sophisticated, worldly, powerful, strength, and intelligence. This makes black not that interesting for us since we want to make a simple app that everyone can understand. People associate the color black with Authority, sophistication, simplicity, protection, formality, elegance, night, power, and mystery. This is very intersting but not for our project since we do not desire people to associate our project with these emotions. If we tone the color black we get gray and white of which i will discuss the color white seperatly. Too much black can be frightening. Depressing unless used with other colors.
![palletes of black](blackpalette.png)
![palletes of black](../assets/blackpalette.png)
<span style="color:White">
<strong> WHITE: </strong>
</span>
White is not a color so it has the same purpose as black being a main tone to our app. White is a light tone which may cause it to glare. This means that you do not what to use the brightest types of screen with white. We do not have this issue so we can use white as much as wel like. White gives people the emotions of: fresh, pure, clear, easy, receptive, modern, neat, and precise. Since we are designing a simple app white is a nice main tone for our app. People associate white with Goodness, innocence, purity, cleanliness, calmness, freshness, healthiness, and precision. This further confirms that white is a good option for our app. However as i said Too bright white can produce eyestrain and headaches. Escpecially elderdly people are extra sensetive for this. So if we use white we need to be a little bit carefull whit it
![palletes of white](whitepalette.png)
![palletes of white](../assets/whitepalette.png)
### Conclusion
We decided to go for

View File

@@ -1,19 +1,45 @@
# Infrastructure
The infrastructure of the database is composed of the following components:
This document describes the infrastructure of the database and server components of the project.
- User
- Pepper
- Interface
- Robot
- Raspberry Pi
- Database
- MariaDB
- Server
- Apache
- phpMyAdmin
- Node.js
## Components
User interacts with Pepper through the interface. The interface sends the user input to the robot. The robot processes the input (java) and sends the output (xml) back to the interface. The interface displays the output to the user. The Raspberry Pi hosts the server and database. The database stores the data and the server hosts the website. The server runs Apache, phpMyAdmin, and Node.js. The interface makes a request to the server (HTTP GET) to retrieve the data in the database. The server processes the request (HTTP GET) and retrieves (SQL) the data from the database. The interface displays the data to the user.
The database component of the project consists of the following components:
- Node.js (Server)
- Apache2 (Web Server)
- phpMyAdmin (Database Management Tool)
- MariaDB (Database)
## Diagrams
Architecture application diagram of the project.
![Architecture application](../diagrams/assets/appDiagramV2.png)
Deyplomment application diagram of the project.
![Deyplomment application](../diagrams/assets/appDiagramV4.png)
## Database
The database component of the project is responsible for storing and managing the data used by the application. The database is implemented using MariaDB. The database is responsible for storing data such as exercises, names, descriptions, images, videos and exercise paths. The database is accessed by the server component of the project to retrieve data.
## Server
The server components of the project are responsible for handling requests from the client application and interacting with the database. The server is implemented using Node.js and is responsible for handling requests to retrieve exercises. The server is also responsible for serving the client application to the user.
The web server component of the project is implemented using Apache2 and is responsible for hosting phpMyAdmin, a database management tool used to interact with the database.
## Problems/Solutions
During the setup of the infrastructure, the following problems were encountered.
### Reverse proxy
The initial problem is that the Pi has a limeted amount of ports that can be used. This means that the server can only be accessed through port 80. This is a problem because the server is running on port 3000. To solve this problem, a reverse proxy was used to redirect traffic from port 80 to port 3000. This was done by creating a virtual host in the Apache2 configuration file that listens on port 80 and redirects traffic to port 3000.
When implementing the reverse proxy a problem was encountered where everything on port 80 was being redirected to port 3000. This was a problem because the server was also running on port 80. The initial solution was to remove the reverse proxy from sites-enabled and restart the server. However this caused the reverse proxy to stop working. Eventually it took too long to fix the problem and the reverse proxy was removed.
Running the server on port 443 was also considered as a solution. At the first sight this dind't seem possible since the access to port 443 is restricted. However, after some research it was found that it is possible to run the server on port 443 by starting the node with sudo. This was the solution that was chosen.
![Application Architecture Diagram](../diagrams/assets/appDiagram.png)

File diff suppressed because one or more lines are too long

View File

@@ -1,99 +1,105 @@
<mxfile host="Electron" modified="2024-05-17T10:24:38.560Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.2 Chrome/114.0.5735.289 Electron/25.9.4 Safari/537.36" etag="vTrgfPgpC1M9saCyJqTJ" version="22.1.2" type="device">
<mxfile host="Electron" modified="2024-05-29T11:03:46.287Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/22.1.2 Chrome/114.0.5735.289 Electron/25.9.4 Safari/537.36" etag="Sie7uAwi7Ncv96kRBi84" version="22.1.2" type="device">
<diagram name="Page-1" id="jecpyCyVafvbFtGhV645">
<mxGraphModel dx="1941" dy="638" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<mxGraphModel dx="2069" dy="713" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="JqL7afyQoL-OOYxCKZbi-2" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-2" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-390" y="240" width="430" height="430" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-34" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-34" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-360" y="420" width="161.25" height="230" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-1" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-690" y="240" width="220" height="160" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-10" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-10" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-640" y="300" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-3" value="Server Node (Raspberry Pi)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-3" value="Server Node (Raspberry Pi)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;" parent="1" vertex="1">
<mxGeometry x="-277.5" y="250" width="205" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-4" value="Client Node" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-4" value="Client Node (Pepper)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=16;" parent="1" vertex="1">
<mxGeometry x="-660" y="250" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-9" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;Android App&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-9" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;Android App&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-626.87" y="325" width="93.75" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-11" value="&amp;lt;&amp;lt;client&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-11" value="&amp;lt;&amp;lt;client&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-610" y="300" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-14" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-14" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-339.37" y="490" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-15" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;Apache2&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-15" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;Apache2&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-319.05" y="515" width="76.87" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-16" value="&amp;lt;&amp;lt;web server&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-16" value="&amp;lt;&amp;lt;web server&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-330.62" y="490" width="102.5" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-20" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-20" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-132.5" y="300" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-21" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;MariaDB&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-21" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;MariaDB&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-107.5" y="325" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-22" value="&amp;lt;&amp;lt;database&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-22" value="&amp;lt;&amp;lt;database&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-102.5" y="300" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="JqL7afyQoL-OOYxCKZbi-23" target="JqL7afyQoL-OOYxCKZbi-14">
<mxCell id="JqL7afyQoL-OOYxCKZbi-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="JqL7afyQoL-OOYxCKZbi-23" target="JqL7afyQoL-OOYxCKZbi-14" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-23" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="S5-NwbH-4CbKXiQop9ow-1" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JqL7afyQoL-OOYxCKZbi-34" target="JqL7afyQoL-OOYxCKZbi-20">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-23" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-340" y="570" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-24" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;phpMyAdmin&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-24" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;phpMyAdmin&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-330.62" y="600" width="97.5" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-25" value="&amp;lt;&amp;lt;DBMS&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-25" value="&amp;lt;&amp;lt;DBMS&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-310" y="570" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-26" value="" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-26" value="" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="-340" y="300" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-27" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;NodeJs&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-27" value="&lt;b style=&quot;font-size: 14px;&quot;&gt;&lt;font style=&quot;font-size: 14px;&quot;&gt;NodeJs&lt;/font&gt;&lt;/b&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;" parent="1" vertex="1">
<mxGeometry x="-307.5" y="325" width="57.5" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-28" value="&amp;lt;&amp;lt;server&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-28" value="&amp;lt;&amp;lt;server&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-310" y="300" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-32" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" edge="1" parent="1" source="JqL7afyQoL-OOYxCKZbi-9" target="JqL7afyQoL-OOYxCKZbi-27">
<mxCell id="JqL7afyQoL-OOYxCKZbi-32" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;" parent="1" source="JqL7afyQoL-OOYxCKZbi-9" target="JqL7afyQoL-OOYxCKZbi-27" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-450" y="370" as="sourcePoint" />
<mxPoint x="-400" y="320" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-33" value="HTTP&amp;nbsp;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-470" y="315" width="70" height="30" as="geometry" />
<mxCell id="JqL7afyQoL-OOYxCKZbi-33" value="HTTP POST&lt;br&gt;&lt;br&gt;JSON" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-466" y="325" width="76" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-35" value="Database Management" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-35" value="Database Management" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="-330.62" y="450" width="100" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-36" value="&amp;lt;&amp;lt;server&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-36" value="&amp;lt;&amp;lt;server&amp;gt;&amp;gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-310.62" y="420" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-39" value="Uses" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxCell id="JqL7afyQoL-OOYxCKZbi-39" value="Uses" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-288.12" y="545" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-40" value="Js/SQL" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-205" y="316" width="60" height="30" as="geometry" />
<mxCell id="JqL7afyQoL-OOYxCKZbi-40" value="Js/SQL&lt;br&gt;&lt;br&gt;JSON" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="1" vertex="1">
<mxGeometry x="-205" y="325" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="JqL7afyQoL-OOYxCKZbi-41" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="JqL7afyQoL-OOYxCKZbi-27" target="JqL7afyQoL-OOYxCKZbi-21">
<mxCell id="JqL7afyQoL-OOYxCKZbi-41" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="JqL7afyQoL-OOYxCKZbi-27" target="JqL7afyQoL-OOYxCKZbi-21" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="-200" y="410" as="sourcePoint" />
<mxPoint x="-150" y="360" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="S5-NwbH-4CbKXiQop9ow-4" value="Maneges" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="-167.5" y="505" width="60" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@@ -0,0 +1,4 @@
# Issues with hardware
## Issues with libraries
The websocket library doesnt work well on the esp8266 d1 mini. It lags out the entire esp and makes it unresponsive.

View File

@@ -7,19 +7,21 @@ Which sensor are we gonna use for this project and why?
We wanna measure the movement of the people doing our exercises. We want to know how many times they have done the exercise and how many times they have done it correctly.
### What sensor are we going to use?
To measure these movements we are gonna use gyroscopes. With gyroscopes we can measure the rotation of the body. With some math we can also measure the speed of the rotation. So we know how fast the person is doing the exercise.
### Which methods are there to measure this?
There are a lot of different ways to measure movement. You can use cameras, gyroscopes, accelerometers or a combination of these. Each of these methods have their own pros and cons. For example cameras are good at measuring movement but they require a lot of processing power and if the user turns the other way the camera cant measure the movement anymore. Accelerometers are good at measuring the movement of the body but they are not good at measuring the speed of the movement. Gyroscopes are good at everything because they can calculate how fast the body is moving and in which rotation.
### Which gyroscopes are there?
There are a lot of different gyroscopes with a lot of different specifications.
### What type of sensor are we going to use?
To measure these movements we are gonna use IMU's. They are a combination of accelerometers and gyroscopes. This way we can measure the movement of the body and the speed of the movement.
* ADXL345
### Which IMU's are there?
There are a lot of different IMU's with a lot of different specifications.
* ADXL345
* BNO085
* Bmi160
### Which one are we gonna use?
We haven't decided on which gyroscope we are gonna use yet.
We are going to use the BNO085 because it has the least amount of drift and its very versatile. We can get almost any type of rotational and acceleration data from it.
---
<br>
<br>

View File

@@ -0,0 +1,137 @@
## Hoe kunnen we voorkomen dat de privacy van ouderen geschonden wordt bij het inzetten van kunstmatige intelligentie om eenzaamheid te bestrijden?
#### Literatuuronderzoek door Luca Warmenhoven
---
### Inhoudsopgave
1. [Inleiding](#inleiding)
2. [Achtergrondinformatie](#achtergrondinformatie)
3. [Onderzoeksvraag en Relevantie](#onderzoeksvraag-en-relevantie)
4. [Onderzoeksmethode](#onderzoeksmethode)
5. [Wat zijn de belangrijkste factoren die bijdragen aan eenzaamheid onder ouderen?](#hoe-ontstaat-eenzaamheid-onder-ouderen)
6. [Op welke manier kunnen we kunstmatige intelligentie inzetten om eenzaamheid onder ouderen te bestrijden?](#op-welke-manier-kunnen-we-kunstmatige-intelligentie-inzetten-om-eenzaamheid-onder-ouderen-te-bestrijden)
7. [Wat zijn de risico's voor de privacy van ouderen wanneer robots voorzien van kunstmatige intelligentie worden ingezet in de ouderenzorg?](#wat-zijn-de-risicos-voor-de-privacy-van-ouderen-wanneer-robots-voorzien-van-kunstmatige-intelligentie-worden-ingezet-in-de-ouderenzorg)
8. [Hoe kunnen we ervoor zorgen dat privacy niet wordt geschonden bij het inzetten van kunstmatige intelligentie om eenzaamheid te bestrijden?](#hoe-kunnen-we-ervoor-zorgen-dat-privacy-niet-wordt-geschonden-bij-het-inzetten-van-kunstmatige-intelligentie-om-eenzaamheid-te-bestrijden)
9. [Conclusie](#conclusie)
10. [Bronnen](#bronnen)
---
### Inleiding
De eenzaamheid onder ouderen is een groeiend probleem dat ernstige gevolgen kan hebben op zowel hun fysieke als mentale
gezondheid. In een vergrijzende samenleving wordt het steeds belangrijker om effectieve oplossingen te vinden om
eenzaamheid onder deze kwetsbare bevolkingsgroep te bestrijden. Een van de veelbelovende innovaties op dit gebied is
het gebruik van kunstmatige intelligentie (KI) en robots in de ouderenzorg. Deze technologieën hebben het potentieel
om ouderen van sociaal contact en ondersteuning te voorzien. Echter, het inzetten van KI roept ook belangrijke
vragen op met betrekking tot de privacy van deze groep.
Het doel van dit onderzoek is om antwoord te geven op de vraag:
*"Hoe kunnen we voorkomen dat de privacy van ouderen geschonden wordt bij
het inzetten van kunstmatige intelligentie om eenzaamheid te bestrijden?"*
Om deze vraag te beantwoorden, zullen we eerst de belangrijkste factoren onderzoeken die bijdragen aan eenzaamheid
onder ouderen. Vervolgens zullen we verkennen hoe KI kan worden ingezet om eenzaamheid te verminderen. Daarna analyseren
we de risico's voor de privacy van ouderen bij het gebruik van KI en robots in de zorg, om tenslotte strategieën te
identificeren die ervoor zorgen dat de privacy van ouderen gewaarborgd blijft.
### Achtergrondinformatie
Eenzaamheid onder ouderen kan worden veroorzaakt door verschillende factoren zoals verlies van een partner,
gezondheidsproblemen, beperkte mobiliteit en sociale isolatie. KI-technologieën kunnen helpen om deze eenzaamheid te
verlichten door het bieden van virtuele gezelschap, sociale interactie en gepersonaliseerde zorg. Echter, het verzamelen
en verwerken van persoonlijke gegevens door KI-systemen brengt aanzienlijke privacyrisico's met zich mee, zoals
ongeautoriseerde toegang tot gevoelige informatie en onvoldoende gegevensbescherming.
### Onderzoeksvraag en Relevantie
Dit literatuuronderzoek richt zich op de vraag hoe we de privacy van ouderen kunnen beschermen bij het gebruik van KI
om eenzaamheid te bestrijden. Dit is van cruciaal belang omdat een gebrek aan adequate privacybescherming niet alleen
het vertrouwen in technologie kan ondermijnen, maar ook de effectiviteit van deze technologieën kan beperken.
### Onderzoeksmethode
Dit literatuuronderzoek is gebaseerd op een systematische analyse van wetenschappelijke artikelen, rapporten en
andere relevante bronnen over eenzaamheid onder ouderen, het gebruik van robots en KI in de ouderenzorg en
privacykwesties in de ouderenzorg. Het doel van dit onderzoek is om de lezer te voorzien van een overzicht van de
belangrijkste bevindingen en aanbevelingen op dit gebied.
---
### Wat zijn de belangrijkste factoren die bijdragen aan eenzaamheid onder ouderen?
Om erachter te hoe we eenzaamheid kunnen aanpakken is het noodzakelijk om te begrijpen waar het vandaan komt. Hierbij
is het belangrijk om te kijken naar wat voor factoren er meespelen in de levens van de ouderen die hieraan kunnen
bijdragen. Eenzaamheid kan zowel fysiek als mentaal zijn, dit betekent dat hoewel het persoon omringt kan zijn met
mensen, hij/zij nog steeds gevoelens van eenzaamheid kan ervaren. De oorzaak van emotionele eenzaamheid verschilt per
persoon, en valt niet zo gemakkelijk te verklaren, als te verhelpen. Bij fysieke eenzaamheid is het echter makkelijker
om erachter te komen waar het vandaan komt. Hierbij kunnen er andere omgevingsfactoren meespelen die ervoor zorgen dat
het persoon zich eenzaam voelt, denk hierbij aan het verlies van een partner of vrienden, familieproblematiek of acute
verandering van levensstijl ([1. SCP 2018](#bronnen)). Door dit soort veranderingen kan het zijn dat het persoon in een
depressie raakt, wat er weer voor kan zorgen dat het persoon zich eenzaam voelt, en dat het persoon zich nog meer
terugtrekt van de buitenwereld. Dit is een vicieuze cirkel die moeilijk te doorbreken is.
### Op welke manier kunnen we kunstmatige intelligentie inzetten om eenzaamheid onder ouderen te bestrijden?
In de laatste decennia is de technologie aanzienlijk geëvolueerd, wat heeft geleid tot bredere toepassingen ervan
in verschillende sectoren. Een van de sectoren waar technologie een grote rol kan spelen is de ouderenzorg.
Tegenwoordig worden robots steeds vaker ingezet in de ouderenzorg om ouderen te helpen met verschillende taken die
fysiek belastend kunnen zijn. Denk hierbij aan een robot die ouderen helpt met zichzelf wassen of met het nuttigen van
voedsel ([3. University of Japan, 2017](#bronnen)).
Naast fysieke taken kunnen robots voorzien van kunstmatige intelligentie ook ingezet worden om ouderen te helpen met
sociale interactie. Hierbij kan de robot conversaties voeren, verhalen vertellen of inhoudelijk reageren op vragen.
Onderzoek heeft aangetoond dat het toepassen van sociale robots in de ouderenzorg een positief effect kan hebben op
zowel cognitieve als emotionele gezondheid van ouderen ([4. University of Twente, 2020](#bronnen)).
Een van de voordelen van het inzetten van robots met kunstmatige intelligentie is dat ze 24/7 beschikbaar zijn en
gepersonaliseerde zorg kunnen bieden aan ouderen. Dit kan helpen om eenzaamheid te verminderen en ouderen te voorzien
van de nodige ondersteuning.
### Wat zijn de risico's voor de privacy van ouderen wanneer robots voorzien van kunstmatige intelligentie worden ingezet in de ouderenzorg?
Het inzetten van kunstmatige intelligentie in de ouderenzorg kan ook risico's met zich meebrengen voor de privacy van
ouderen. Een van de belangrijkste zorgen is het waarborgen van vertrouwelijke informatie over de ouderen in kwestie.
Indien de robots zijn voorzien van diverse sensoren en een internet verbinding, is het mogelijk dat de makers van de
robots deze informatie gebruiken om de robot te trainen om de reacties te personaliseren. Echter kan de inhoud van deze
data gevoelige informatie bevatten, zoals medische gegevens of financiële informatie. Het is daarom van groot belang
dat deze data goed beschermd wordt en dat ouderen controle hebben over hun eigen data ([5. KI, Privacy and Security, 2022](#bronnen)).
Een ander risico is dat de robots gehackt kunnen worden, wat ervoor kan zorgen dat de gevoelige informatie van ouderen
in verkeerde handen terecht komt. Daarom is het noodzakelijk dat er voldoende beveiligingsmaatregelen worden genomen
en/of dat de data op een veilige manier wordt opgeslagen ([6. Problematic Interactions between KI and Health Privacy, 2021](#bronnen)).
### Hoe kunnen we ervoor zorgen dat privacy niet wordt geschonden bij het inzetten van kunstmatige intelligentie om eenzaamheid te bestrijden?
Om ervoor te zorgen dat de privacy van ouderen niet geschonden wordt bij het inzetten van robots die zijn voorzien van
kunstmatige intelligentie is het belangrijk dat er voldoende maatregelen getroffen worden om de data van hen te
beschermen. Een van de manieren is om duidelijke richtlijnen op te stellen voor de makers van de robots, zodat er bekend
is welke data er verzameld mag worden en hoe zij hiermee moeten omgegaan. Daarnaast is het van belang dat ouderen
de optie hebben om zelf te bepalen welke data er verzameld mag worden en dat zij te allen tijde de controle hebben
over hun eigen data. Dit kan bijvoorbeeld door het instellen van duidelijk aangegeven privacy-instellingen op de robot
of door het aanbieden van een opt-out mogelijkheid ([5. KI, Privacy and Security, 2022](#bronnen)).
### Conclusie
Uit dit literatuuronderzoek blijkt dat eenzaamheid onder ouderen een behoorlijk complex probleem is met zowel fysieke
als mentale oorzaken, bijvoorbeeld door het verlies van een partner of door sociale isolatie. Daarnaast zijn we erachter
gekomen dat kunstmatige intelligentie (KI) en robots veelbelovende technologieën zijn die de ouderen kunnen helpen om
het gevoel van eenzaamheid te verminderen door het bieden van sociaal contact en ondersteuning. Echter kan het inzetten
van KI en robots ook risico's met zich meebrengen op het gebied van privacy, zoals ongeautoriseerde toegang tot
gevoelige informatie en onvoldoende gegevensbescherming. Om ervoor te zorgen dat de privacy van ouderen niet geschonden
wordt indien KI ingezet wordt om eenzaamheid te bestrijden, is het van belang dat er voldoende maatregelen getroffen
worden om de data van ouderen te beschermen en dat ouderen controle hebben over hoe er wordt omgegaan met hun data.
Kortom, het is van groot belang dat er genoeg richtlijnen en maatregelen getroffen worden om de privacy te waarborgen
voordat kunstmatige intelligentie ingezet kan worden als persoonlijke zorgverlener voor ouderen.
### Bronnen
1. [Eenzaamheid ouderen - SCP](https://repository.scp.nl/bitstream/handle/publications/393/Kwetsbaar%20en%20eenzaam.pdf?sequence=1&isAllowed=y)
2. [Cijfers eenzaamheid onder ouderen - Centraal Bureau van Statistiek](https://www.cbs.nl/nl-nl/nieuws/2023/38/bijna-70-procent-van-ouderen-heeft-minstens-elke-week-contact-met-de-buren)
3. [Inzetten robots in de ouderenzorg - University of Japan](https://digitcult.lim.di.unimi.it/index.php/dc/article/view/54)
4. [Effectiviteit robots in de ouderenzorg - University of Twente](https://essay.utwente.nl/92446/1/Watford-Spence_MA_Behavioural%2C%20Management%20and%20Social%20sciences.pdf)
5. [KI, Privacy and Security](https://www.frontiersin.org/articles/10.3389/frai.2022.826737/full)
6. [Problematic Interactions between KI and Health Privacy](https://heinonline.org/HOL/LandingPage?handle=hein.journals/utahlr2021&div=25&id=&page=)

View File

@@ -1,68 +0,0 @@
# Literatuuronderzoek Luca Warmenhoven
## Hoe kunnen we voorkomen dat de privacy van ouderen wordt geschonden bij het inzetten van kunstmatige intelligentie om eenzaamheid te bestrijden?
---
### Inhoudsopgave
1. [Inleiding](#inleiding)
2. [Hoe ontstaat eenzaamheid onder ouderen?](#hoe-ontstaat-eenzaamheid-onder-ouderen)
3. [Kan kunstmatige intelligentie ingezet worden om dit te verhelpen?](#op-welke-manier-kunnen-we-kunstmatige-intelligentie-inzetten-om-eenzaamheid-onder-ouderen-te-bestrijden)
4. [Hoe kunnen we ervoor zorgen dat de privacy van ouderen niet wordt geschonden?](#hoe-kunnen-we-ervoor-zorgen-dat-dit-gedaan-kan-worden-zonder-de-privacy-van-ouderen-te-schenden)
5. [Conclusie](#conclusie)
6. [Bronnen](#bronnen)
---
### Inleiding
Door de vergrijzing van de bevolking neemt het aantal ouderen in Nederland toe. Dit zorgt ervoor dat er steeds meer ouderen terecht komen in de verzorgingstehuizen.
Met een stijgende hoeveelheid ouderen in de verzorgingstehuizen zou je denken dat de eenzaamheid onder hen afneemt, maar dit is echter niet het geval.
Een manier om dit probleem op te lossen is door het inzetten van robots. Om deze robots nog capabeler te maken wordt er tegenwoordig ook gebruik gemaakt van kunstmatige
intelligentie. Dit komt echter ook met nadelen, zo kan het dat er informatie gedeeld wordt met de makers van de robots.
In dit onderzoek zal er gekeken worden of het mogelijk is om kunstmatige intelligentie toe te passen zonder dat dit ten koste gaat van de privacy van de ouderen.
### Wat zijn de belangrijkste factoren die bijdragen aan eenzaamheid onder ouderen?
Om te begrijpen hoe we eenzaamheid kunnen aanpakken is het noodzakelijk om te begrijpen waar het vandaan komt. Hierbij is het belangrijk om te kijken
naar wat voor factoren er meespelen in de levens van de ouderen die hieraan kunnen bijdragen. Eenzaamheid kan zowel fysiek als mentaal zijn, dit betekent
dat hoewel het persoon omringt kan zijn met mensen, hij/zij nog steeds gevoelens van eenzaamheid kan ervaren. De oorzaak van emotionele eenzaamheid verschilt
per persoon, en valt niet zo gemakkelijk te verklaren, als te verhelpen. Bij fysieke eenzaamheid is het echter makkelijker om te zien waar het vandaan komt.
Hierbij kunnen er andere omgevingsfactoren meespelen die ervoor zorgen dat het persoon zich eenzaam voelt,
denk hierbij aan het verlies van een partner of vrienden, familieproblematiek of acute verandering van levensstijl ([1. SCP 2018](#bronnen)).
Door dit soort veranderingen kan het zijn dat het persoon in een depressie raakt, wat er weer voor kan zorgen dat het persoon zich eenzaam voelt,
en dat het persoon zich nog meer terugtrekt van de buitenwereld. Dit is een vicieuze cirkel die moeilijk te doorbreken is.
Daarom is het belangrijk om te kijken of er ook methoden zijn om hierbij te helpen, zowel binnen als buitenhuis.
Doordat robots de laatste decennia steeds geavanceerder zijn geworden, is het mogelijk om te overwegen deze toe te passen
in de ouderenzorg om te helpen bij het eenzaamheidsprobleem. Robots worden de afgelopen jaren al steeds meer ingezet om ouderen te helpen
bij bepaalde dagelijkse problemen, zoals het wassen van ouderen in het bad, of het helpen bij eten consumeren ([3. University of Japan, 2017](#bronnen)).
Door de verbeteringen van technologie over de afgelopen jaren heeft K.I. ook een drastische verbetering ondergaan. Hierdoor valt er te overwegen
om deze toe te passen om te helpen met het eenzaamheidsprobleem bij ouderen.
### Op welke manier kunnen we kunstmatige intelligentie inzetten om eenzaamheid onder ouderen te bestrijden?
Zoals al eerder was vermeld worden robots al langer gebruikt bij het helpen van ouderen met huishoudelijke taken die voor hen te zwaar zijn.
Daarom valt het idee ook te overwegen om robots in te zetten om ouderen te helpen met het bestrijden van eenzaamheid. Hiervoor kan er
gebruik gemaakt worden van kunstmatige intelligentie. Kunstmatige intelligentie kan gebruikt worden om de robot te leren hoe het om moet gaan met
de gebruiker, om zowel te horen wat de gebruiker zegt, inhoudelijke reacties te geven op de gebruiker of om de gebruiker te helpen met bepaalde taken als ernaar
gevraagd wordt. Dit kan ervoor zorgen dat de ouderen zich minder eenzaam voelen, en dat ze zich meer op hun gemak voelen in hun eigen huis.
### Hoe kunnen we ervoor zorgen dat dit gedaan kan worden zonder de privacy van ouderen te schenden?
### Conclusie
### Bronnen
1. [Eenzaamheid ouderen](https://repository.scp.nl/bitstream/handle/publications/393/Kwetsbaar%20en%20eenzaam.pdf?sequence=1&isAllowed=y)
2. [Cijfers eenzaamheid onder ouderen](https://www.cbs.nl/nl-nl/nieuws/2023/38/bijna-70-procent-van-ouderen-heeft-minstens-elke-week-contact-met-de-buren)
3. [Inzetten robots in de ouderenzorg](https://digitcult.lim.di.unimi.it/index.php/dc/article/view/54)
4. [Effectiviteit robots in de ouderenzorg](https://essay.utwente.nl/92446/1/Watford-Spence_MA_Behavioural%2C%20Management%20and%20Social%20sciences.pdf)
5. [AI, Privacy and Security](https://www.frontiersin.org/articles/10.3389/frai.2022.826737/full)
6. [Problematic Interactions between AI and Health Privacy](https://heinonline.org/HOL/LandingPage?handle=hein.journals/utahlr2021&div=25&id=&page=)

View File

@@ -1,50 +0,0 @@
## Hoe kan technologie worden ingezet om cognitieve achteruitgang tegen te gaan?
### Welke oorzaken zijn er voor cognitieve achteruitgang?
### Wat voor methodes zijn er om cognitieve achteruitgang te remmen?
### Hoe kan techniek worden toegepast om
Inleiding: ~10%
Conclusie: ~10%
~300 woorden totaal
Minimaal 5 bronnen zoeken
## Hoe kunnen ethische richtlijnen worden ontwikkeld voor het toepassen van kunstmatige intelligentie bij het aanpakken van eenzaamheid onder ouderen?
---
### Inleiding
Kunstmatige intelligentie, het is tegenwoordig overal terug te vinden. Dit kan zowel door het gebruiken van ChatGPT om je
huiswerk te maken, als de muziek die Spotify je aanbeveelt, als de videos die je op het internet vindt. Overal zit tegenwoordig
kunstmatige intelligentie achter, om de gebruikerservaring door en door beter en makkelijker te maken. Toch zitten er ook mogelijke
nadelen achter, wat nou als K.I. mijn baan over zal nemen? Wat als K.I. een eigen wil krijgt en tegen ons keert? Hoe kan
K.I. onze privacy blijven respecteren? Dit zijn allemaal belangrijke vragen om over na te denken.
Om een beter plaatje te kunnen schetsen van dit soort vragen is het het best om ze een voor een te beantwoorden.
Daarom gaan we hierna verder op hoe we ervoor kunnen zorgen dat kunstmatige intelligentie onze privacy blijft respecteren en
of hier naleefbare regels voor gemaakt kunnen worden. Ook proberen we hier in te zien of kunstmatige intelligentie daadwerkelijk
een positieve impact kan maken voor ouderen die zich eenzaam voelen.
### Op welke manier kunnen we nauwkeurig en effectief meten of kunstmatige intelligentie het eenzaamheidsgevoel van ouderen kan verminderen?
### Wat voor ethische problemen kunnen er ontstaan zodra kunstmatige intelligentie wordt ingezet bij het aanpakken van eenzaamheid onder ouderen?
### Welke richtlijnen kunnen er worden opgesteld om deze problemen te voorkomen?
### Betrouwbaarheid bronnen:
Currency, Relevance, Authority, Accuracy, Purpose

View File

@@ -0,0 +1,62 @@
STARR
## Reflectie Opdracht Blok 1 - Climate Measuring Box
### Situatie
Voor het eerste blok was de opdracht het maken van een meetsysteem om bepaalde omgevingswaarden te meten, waarbij deze metingen
op een webpagina live weergeven worden.
Daarnaast moesten er ook bepaalde waarden gestuurd worden naar de HvA server, om deze vervolgens op de website op een map te weergeven.
Een voorbeeld van meetwaarden die gestuurd moesten worden waren temperatuur, luchtvochtigheid en lichtintensiteit.
### Taak
Als taak van dit project was het noodzakelijk om een hardware systeem te bouwen met behulp van de ESP32.
Hierbij was het nodig om meerdere sensoren te verbinden aan de ESP32 en deze sensoren uit te lezen.
De waarden van deze sensoren moesten vervolgens via een seriële connectie naar een webpagina gestuurd worden.
Daarnaast moest er ook een van deze waarden naar de HvA server gestuurd worden, om vervolgens op een map weergegeven te worden.
Al deze meetwaarden moesten live getoond worden op de website.
### Actie
Om te voldoen aan de criteria voor het project heb ik gebruik gemaakt van een luchtvochtigheidsensor gepaard met een temperatuursensor (DHT11)
en een lichtsensor (GL5528). Deze sensoren leverde adequate data voor het project. Daarnaast heb ik een simpele website gemaakt
waarbij de waarden van deze sensoren live in het midden van de website getoond werden.
### Resultaat
Het resultaat van het project was een werkend meetsysteem dat de waarden van de sensoren live weergaf op een website.
### Reflectie
In het eerste blok heb ik behoorlijk veel nieuwe gedragscriteria geleerd.
Ik heb geleerd om beter mijn werk bij te houden door het te actief te documenteren en het bij te houden met een version control system (VSC) zoals git.
Ik vond het aan het begin wel lastig om hieraan te voldoen, gezien ik hiervoor vrij weinig aan documentatie als git heb gedaan.
### Transfer
## Reflectie opdracht Blok 2 - TI Game Controller
## Reflectie opdracht Blok 3 - Optimalisatie Studieomgeving
Skills ontwikkelingsplan SMART
Professional Skills
Persoonlijk Leiderschap
Toekomstgericht organiseren
Doelgericht interacteren
Onderzoekend probleemoplossen
Essential Skills: Nederlands, Engels en Wiskunde

View File

@@ -0,0 +1,88 @@
# Expert review sprint 2
# Expert review sprint 2
### K1
Voor het maken van object georiënteerde software die samenwerkt met een database maak ik gebruik van Java, NodeJs, phpMyAdmin en MariaDB.
### Java
Java gebruiken wij als taal van de app. Deze taal zorgt ervoor dat onze app functioneert.
### Database
De database voor FitBot zal worden gebruikt als opslag van de oefeningen die wij willen gebruiken. Wij moeten deze nog verbinden met de app
#### Apache en phpMyAdmin
Om de database te managen gebruiken wij PHPmyadmin deze meot worden gedraaid op een webserver en voor de webserver hebben wij apache2 gebruikt
##### MariaDB
MariaDB dient als onze database om de oefeningen in op te slaan.
##### NodeJs
NodeJS is geinstaleerd op de Pi maar deze moeten wij nog verder instellen
Ik heb in java ook OOP gewerkt, niet in hele grote maten, omdat wij gaan voor een minimalistische app, maar ik heb de app ontworpen daar heb ik gebruik gemaakt van styles. Hier vindt u mijn documentatie over android styles. [Documentatie styles](docs\documentation\android\code_documentation\AndroidStyles.md)
Ik heb ook een class gemaakt om eenvoudig code te schrijven om via buttons te navigeren. Ik heb hier nog geen documentatie over geschreven, maar ik heb wel de code al af en functionerend. Hier vindt u de class [buttonClass](code\src\Fitbot\app\src\main\java\com\example\fitbot\util\ButtonNavigation.java)
```java
com.example.fitbot.util.ButtonNavigation.setupButtonNavigation(this, R.id.homeButton, MainActivity.class);
```
Dit hoe je de class implementeerd in de activities.
### K2
De wensen en Behoeftes van de gebruikers hebben wij nog niet kunnen meten. Ik ga wel binnenkort (28 mei) een wandeling maken met de gebruikers. Deze wandeling doe ik via buurtcampus oost. Om deze test zo goed mogelijk uitvoeren heb ik een test card gemaakt. Met deze testcard wil ik aan de gang gaan tijdens de wandeling
![TESTCARD](TESTCARD28.png)
Na het uitvoeren van de test ga ik de resultaten bespreken in een apart markdown folder. Na het bespreken van de resultaten ga ik een learningcard maken, zodat ik kan zien wat ik geleerd heb.
![empty learning card](Learningcardempty.png)
Daarnaast heb ik meerdere onderzoeken naar hoe je een app voor ouderen moet maken. Dit onderzoek kan je hier vinden [colorsforlayout](docs\documentation\brainstorm\colorsforlayout.md)
Ik zou ook nog graag onze app willen voorleggen aan ouderen om te kijken of onze app wel goed gebouwd is, dit komt als wij ons prototype afhebben dan kunnen we beginnen met testen en aan de hand van die feedback gaan wij extra user stories aanmaken.
### K3
De infrastructuur voor FitBot bestaat uit een database, een server en een app. De database wordt gebruikt om de oefeningen in op te slaan, de server wordt gebruikt om de app te verbinden met de database en de app wordt gebruikt om de oefeningen op te halen.
Voor de server gebruiken Wij Apache2.
Voor de database gebruiken wij MariaDB.
Voor management van de database gebruiken wij phpMyAdmin.
**Infrastructuur diagram**
```mermaid
graph TD
    subgraph Raspberry Pi
        A[MariaDB]
    end
    subgraph Pepper Bot
        C[Android Tablet]
   
    end
    subgraph WiFi Fit Board
     B[WiFi Fit Board]
    end
    B --> |Bluetooth| C
    C --> |Receive/Send Data| A
    A --> |Communicate Workouts| C
   
```
Om nog extra voor K3 te doen ga ik een onderzoek schrijven over de datatransfer protocollen en welke het beste werkt voor ons project. Dan aan de hand van dat onderzoek moeten wij een keuze gaan maken in welke protocollen we willen gebruiken.
### K4
Ik heb de verschillen tussen de NAO en pepper onderzocht, dit heb ik gedaan om te kijken welke het beste bij ons project past. Dit is belangrijk om te weten voor als we moeten switchen/het project opnieuw moeten doen.
[pepperNAOcompare](Docs\documentation\robots\Comparisons.md)
Daarnaast waren er wat mankementen met de Wiifit bord. ik wil graag onderzoeken hoe het fout kan gaan en wat de alternatieven zijn.
### K5
Voor K5 hebben wij motion trackers ontworpen die wij willen gebruiken voor onze oefeningen. Deze werken met een accelerometeren een gyro sensor. Deze gebruiken wij om te meten of een persoon de oefening goed. De gebruiker krijgt zijn bewegeingen live terug te zien in de app en zo kan je je eigen bewegingen zien en het vergelijken met het voorbeeld. Ook hebben wij een wii fit bord om te kijken of een persoon er op staat dit kan gebruikt worden voor oefeningen op 1 been bijvoorbeeld. Deze moeten wij nog verbinden met de app alleen hebben wij een probleem dat het wiifit bord niet wil werken als alternatief gaan wij aan de slag met een ESP en LDRs. Wij willen meten of iemand op een bord staat doormideel wan licht en wij willen die dat versturen met de Bluetooth van de EPS door daar een bleutooth server op te hosten die comminuceert met de app.

View File

@@ -67,25 +67,50 @@ https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8936033/
# inleiding
De vergrijzing van de samenleving zet druk op de ouderenzorg. Er is een tekort aan zorgverleners, terwijl de vraag naar zorg toeneemt. Robotica wordt gezien als een mogelijke oplossing om dit probleem optelossen. Robots kunnen taken overnemen van verpleegsters, zoals medicatie toedienen, lichaamsverzorging en gezelschap bieden. Maar de inzet van robots in de ouderenzorg roept ook ethische dilemma's op. Ik ga onderzoeken welke etische dillemas er kunnen ontstaan in de zorg. Om dit doel te bereiken, zullen we de volgende deelvragen beantwoorden:
De vergrijzing van de samenleving zet druk op de ouderenzorg. Er is een tekort aan zorgverleners, terwijl de vraag naar zorg toeneemt. Robotica wordt gezien als een mogelijke oplossing om dit probleem op te lossen. Robots kunnen taken overnemen van verpleegsters, zoals medicatie toedienen, lichaamsverzorging en gezelschap bieden. Maar de inzet van robots in de ouderenzorg roept ook ethische dilemma's op. In dit onderzoek wordt onderzocht welke ethische Dillema's er kunnen ontstaan in de zorg. Om dit doel te bereiken, zullen de volgende deelvragen beantwoord worden:
- Wat zijn de mogelijke effecten van het gebruik van robots op het emotionele en sociale welzijn van ouderen?
- Leidt robotisering in de ouderenzorg tot onpersoonlijke en mechanische zorg?
- Welke voordelen zijn er bij gebruik van robots in de ouderenzorg
- Welke risico's zijn er over de veiligheid en privacy voor ouderen bij het gebruik van robots in de zorg?
- Welke nadelen zijn er bij gebruik van robots in de ouderenzorg
Deze vragen behandelen allerei verschillende aspecten van robotica in de ouderzorg. na het beantwoorden van de deelvragen kunnen wij een concusie trekken en kijken naar welke dillemas er kunnen ontstaan.
Deze vragen behandelen verschillende aspecten van robotica in de ouderzorg. Na het beantwoorden van de deelvragen kunnen we een conclusie trekken en kijken naar welke dilemma's er kunnen ontstaan.
## Wat zijn de mogelijke effecten van het gebruik van robots op het emotionele en sociale welzijn van ouderen?
Het sociale welzijn van ouderen is een belangrijk onderwerp. Ouderen kunnen zich vaak enzaam of afgesloten voelen van de samenleving. Dit is een groot probleem binnen in de ouderzorg omdat je niet wilt dat ouderen zich nog eenzamer gaan voelen nadat zij worden verzorgd door een robot. Daarom wil ik weten wat de effecten zijn van het gebruik van robotica in de ouderzorg, Zodat ik daaruit kan bepalen wat voor een dillema het met zich mee zou brengen.
Het sociale welzijn van ouderen is een belangrijk onderwerp. Ouderen kunnen zich vaak eenzaam of afgesloten voelen van de samenleving. Dit is een groot probleem binnen in de ouderzorg omdat je niet wilt dat ouderen zich nog eenzamer gaan voelen nadat ze worden verzorgd door een robot. Daarom is het belangrijk om te weten wat de effecten zijn van het gebruik van robotica in de ouderzorg, zodat er daaruit kan bepaald worden wat voor dilemma's het met zich mee kan brengen.
Er zijn al veel onderzoeken geweest naar dit onderwerp. Onderzoek wijst uit dat robots zowel positieve als negatieve effecten kunnen hebben. Een postief effect ervan is dat ouderen zich minder eenzaam voelen. 17 onderzoeken met 4 verschillende type robots wijsen erop dat Uit de meeste onderzoeken bleek dat gezelschapsrobots een positieve invloed hadden op (socio)psychologische (bijv. humeur, eenzaamheid, sociale connecties en communicatie) en fysiologische (bijv. stressverlaging) variabelen. De methodologische kwaliteit van de studies was over het algemeen laag.[1] Dit laat zien dat het helpt om eenzaamheid bij ouderen tegentegaan. Ze kunnen ook worden gebruikt om ouderen te helpen in contact te blijven met vrienden en familie. Dit is handig iets omdat ouderen dan dichter bij hun familie zijn wat voor de meeste ouderen heel belangrijk is om eenzaamheid tegen te gaan. Bovendien kunnen robots worden gebruikt om ouderen te motiveren om actief en betrokken te blijven bij hun leven. Fitness is niet alleen iets om fit te blijven maar brengt ook socialen aspecten met zich mee. Ik ben nu persoonlijk bezig met een project waarmee wij ouderen willen stimuleren meer te bewegen zodat zij ook wat vaker naar buiten kunnen en potentieel ook samen workouts kunnen doen.
Er zijn al veel onderzoeken geweest naar dit onderwerp. Onderzoek wijst uit dat robots zowel positieve als negatieve effecten kunnen hebben. Een positief effect ervan is dat ouderen zich minder eenzaam voelen. 17 onderzoeken met 4 verschillende type robots wijzen erop dat uit de meeste onderzoeken bleek dat gezelschapsrobots een positieve invloed hadden op (socio)psychologische (bijv. humeur, eenzaamheid, sociale connecties en communicatie) en fysiologische (bijv. stressverlaging) variabelen. De methodologische kwaliteit van de studies was over het algemeen laag volgens [(Socially Assistive Robots in Elderly Care: A Systematic Review into Effects and Effectiveness, 2010)](https://www.sciencedirect.com/science/article/abs/pii/S1525861010003476). Dit laat zien dat het helpt om eenzaamheid bij ouderen tegen te gaan. Ze kunnen ook worden gebruikt om ouderen te helpen in contact te blijven met vrienden en familie. Dit is handig iets omdat ouderen dan dichter bij hun familie zijn, wat voor de meeste ouderen heel belangrijk is om eenzaamheid tegen te gaan. Bovendien kunnen robots worden gebruikt om ouderen te motiveren om actief en betrokken te blijven bij hun leven. Fitness is niet alleen iets om fit te blijven, maar brengt ook sociale aspecten met zich mee.
Over het algemeen zijn de mogelijke effecten van robots op het emotionele en sociale welzijn van ouderen complex. Er zijn zowel mogelijke Voordelen en nadelen, en de impact van robots zal waarschijnlijk van persoon tot persoon verschillen. Het is belangrijk om deze factoren zorgvuldig af te wegen bij het beslissen of robots wel of niet in de ouderzorg te implementeren.
Over het algemeen zijn de mogelijke effecten van robots op het emotionele en sociale welzijn van ouderen complex. Er zijn zowel mogelijke Voordelen als nadelen, en de impact van robots zal waarschijnlijk van persoon tot persoon verschillen. Het is belangrijk om deze factoren zorgvuldig af te wegen bij het beslissen of robots wel of niet in de ouderzorg te implementeren.
## Kan het gebruik van robots in de ouderenzorg leiden tot een gevoel van dehumanisering of verminderde menselijke interactie voor ouderen?
## Welke voordelen zijn er bij gebruik van robots in de ouderenzorg
Het gebruik van robots in de ouderenzorg kan meerdere voordelen met zich meebrengen. Robots kunnen in sommige aspecten beter zijn dan mensen. Het is belangrijk om er achter komen wat de voordelen zijn, zodat ik kan inzien wat de positieve kant is van het gebruik van robots. Daarnaast vallen er ook wat dilemma's af omdat als er voordelen zijn dat er niet vaak een dilemma aan hangt.
Robots kunnen taken overnemen van zorgverleners, zoals het toedienen van medicijnen, het verzorgen van patiënten en het verplaatsen van patiënten. Hierdoor kunnen zorgverleners zich meer focussen op complexere zorgtaken die robots niet kunnen overnemen en meer tijd doorbrengen met ouderen. Dit heeft een positief effect op het bestrijden van de eenzaamheid van ouderen. Uit onderzoek blijkt dat 70% van de zorgverleners in verpleeghuizen gelooft dat robots hen kunnen helpen om de kwaliteit van zorg te verbeteren. [(Impacts of robot implementation on care personnel and clients in elderly-care institutions, 2019)](https://www.sciencedirect.com/science/article/pii/S1386505619300498) Het gebruik van robots zorgt dus ervoor dat de simpelere taken die vaak moeten gebeuren dat die geautomatiseerd worden. Daarnaast kunnen robots ook de hele dag en nacht door zorg bieden indien nodig. Dit zorgt ervoor dat er minder personeel nodig is voor nachtdiensten in de zorg.
Dit is een groot voordeel van het gebruik van robots. De vermindering in de werkdruk in de zorg is fijn voor de hulpverleners en ook voor de ouderen. Als de zorgverleners meer tijd hebben voor de ouderen en de zwaardere taken kunnen de robots het lichte en simpele werk overnemen.
## Welke nadelen zijn er bij gebruik van robots in de ouderenzorg
Naast de voordelen zijn er ook nadelen bij het gebruik van robots in de ouderenzorg. Deze nadelen zijn essentieel om te onderzoeken, doordat er vaak dilemma's aan nadelen hangen. Robots kunnen meerdere nadelen met zich mee brengen. Deze nadelen kunnen in het ethische aspect vallen, maar ook daar buiten.
Een nadeel dat zou kunnen vormen heeft te maken met privacy. Ouderen kunnen te maken krijgen met geheugen verlies. Dit kan leiden tot momenten dat ze niet meer weten wat ze zeggen of waar ze toestemming op geven. Een robot kan niet altijd de situatie begrijpen als een persoon te maken heeft met geheugen verlies. Dit zou een probleem kunnen zijn volgens [((The ethical issues of social assistive robotics: A critical literature review, 2021)](https://www.sciencedirect.com/science/article/pii/S0160791X21002013#bib40:~:text=3.1.1.%20Well,requiring%20ethical%20ponderation). Daarnaast slaan de robots constant data op zoals wat de gebruiker doet, waar ze naar toe gaan en met wie ze omgaan. De robots kunnen met deze informatie een profiel gaan maken per persoon met de data die ze verzamelen. Deze vormen een privacy problemen doordat het persoonlijke informatie kan zijn. Deze persoonlijke profielen kunnen worden verkocht voor commerciële doel einde of worden gelekt waardoor de persoonlijke informatie publiekelijk kan zijn.
De nadelen van het gebruik van robots in de ouderenzorg is vooral gebonden aan privacy. Als de robots persoonlijke profielen kunnen aanmaken vormt dit een gevaar voor de privacy. Deze profielen kunnen voor meerdere doeleinde worden gebruikt die een gevaar kunnen vormen voor de ouderen.
# conclusie
In dit onderzoek hebben we het gehad over het sociale welzijn van de ouderen en de voor- en nadelen van robots in de ouderen zorg. Het is belangrijk dat we voorzichtig doen met het implementeren van robots in de ouderenzorg doordat de behoeftes per persoon kunnen verschillen. We moeten goed blijven onderzoeken wat de behoeftes zijn van de ouderen omdat het belangrijk is dat ze zich niet slecht gaan voelen. De voordelen van de robots zijn dat we de druk van de zorgverleners af kunnen halen. Doordat de robots de simpele taken van de zorgverleners kunnen over nemen kan er extra tijd vrij komen om met de ouderen persoonlijke tijd door te brengen. Er zijn ook nadelen van het gebruik van robots, deze hangen vooral aan de privacy. Doordat de robots een profiel van de ouderen kunnen maken en deze kan worden misbruikt voor commerciële doel einde.
Een dilemma die kan ontstaan gaat over Privacy en gegevens. Robots verzamelen constant data over ouderen en mensen met wie ze omgaan. Deze informatie kan gevoelig zijn over de gezondheid en het welzijn van die persoon. Ook zijn er dilemma's over de behoeftes van oudere. Is het wel ethisch verantwoordelijk om robots te gebruiken tegen de zin in van ouderen. Als de robots globaal worden ingezet kan het zo zijn dat niet iedereen er comfortabel mee is en dat men op zoek is naar menselijk contact. Voor verder onderzoek adviseer ik om te kijken naar hoe we gegevens kunnen beschermen en met welke gegevens ze comfortabel zijn te delen met de robot. Dit is essentieel om te weten om de privacy te beschermen van de ouderen. Doordat het een dilemma is moeten we kijken naar de oplossingen.
(Socially Assistive Robots in Elderly Care: A Systematic Review into Effects and Effectiveness https://www.sciencedirect.com/science/article/abs/pii/S1525861010003476)[1]
(Impacts of robot implementation on care personnel and clients in elderly-care institutions https://www.sciencedirect.com/science/article/pii/S1386505619300498)
(The ethical issues of social assistive robotics: A critical literature review https://www.sciencedirect.com/science/article/pii/S0160791X21002013)
https://www.sciencedirect.com/science/article/pii/S0160791X21002013#bib40:~:text=3.1.1.%20Well,requiring%20ethical%20ponderation

View File

@@ -0,0 +1,106 @@
# Inleiding
Hier zal ik mijn skills ontwikkelingsplan schrijven voor mijn persoonlijk leiderschap (G1). Dit plan bestaat uit een reflectie van de afgelopen blokken, mijn sterke en zwakke punten en mijn smart leerdoelen voor de komende blokken.
De vier professional skills:
- Toekomstgericht organiseren
- Onderzoekend probleemoplossen
- Persoonlijk leiderschap
- Doelgericht interacteren
# Reflectie
Hieronder vind je mijn reflectie over de afgelopen blokken. In deze reflectie beschrijf ik mijn obstakels en leerpunten. Na mijn reflectie schrijf ik mijn sterke en zwaktepunten op. Ook ga ik de professional skills gebruiken als lijn om mijn reflectie te schrijven.
## climate measuring box (blok 1)
In blok 1 heb ik me georiënteerd op de opleiding. Het was even wennen het verschil tussen deze opleiding en mijn middelbare school, maar ik wende vrij snel mede door mijn fijne klas. Ik heb goed mezelf leren kennen in de eerste weken, alleen kwam ik stroef op stap omdat ik geen codeer ervaring had gelukkig had ik mijn klasgenoten om mij heen die me konden helpen. Helaas kwam ik daardoor wel tekort in andere aspecten naast coderen. Mijn documentatie liep achter en ik werkte niet goed met scrum.
Door dat ik achterliep met documenteren was het moeilijk om mij progressie te volgen. Dit zorgde niet voor vertraging in mijn werk. Wat wel voor vertraging zorgde was mijn planning en scrum skills. Doordat ik geen planning maakte en niet altijd mijn issue bord bijwerkte was mijn werksnelheid niet optimaal en was ik niet helemaal tevreden met hoe ik mijn eindproduct er uitzag. Ik had wel al mijn issues afgekregen, dus het was wel een volledig product.
Mijn sterke en zwakke punten van blok 1 waren dan ook:
- Niet bang zijn om hulp te vragen
- Snel opstap komen in een nieuwe omgeving
- Snel ontwikkelen van skills die ik miste
Zwakke punten:
- Weinig gebruik van de scrum methode
- Het documenteren van mijn werk
- planning maken voor de sprint
In blok 1 heb ik enorm veel kunnen leren over de IT-wereld en heb ik snelle progressie gemaakt in het vakgebied. Ik ben enorm tevreden met mijn persoonlijke groei als persoon en student.
![Feedback blok 1](../Niels/assets/feedbackblok1.png)
## TI game controller (blok 2)
In blok 2 hadden we een nieuw project. Dit was ook het project dat ik met een klasgenoot aan het maken was. De overgang naar scrum en de noodzaak voor uitgebreide documentatie waren nieuw en waren mijn zwakke punten uit blok 1. Dit was een lastig blok door deze punten. Gelukkig kon ik snel aan de bel trekken en was mijn teamgenoot hier van op de hoogte. Dankzij mijn sterke communicatieve vaardigheden die ik tijdens mijn middelbareschooltijd had ontwikkeld. Konden we snel naar elkaar toestappen met problemen en een oplossing zoeken. Dankzij dit hebben we geen conflicten gehad in onze samenwerking. Toen we verder in het blok gingen kwamen mijn scrum skills en documentatie tevoorschijn. Ik werkte bijna dagelijks het scrumbord bij en ik documenteerde mijn werk.
Helaas was er een nieuwe zwakte ontdekt bij mij. Mijn commit gedrag was niet goed. Ik maakte hele grote commits wat ervoor zorgde dat het heel onduidelijk werd. Dit zorgde er ook voor dat ik slechte commit messages schreef. Dit maakte het onduidelijk waar ik aan gewerkt had en ik moest dus elke keer gaan uitleggen wat ik gedaan had. Mijn teamgenoot had hier geen probleem mee, maar ik wist dat als ik in een grotere groep ging werken dat ik niet elke keer alles kon gaan uitleggen dus moest ik dit gaan veranderen.
Mijn sterke en zwakke punten van blok 2 waren dan ook:
Sterke punten:
- Goede communicatie
- Oplossingsgericht
- Snel aan de bel trekken als er iets mis kan gaan
Zwakke punten:
- Gebruik maken van UML
- Commit gedrag
In blok 2 heb ik veel kunnen leren over het samenwerken in een team, scrum werken en documenteren. Ik ben enorm tevreden over dat ik mijn zwakte punten van blok 1 heb kunnen verbeteren in blok 2 en ik was zeker tevreden over de samenwerking met mijn teamgenoot.
![Feedback blok 2](../Niels/assets/feedbackblok2.png)
## Verbetering leer omgeving (blok 3)
In blok moesten we in een team van 4 werken. Deze moesten we zelf samenstellen, alleen hingen er eisen aan dat er mensen van je nieuwe klas bij moesten zitten. Ik vond dit jammer omdat ik graag met de mensen die ook goed kende en waarmee ik hetzelfde niveau deelde. Door die eisen werd bijna ons team uit elkaar gehaald, maar was er uiteindelijk besloten dat we toch verder mochten gaan, omdat het anders niet aan de andere eisen voldeed. Dit was voor mij enorm fijn omdat ik beter leer in een team waarmee ik dezelfde problemen deel. We hadden een team van 4 dit was wel een stuk fijner dan 2 omdat je dan met een groep dingen kan bepalen. Wij hadden in het begin problemen met een goed idee te verzinnen voor het blok. Dit kwam voor mij door een tekort aan creativiteit bij mij en het inbeelden van tekorten op de school omdat ik er nog niet zo vaak en lang ben. Maar wij hebben ons hierdoorheen gewerkt en wij konden aan de slag.
Tijdens blok 3 kwam ik er achter dat ik vrij ontevreden was met de huidige staat van de opleiding. Hierdoor wist ik niet zeker of ik wel verder wou gaan met de opleiding. Dit zorgde voor een tekort aan motivatie bij mij voor een tijd. Ik ging ook meer kijken naar andere studies wat zorgde voor minder tijd voor mijn project. In sprint 3 had ik besloten om in ieder geval mijn propedeuse te halen. Ik ben aan de ene kant blij dat ik in de situatie kwam zodat goed kon nadenken over wat ik wil gaan doen in de toekomst, maar helaas zorgt dit voor hindernis in het werk.
Mijn sterke en zwakke punten van blok 3 waren dan ook:
Sterke punten:
- Sterke communicatie
- Doorzettingsvermogen
- Goed te werk in een fijne omgeving
Zwakke punten:
- Motivatie
- Creativiteit
- Kennis over Back-end
In blok 3 heb ik veel kunnen leren over mijzelf, ik kwam te leren over mijn tekorten aan kennis binnen IT en mijn toekomst. Ik heb een lang gesprek gehouden met een studiebegeleider en ik heb gekeerd dat ik dit zeker vaker moet gaan doen om te kijken wat ik wil en wat de alternatieven zijn.
!![Feedback blok 3](../Niels/assets/feedbackblok3.png)
# Sterke en zwakke punten (Profesional skills)
# Smart leerdoelen
**Situatie**
**Taak/Opgave**
**Aanpak en activiteiten**
**Resultaat**
**Reflectie**
**Transfer**
# Conclusie
# Profesional skills
https://www.hva.nl/binaries/content/assets/serviceplein-a-z/media-creatie-en-informatie/hbo-ict/competenties/professional-skills-hbo-ict-2023-2024.pdf
De vier profesional skills:
- Toekomstgericht organiseren
- Onderzoekend probleemoplossen
- Persoonlijk leiderschap
- Doelgericht interacteren

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -10,31 +10,31 @@ Deelvraag: Welke ethische vragen komen naar boven bij het vervangen van menselij
## Inleiding
Dit literatuur onderzoek gaat over de opkomst van robots in de ouderenzorg en de invloed die dit heeft op de ouderen die er mee te maken krijgen. De vraag naar ouderenzorg word veel groter, waardoor de vraag naar personeel ook stijgt. Daarnaast is er ook nog sprake van vergrijzing waardoor de vraag nog meer toeneemd. Omdat er niet genoeg personeel is om de grote vraag te vervullen worden er robots ingezet om de taken van het personeel over te nemen. Wat voor effect heeft deze verandering op de ouderen en is het wel verantwoord om robots in te zetten in de ouderenzorg?
Dit literatuur onderzoek gaat over de opkomst van robots in de ouderenzorg en de invloed die dit heeft op de ouderen die er mee te maken krijgen. De vraag naar ouderenzorg word veel groter, waardoor de vraag naar personeel ook stijgt. Daarnaast is er ook nog sprake van vergrijzing waardoor de vraag nog meer toeneemt. Omdat er niet genoeg personeel is om de grote vraag te vervullen worden er robots ingezet om de taken van het personeel over te nemen. Wat voor effect heeft deze verandering op de ouderen en is het wel verantwoord om robots in te zetten in de ouderenzorg?
## Taken van robots in de ouderenzorg
Robots kunnen ouderen helpen bij hun dagelijkse activiteiten. Blijkt uit het literatuuroverzicht van [(Pouyan Asgharian)](https://www.mdpi.com/2218-6581/11/6/127). Volgens de schrijvers kunnen deze robots herinneringen, huishoudelijke taken, veiligheid en gezondheidsmonitoring ondersteunen. "mobile social robots could assist older adults throughout their daily activities such as reminding, household tasks, safety, or health monitoring", zegt [(Pouyan Asgharian)](https://www.mdpi.com/2218-6581/11/6/127). Dit laat zien dat robots best veel last kunnen overnemen van het zorgpersoneel.
Robots kunnen ouderen helpen bij hun dagelijkse activiteiten. Blijkt uit het literatuuroverzicht van [(Asgharian et al. (2022)
)](https://www.mdpi.com/2218-6581/11/6/127). Volgens de schrijvers kunnen deze robots herinneringen, huishoudelijke taken, veiligheid en gezondheidsmonitoring ondersteunen. Volgens [(Asgharian et al. (2022)
)](https://www.mdpi.com/2218-6581/11/6/127) Kunnen mobiele robots ouderen mensen assisteren met taken zoals herinneringen of huishoudelijke taken. Dit laat zien dat robots best veel last kunnen overnemen van het zorgpersoneel.
Aan de andere kant, zoals beschreven in het artikel van [(Frontiers in Robotics and AI, 2021)](https://www.frontiersin.org/articles/10.3389/frobt.2021.605715/full), is de natuurlijke interactie tussen mens en robot complex. Robots moeten niet alleen in staat zijn om de intenties, gevoelens en persoonlijkheden van gebruikers te begrijpen, maar ze moeten ook in staat zijn om op een natuurlijke en medelevende manier te reageren. Dit vereist cognitieve en sociaal-emotionele vaardigheden, evenals geavanceerde redeneer-, perceptie- en leermodules voor robots. Zo zeggen de auteurs dat "In summary, to achieve natural human-robot interaction during cognitive training requires not only multimodal sensing technology and artificial intelligence (e.g., deep learning) but also the development of related fields" [(Frontiers in Robotics and AI, 2021)](https://www.frontiersin.org/articles/10.3389/frobt.2021.605715/full).
Aan de andere kant, zoals beschreven in het artikel van [(Frontiers in Robotics and AI, 2021)](https://www.frontiersin.org/articles/10.3389/frobt.2021.605715/full), is de natuurlijke interactie tussen mens en robot complex. Robots moeten niet alleen in staat zijn om de intenties, gevoelens en persoonlijkheden van gebruikers te begrijpen, maar ze moeten ook in staat zijn om op een natuurlijke en medelevende manier te reageren. Dit vereist cognitieve en sociaal-emotionele vaardigheden, evenals geavanceerde redeneer-, perceptie- en leermodules voor robots. Zo zeggen de auteurs dat [(Frontiers in Robotics and AI, 2021)](https://www.frontiersin.org/articles/10.3389/frobt.2021.605715/full) interactie trainen voor de robot enorm lastig is en dat er nog veel onderzoek nodig is om dit te verbeteren.
## Ervaring van ouderen met robots
Bij de introductie van robots in de ouderenzorg zijn de ervaringen van de ouderen verdeeld. Er zijn veel positieve en negatieve ervaringen met robots in de ouderenzorg volgens [(Helinä Melkas, 2016)](https://roseproject.aalto.fi/images/publications/ICServe_Melkas.pdf). De positieve ervaringen zijn bijvoorbeeld dat er iemand even voor hun was en dat de robot niet boos of geïrriteerd raakt om iets vaker te herhalen. Ouderen ervaren ook negatieven ervaringen met robots. Zoals dat ze de robots verwarrend vinden ook vinden sommigen ouderen dat ze het menselijk contact missen. [(Helinä Melkas, 2016)](https://roseproject.aalto.fi/images/publications/ICServe_Melkas.pdf).
## Welke ethische vragen komen er naar boven?
Het gebruik van robots wekt meerdere ethische vragen op, zoals wat voor impact dit heeft op de zorg en wat voor sociale impact heeft dit op ouderen. Ook speelt privacy een grote rol. Volgens [(Poulsen et al. 2018)](https://researchoutput.csu.edu.au/ws/portalfiles/portal/35459797/28761055_Conference_paper.pdf) Is een goed maatregel beperken wat de robot kan doen, zodat er minder ethische vraagstukken naar voren komen en dus ook privacy beter beschermt kan worden. Ook word er in het artikel gezegd dat er met de ouderen overlegd moet worden wat ze van de robot verwachten en wat ze wel en niet willen van de robot. Het is belangrijk om de ouderen te betrekken bij de beslissingen die gemaakt worden.
## Conclusie
## ongebruikte bronnen
* https://digitcult.lim.di.unimi.it/index.php/dc/article/view/54
* https://www.mdpi.com/2076-3417/11/16/7248
* https://www.sciencedirect.com/science/article/pii/S1386505619300498
* https://www.mdpi.com/2075-1702/10/8/622
* https://link.springer.com/article/10.1007/s12652-020-02871-6
* https://www.researchgate.net/profile/Catharina-Wasic-2/publication/345981733_Towards_an_All-Day_Assignment_of_a_Mobile_Service_Robot_for_Elderly_Care_Homes/links/5fb7a5ff92851c933f431a40/Towards-an-All-Day-Assignment-of-a-Mobile-Service-Robot-for-Elderly-Care-Homes.pdf
* https://www.mdpi.com/2218-6581/11/6/127
* https://www.frontiersin.org/articles/10.3389/frobt.2021.605715/full
Er zijn dus gemengde redenen om robots in te zetten in de ouderenzorg. Het is belangrijk om te kijken naar de ervaringen van de ouderen en of het wel verantwoord is om robots in te zetten in de ouderenzorg. Uiteindelijk moet er gekeken worden of de ouderen een robot willen en wat de wensen er van zijn.
## bronnen
* https://www.frontiersin.org/articles/10.3389/frobt.2021.605715/full
* https://www.mdpi.com/2218-6581/11/6/127
* https://roseproject.aalto.fi/images/publications/ICServe_Melkas.pdf
* https://researchoutput.csu.edu.au/ws/portalfiles/portal/35459797/28761055_Conference_paper.pdf

View File

@@ -0,0 +1,11 @@
# Reflectie 3 blokken
## Blok 1
In blok 1 heb ik de professionele skills Persoonlijk leiderschap en Toekomstgericht organiseren. Ik had veel moeite met documenteren en het scrumboard te gebruiken, omdat ik er nog geen ervaring mee had. Ik had op dat moment al het hele project in blokjes opgedeeld voor mezelf en keer daarna nooit meer naar het scrumboard. Door die manier van werken deed ik ook 5 dingen tegelijk waardoor ik af en toe het overzicht kwijtraakte . Ik had als doel opgesteld om in de volgende blokken meer het scrumboard te gaan gebruiken. Mijn aanpak was proberen zelf wat user storys te maken, zodat ik ook wat meer betrokken was bij het scrumboard. Uiteindelijk heb ik daardoor wel wat meer gebruik gemaakt van het scrumboard, maar ik ging nog wel veel mijn eigen weg. Ik was niet helemaal tevreden met het resultaat, maar de aanpak werkte wel. Wat ik heb geleerd is als ik veel gebruik van iets wil maken moet ik er zelf ook bij betrokken zijn. Volgende keren zorg ik er voor dat ik betrokken ben bij het scrum board wat nu ook moet, waardoor ik meer het scrumboard gebruik.
## Blok 2
In blok 2 gingen we voor het eerst samenwerken in een duo, waarbij we ook deels onze eigen user storys moesten maken, dat heeft me ook geholpen om door het hele blok heen het scrumboard meer te gebruiken. Communicatie ging over het algemeen in dat blok redelijk goed. Als we vragen aan elkaar hadden werden die gewoon gesteld en als een van ons vastliep hielpen we elkaar. In sprint 2 werden classes aan ons geïntroduceerd waarbij ik best wat moeite had om dat te begrijpen. Dus ik had maar 1 class gemaakt en verder alles in functies gestopt. Pas eind sprint 2 probeerde ik de feedback te verwerken om alles in classes te stoppen, maar omdat je code uiteindelijk zo complex is. Is het bijna onmogelijk om het in classes te stoppen. Waarbij het resultaat was een heel lastig leesbaar programma. Ik was niet tevreden of over het resultaat aan het einde van het blok. Mijn aanpak was bij het volgende blok. Meteen alles in classes maken. Wat uiteindelijk wel goed heeft gewerkt. Ben daardoor ook achter gekomen hoe handig classes zijn en dat ze enorm veel overzicht geven van wat je aan het maken bent.
## Blok 3
In blok 3 stond doelgericht interacteren en persoonlijke leiderschap centraal. Het groepje in blok 3 was te gezellig waardoor we vaak meer zaten te lollen dan we aan het werk waren. Ik had mezelf de taak gegeven om proberen om meer gefocust te werken zonder dat ik afgeleid raakte door mijn groepje. Mijn aanpak was door mezelf af te schermen met een koptelefoon of eventjes ergens anders te gaan zitten, wat ook goed hielp was even een rondje lopen. Op die manier kon ik de laatste sprint heel efficiënt werken en in blok 4 merk ik ook dat die techniek enorm erg helpt met meer gefocust en productief blijven op een dag. Dit resultaat was eigenlijk een beetje laat het liefst deed ik dit al eind sprint 1, zodat ik heel het blok beter kon doorwerken.

View File

@@ -2,22 +2,33 @@
## Inhoudsopgave
- [Inleiding](#inleiding)
- [Reflectie](#reflectie)
* [Blok 1](#blok-1)
* [Blok 2](#blok-2)
* [Blok 3](#blok-3)
- [Conclusie](#conclusie)
* [Inleiding](#inleiding)
* [Reflectie](#reflectie)
+ [Blok 1](#blok-1)
+ [Blok 2](#blok-2)
+ [Blok 3](#blok-3)
* [Conclusie](#conclusie)
## Inleiding
In dit document zal ik een skill ontwikkelplan schrijven voor mijn persoonlijk leiderschap. Dit plan zal bestaan uit een reflectie van de afgelopen blokken, mijn sterke en zwakke punten en mijn smart leerdoelen voor de komende blokken.
De vier professional skills:
* Toekomstgericht organiseren
* Onderzoekend probleemoplossen
* Persoonlijk leiderschap
* Doelgericht interacteren
## Reflectie
In het volgende stuk zal ik reflecteren op de afgelopen blokken. Hierbij kijk ik naar de feedback die ik heb gekregen, waar ik op dat moment stond en wat ik heb geleerd. Bij het reflecteren zal ik de vier professional skills gebruiken als leidraad.
### Blok 1
In het eerste blok heb ik op veel verschillende vlakken geleerd wat mijn sterke en zwakke punten zijn. Groot en deels van de eerste periode in blok 1 heb ik gespendeerd aan mezelf leren kennen binnen de opleiding. Het werken binnen een nieuwe omgeving en met nieuwe mensen was voor mij goed te doen. Ik heb de leeromgeving snel leren kennen en heb geen moeite gehad met het communiceren met mijn medestudenten en docenten.
In het eerste blok heb ik op veel verschillende vlakken geleerd wat mijn sterke en zwakke punten zijn. Groot en deels van de eerste periode in blok 1 heb ik gespendeerd aan mezelf leren kennen binnen de opleiding. Het werken binnen een nieuwe omgeving en met nieuwe mensen was voor mij goed te doen. Ik heb de leeromgeving snel leren kennen en heb geen moeite gehad met het communiceren met mijn medestudenten en docenten. Enekele problemen die ik tijdens dit blok tegen kwam heb ik snel kunnen oplossen door vragen te stellen aan de docenten.
Door dagelijks mijn bezigheden te documenteren heb ik een goed overzicht kunnen houden van mijn werkzaamheden dit heeft mij geholpen om snel te kunnen schakelen tussen verschillende taken. Aan het begin van de sprints plannde ik mijn werkzaamheden in en zorgde ik ervoor dat ik mijn werkzaamheden op tijd af had. Ik heb in blok 1 veel tijd gestoken in het voorbereiden en het documenteren van mijn werk. Dit heeft mij geholpen om het beste uit mezelf te halen.
Als ik een aantal sterke en zwakke punten moet noemen van blok 1 dan zijn dat:
@@ -25,9 +36,9 @@ Sterke punten:
- Goed kunnen communiceren
- Snel kunnen schakelen tussen verschillende taken
- Snelle ontwikkeling in nieuwe omgevingen
- Documenteren van het werk
- Voorbereiden van presentaties
- Het beste uit mezelf halen
- Voorbereiden en documenteren van werkzaamheden
- Goed kunnen plannen
- Het meeste uit mezelf halen
Zwakke punten:
- Meer gebruik maken van coding conventions
@@ -35,28 +46,87 @@ Zwakke punten:
Ik heb in blok 1 enorm veel kunnen leren en heb echt het meeste uit mezelf kunnen halen. Ik ben erg tevreden met de resultaten die ik heb behaald en ben blij met de manier waarop ik mezelf heb kunnen ontwikkelen.
![Beoordeling Blok 1](../assets/beoordelingBlok1.png)
### Blok 2
Niet alles op mij nemen en meer vertrouwen hebben in anderen
In blok 2 heb ik voor het eerst moeten samenwerken met een teamgenoot. Aan het begin heb ik veel moeite gehad met het toe vertrouwen van werk aan mijn teamgenoot. Ik heb hier veel van kunnen leren en gerealiseerd dat ik te perfectionistisch aan het werk was. Ik heb in blok 2 veel tijd gestoken in het leren vertrouwen van mijn teamgenoot en het loslaten van de controle. Dit heeft mij geholpen om beter te kunnen samenwerken en om meer te kunnen focussen op mijn eigen werkzaamheden. Een voordeel van deze perfectionistische houding was dat ik de werkzaamheden van het project goed kon overzien en kon bijsturen waar nodig. Door dagelijks eerder aanwezig te zijn heb ik met mijn teamgenoot de tijd kunnen nemen om de werkzaamheden te bespreken en te plannen.
De eerste 2 weken (sprint 1) van blok 2 hebben ik en mijn teamgenoot aan een game gewerkt voor ons project. We hebben uiteindelijk besloten om deze game niet voor te zetten en zijn overgestapt naar een nieuwe game. We hebben allebei de realisatie gehad dat de gekozen game te hoog gegrepen was en dat we beter een andere game konden kiezen. Dit was een goede keuze en heeft ons geholpen om de rest van het project goed te kunnen afronden.
Als ik een aantal sterke en zwakke punten moet noemen van blok 2 dan zijn dat:
Sterke punten:
- Goed kunnen communiceren
- Snel kunnen schakelen tussen verschillende taken
- Snelle ontwikkeling in nieuwe omgevingen
- Inzicht om problemen te voorkomen
Zwakke punten:
- Gebruik maken van UML
- Te perfectionistisch aan het werk
Ik heb in blok 2 veel kunnen leren over het samenwerken met een teamgenoot en het loslaten van de controle. In het begin was dit erg lastig maar naarmate de weken vorderde heb ik hier veel van kunnen leren. De behaalde resultaten in blok 2 zijn goed en ik ben tevreden dat ik controle heb kunnen loslaten en heb kunnen samenwerken met mijn teamgenoot.
![Beoordeling Blok 2](../assets/beoordelingBlok2.png)
### Blok 3
eerder aan de bel trekken wanneer het team niet goed functioneert
Blok 3 is voor mij het blok geweest met de meeste leer punten. Het blok is begonnen met het leren van je nieuwe klas, er is door de opleiding een keuze gemaakt op klassen te vormen met leerlingen van de zelfde richting. Dit hield in dat ik in een nieuwe klas terecht kwam met nieuwe mensen. Dit was voor mij een grote verandering omdat ik gewend was geraakt aan mijn oude klas. Ik hierdoor ook kunnen ontdekken dat ik moeite heb met grote veranderingen. Het onbekende en niet wetende is voor mij een grote uitdaging.
## Sterke en zwakke punten (Profesional skills)
In blok 3 zijn we gaan werken in teams van 4, aan het begin was ik hier erg enthousiast over omdat je met een groter team een beter product neer zou kunnen zetten. Dit bleek in de praktijk toch lastiger dan gedacht. De teams van blok 3 moest je zelf maken en binnen het team moesten leerlingen van de verschillende klassen zitten. Helaas zat niet iedereen binnen het team op het zelfde niveau. Ik heb in de eerste sprint de rol van scrum master op mij genomen. Hierdoor heb ik het project kunnen uitplannen en heb ik een werk structuur voor het team opgezet.
## Smart leerdoelen
Naarmate het project zich vorderede werdt duidelijk dat het niveau verschil een probleem begon te worden. Halverwege sprint 2 heb ik met een docent gesproken over de problemen binnen het team. Hier uit kwam voort dat een spoed overleg met het team nodig was. Een week later vond dit overleg plaats. Hier uit bleek dat door het niveau verschil maakte dat sommige teamleden niet mee konden komen. Deze leerlingen gingen met hun problemen niet naar de docenten maar vroegen dit aan de andere teamleden. Dit heeft er voor gezorgd dat de andere teamleden niet aan hun eigen werkzaamheden toe kwamen. De uitkomst van dit overleg was de teamleden die niet mee konden komen met hun problemen naar docenten zouden gaan. Als binnen 1 week geen verbetering zou zijn dan zou het team uit elkaar worden gehaald. Na dit overleg is de samenwerking verbeterd maar het niveau verschil bleef een probleem. Dit heeft er voor gezorgd dat het project niet op het gewenste niveau is afgerond.
## Conclusie
Als ik een aantal sterke en zwakke punten moet noemen van blok 3 dan zijn dat:
Sterke punten:
- Leiderschap nemen
- Doorzettingsvermogen
- Doelgericht werken
Zwakke punten:
- Moeite met grote veranderingen
- Moeite met onbekende situaties
- Te laat aan de bel trekken bij problemen
In blok 3 heb ik veel kunnen leren over het samenwerken in een team waar niveau verschil is. Ik heb geleerd dat ik eerder deze problemen moet aangeven bij de docenten en niet moet wachten tot het te laat is. Ik heb in blok 3 veel tijd gestoken in het leren van het leiden van een team en het nemen van leiderschap.
![Beoordeling Blok 3](../assets/beoordelingBlok3.png)
## Profesional skills
https://www.hva.nl/binaries/content/assets/serviceplein-a-z/media-creatie-en-informatie/hbo-ict/competenties/professional-skills-hbo-ict-2023-2024.pdf
De vier profecional skills:
De vier professional skills:
- Toekomstgericht organiseren
- Onderzoekend probleemoplossen
- Persoonlijk leiderschap
- Doelgericht interacteren
* Toekomstgericht organiseren
* Onderzoekend probleemoplossen
* Persoonlijk leiderschap
* Doelgericht interacteren
STARTT
situatie
taak
actie
resultaat
tijd
toekomst
### Toekomstgericht organiseren
### Onderzoekend probleemoplossen
### Persoonlijk leiderschap
### Doelgericht interacteren
## Smart leerdoelen
## Conclusie

Some files were not shown because too many files have changed in this diff Show More