Compare commits

...

367 Commits

Author SHA1 Message Date
Pascal Serrarens
55347a4f25 Fix include 2024-12-28 15:36:25 +01:00
Pascal Serrarens
f63d5501e1 Merge commit 'b9937a72e3c983ee8124db8996ac659bc9e017de' into Experimental 2024-12-28 15:31:13 +01:00
Pascal Serrarens
0292dbef75 Moved to ControlCore subtree 2024-12-28 11:15:43 +01:00
Pascal Serrarens
07f78105aa Add 'ControlCore/' from commit '0a57e6d99abadc3257c6b1fdf5880b993e0d0fcb'
git-subtree-dir: ControlCore
git-subtree-mainline: 2b5f5a58ac608aca3aad452a87f6cb27f428cbde
git-subtree-split: 0a57e6d99abadc3257c6b1fdf5880b993e0d0fcb
2024-12-28 11:01:12 +01:00
Pascal Serrarens
2b5f5a58ac subtree migration step 1 2024-12-28 11:00:57 +01:00
Pascal Serrarens
788765dc97 Cleanup 2024-12-19 09:14:11 +01:00
Pascal Serrarens
b027460c63 Fixed negative angular velocity 2024-12-18 16:59:30 +01:00
Pascal Serrarens
701316d687 Thing -> ControlCore 2024-12-18 16:53:54 +01:00
Pascal Serrarens
9fb690a71b Support Destroy and UpdateAll 2024-12-17 12:09:30 +01:00
Pascal Serrarens
b97769624f Removed missin g include 2024-12-16 12:43:40 +01:00
Pascal Serrarens
5ebc449a79 Fixed undefined INFINITY in test 2024-12-16 12:43:09 +01:00
Pascal Serrarens
bb03e7d128 Fixed tests, removed most float16 overhead 2024-12-16 12:36:36 +01:00
Pascal Serrarens
2d8ea455e6 Send custom msg with control core 2024-12-16 11:42:19 +01:00
Pascal Serrarens
fec44b0397 Moved setname to corething 2024-12-16 09:13:59 +01:00
Pascal Serrarens
df8e065003 Use thingId from ControlCore 2024-12-16 09:11:06 +01:00
Pascal Serrarens
b2f1a74133 Moved fields from thing to corething 2024-12-16 08:28:19 +01:00
Pascal Serrarens
12fd89f3fb Migrated to ControlCore 2024-12-15 13:16:27 +01:00
Pascal Serrarens
0a155874e4 Updated linaar algebra 2024-12-14 12:40:39 +01:00
Pascal Serrarens
0cf4413814 Improved rounding of spherical positions 2024-12-14 12:39:01 +01:00
Pascal Serrarens
7bcd80087a Extended use of CoreThing 2024-12-14 10:45:43 +01:00
Pascal Serrarens
66c4b4ca7a Moved files to ControlCore Subtree 2024-12-13 17:10:05 +01:00
Pascal Serrarens
e09a609430 Moved ControlCore 2024-12-13 17:06:05 +01:00
Pascal Serrarens
55b63f7c3e Steps towards using ContolCore 2024-12-13 16:58:03 +01:00
Pascal Serrarens
7e5876e2f8 Extended the ControlCore 2024-12-11 18:01:06 +01:00
Pascal Serrarens
14e3499742 Added initial ControlCore code 2024-12-10 16:56:32 +01:00
Pascal Serrarens
f05ab5c742 ControlCore compatibility 2024-12-10 13:03:09 +01:00
Pascal Serrarens
181deae258 Add Messages to the Makelists 2024-12-02 09:25:28 +01:00
Pascal Serrarens
5c5d8b3189 Disabled perception update pose 2024-12-02 09:17:00 +01:00
Pascal Serrarens
3132912afc Separated out low-level messaging 2024-12-02 09:16:46 +01:00
Pascal Serrarens
fb5314019c Improved interestingThings 2024-11-29 17:44:59 +01:00
Pascal Serrarens
40c1e1d50c Fix unit tests 2024-11-29 15:09:47 +01:00
Pascal Serrarens
6356769aa9 Improved connecting 2024-11-29 15:06:08 +01:00
Pascal Serrarens
5ee5debf35 Add directional sensor 2024-11-29 12:56:59 +01:00
Pascal Serrarens
0a4c90225b Removed arduino include 2024-11-29 09:48:56 +01:00
Pascal Serrarens
ba009f79f7 Support simulated sensing 2024-11-27 13:40:58 +01:00
Pascal Serrarens
4ebe38eb39 FindChild by name 2024-11-15 17:06:13 +01:00
Pascal Serrarens
f1a6ea29c4 Further test fixes 2024-11-15 15:15:29 +01:00
Pascal Serrarens
c4d0ef95cf Fix test 2024-11-15 15:09:13 +01:00
Pascal Serrarens
4b21057fdd Model loading 2024-11-15 14:52:08 +01:00
Pascal Serrarens
51e605ca6d Thing Name support 2024-11-14 11:29:08 +01:00
Pascal Serrarens
610121f944 Velocity refactoring 2024-11-07 13:59:24 +01:00
Pascal Serrarens
3726070f02 Model scale support 2024-11-05 14:55:04 +01:00
Pascal Serrarens
3bc1866d34 Fixed unit test 2024-10-24 11:37:23 +02:00
Pascal Serrarens
db644af1ca Replace roboid worldpos/orient with worldOriginPos/orient 2024-10-24 11:33:33 +02:00
Pascal Serrarens
9b6bce5155 Release thing method added 2024-10-22 11:25:38 +02:00
Pascal Serrarens
f77b00f639 InterestingThings are now Things 2024-10-22 11:25:18 +02:00
Pascal Serrarens
0e2f628e3e Improve use of position/orientation 2024-10-21 17:54:27 +02:00
Pascal Serrarens
6e996c64eb Thing improvement 2024-10-21 12:52:25 +02:00
Pascal Serrarens
25bc715e13 Update LinearAlgebra 2024-09-27 15:48:47 +02:00
Pascal Serrarens
8443530819 Replace AngleAxis with Spherical 2024-09-27 09:46:20 +02:00
Pascal Serrarens
8d5707ce57 Minor improvements 2024-09-26 12:09:56 +02:00
Pascal Serrarens
827504fbd0 Make velocities visible 2024-09-25 11:49:16 +02:00
Pascal Serrarens
1079a725d9 Fix unit tests 2024-09-25 11:39:39 +02:00
Pascal Serrarens
b662348236 Improve servo angle limits 2024-09-25 11:28:31 +02:00
Pascal Serrarens
9a5fcf5798 Fix include error 2024-09-24 12:30:02 +02:00
Pascal Serrarens
dc9d1cd80f Updated spherical direction and unit tests 2024-09-24 12:26:03 +02:00
Pascal Serrarens
84654af2c3 Fix incompatibilities 2024-09-24 11:33:07 +02:00
Pascal Serrarens
60516dec0d Improve broadcast support 2024-09-23 10:05:02 +02:00
Pascal Serrarens
9de2fa6492 Minor improvements 2024-09-20 15:14:47 +02:00
Pascal Serrarens
7d4c26d10b Fix unit tests 2024-09-20 14:40:13 +02:00
Pascal Serrarens
d2c0ab5f9c Fix LinearAlgebra 2024-09-20 14:10:14 +02:00
Pascal Serrarens
58046f96ab Move to Spherical/SwingTwist 2024-09-20 12:30:21 +02:00
Pascal Serrarens
5b4dfbb0ae Improved angular support 2024-09-16 15:21:47 +02:00
Pascal Serrarens
89099a2dbb Merge branch 'main' of http://gitlab.passervr.com/passer/cpp/roboidcontrol 2024-09-16 14:24:38 +02:00
Pascal Serrarens
c1c1d74814 Improve sensor publication 2024-09-14 12:38:24 +02:00
Pascal Serrarens
5c5bf39bd3 Made limited target angle public (tmp for testing..) 2024-09-12 15:31:01 +02:00
Pascal Serrarens
51ef92d308 Update linear algebra 2024-09-09 16:02:38 +02:00
Pascal Serrarens
290ef4bb03 Enable sendpose 2024-09-09 15:14:27 +02:00
Pascal Serrarens
d486cd7b4f Roboid name support 2024-09-08 11:38:58 +02:00
Pascal Serrarens
1f85c6cc4b Added temperature type 2024-09-07 17:43:07 +02:00
Pascal Serrarens
2d83c0296b Add broadcast state (for temperature sensor) 2024-09-07 17:21:34 +02:00
Pascal Serrarens
2134d64c80 Added broadcast state 2024-09-07 15:50:01 +02:00
Pascal Serrarens
10c6ab3794 Updated linear algebra 2024-09-06 15:35:54 +02:00
Pascal Serrarens
871a01f4d4 Removed blocking condition 2024-09-02 15:50:03 +02:00
Pascal Serrarens
0779554313 Added actual angle 2024-08-30 16:28:15 +02:00
Pascal Serrarens
25cb1e1822 Send only when connected 2024-08-30 12:01:38 +02:00
Pascal Serrarens
b2adaac890 Merged changes 2024-08-29 13:53:09 +02:00
Pascal Serrarens
86a795dd81 Fix unit test 2024-08-29 12:39:53 +02:00
Pascal Serrarens
7d3fcba55d Removed Arduino include 2024-08-29 12:04:14 +02:00
Pascal Serrarens
a890cdb7fb Fix issues, add networking documentation 2024-08-29 11:44:42 +02:00
Pascal Serrarens
67b6d134e5 Improve perception 2 2024-08-29 11:31:21 +02:00
Pascal Serrarens
e3d5b993d9 Improve perception 2024-08-29 11:31:09 +02:00
Pascal Serrarens
05f4456c48 Updated linearalgebra 2024-08-28 12:12:15 +02:00
Pascal Serrarens
b0de0cf676 Moved to Polar/Spherical template classs 2024-08-28 11:33:32 +02:00
Pascal Serrarens
a98a483cb1 Fix Unit test 2024-08-28 10:29:40 +02:00
Pascal Serrarens
08eec48044 Spherical16 support 2024-08-28 09:42:51 +02:00
Pascal Serrarens
28340b1620 Add world orientation 2024-08-22 15:02:12 +02:00
Pascal Serrarens
f06eeb71ec Fix unit tests 2024-08-22 14:35:50 +02:00
Pascal Serrarens
b9ee5ff9dd Fix Spherical->Vector3 2024-08-22 12:50:03 +02:00
Pascal Serrarens
0ddaae8b6d Usaging SphericalOf 2024-08-22 12:28:34 +02:00
Pascal Serrarens
51546db8f2 Sync multiple children 2024-08-19 11:57:40 +02:00
Pascal Serrarens
58f2f4adce Add target 2024-08-19 11:57:23 +02:00
Pascal Serrarens
c421fd4db7 Use AngleAxis for tracked thing orientation (but this will change again in the future) 2024-08-06 12:10:35 +02:00
Pascal Serrarens
10700da996 Fix tests 2024-08-05 11:47:07 +02:00
Pascal Serrarens
9b0a5e066f Add add/subtract for discrete angles 2024-08-05 11:38:12 +02:00
Pascal Serrarens
ed715ed610 Fixed explicit Angle->float 2024-08-05 10:21:39 +02:00
Pascal Serrarens
246929a81d Fix precision 2024-08-02 14:28:08 +02:00
Pascal Serrarens
f3e2656502 Use Angle16 for servo angles 2024-08-02 09:10:42 +02:00
Pascal Serrarens
4b362fffa8 Extend Angle type usage 2024-08-02 08:54:00 +02:00
Pascal Serrarens
00f40fea98 Improve AngleOf usage 2024-07-31 11:44:43 +02:00
Pascal Serrarens
42d64a6afe Updated float16 2024-07-31 08:53:16 +02:00
Pascal Serrarens
d1d404f750 renamed float16 again 2024-07-02 12:31:59 +02:00
Pascal Serrarens
16a608c2b7 Renamed float16 2024-07-02 12:29:51 +02:00
Pascal Serrarens
c31fd5f911 Fix include 2024-07-02 12:28:05 +02:00
Pascal Serrarens
543ddf79b4 Cleanup 2024-07-02 11:33:53 +02:00
Pascal Serrarens
4223961fe7 Improved max vellocity 2024-07-02 11:31:36 +02:00
Pascal Serrarens
edf2df6c7e Improve receive pose orientation 2024-06-18 13:06:58 +02:00
Pascal Serrarens
b5fe2fda47 Improve receiving pose 2024-06-18 11:21:26 +02:00
Pascal Serrarens
bca786534d Cleanup 2024-06-17 14:30:39 +02:00
Pascal Serrarens
c299bb0018 Add SendInt 2024-06-17 14:30:31 +02:00
Pascal Serrarens
7dfd2b0004 Bugfixes 2024-06-17 12:03:57 +02:00
Pascal Serrarens
c52d009c91 Try to fix the submodule reference for automatic build 2024-06-17 11:21:00 +02:00
Pascal Serrarens
525ba3ea18 Perception initialization is now though adding sensors as children 2024-06-14 19:48:07 +02:00
Pascal Serrarens
4059e26027 Added Sphere perception 2024-06-07 17:47:42 +02:00
Pascal Serrarens
643129fdae Performance improvements 2024-06-07 14:00:40 +02:00
Pascal Serrarens
bc136362f2 things with spherical position and an orientation 2024-05-31 09:53:21 +02:00
Pascal Serrarens
186ccd92e5 Publish model when networkid was received 2024-05-29 12:18:11 +02:00
Pascal Serrarens
95988c924a Experimental Publish model support 2024-05-28 12:49:53 +02:00
Pascal Serrarens
57f7f56d26 Send Spherical using Angl8 and Float16 2024-05-27 17:32:37 +02:00
Pascal Serrarens
dc1abb2997 Increased buffersize to 256 bytes 2024-05-27 12:15:59 +02:00
Pascal Serrarens
3606cb642a Add float16 sending support 2024-05-27 12:14:56 +02:00
Pascal Serrarens
89453f621c Updated LinearAlgebra 2024-05-24 10:46:39 +02:00
Pascal Serrarens
52a75d6b7b Refactoring 2024-05-17 11:58:06 +02:00
Pascal Serrarens
1aa4520646 Inverstigation response 2024-05-17 11:57:47 +02:00
Pascal Serrarens
0ae0fd4e08 Fix include 2024-05-14 12:26:11 +02:00
Pascal Serrarens
fe50d79496 fix double/float conversion 2024-05-14 12:16:39 +02:00
Pascal Serrarens
dd7e2d7004 Updated LinearAlgebra 2024-05-14 12:09:48 +02:00
Pascal Serrarens
863fae2f19 Fix tests 2024-05-14 11:58:51 +02:00
Pascal Serrarens
b81b236ef4 Bugfixes 2024-05-14 11:58:42 +02:00
Pascal Serrarens
aa3f7a3351 Removed arduino include 2024-05-14 11:20:33 +02:00
Pascal Serrarens
eb15b11652 Updated LinearAlgebra 2024-05-14 09:21:50 +02:00
Pascal Serrarens
afa1809cb7 LinearAlgebra fixes 2024-05-10 18:27:27 +02:00
Pascal Serrarens
2b6912a2c9 LinearAlgebra updates 2024-05-10 18:20:09 +02:00
Pascal Serrarens
6ee5bc44f8 Bug fixes 2024-05-10 12:44:41 +02:00
Pascal Serrarens
ba18f5763f Performance improvement 2024-05-10 11:17:44 +02:00
Pascal Serrarens
2b392ef045 positive angle ->turn right 2024-05-10 11:10:16 +02:00
Pascal Serrarens
a41a2b2c04 Plane update improvement 2024-05-10 09:38:12 +02:00
Pascal Serrarens
0be698689d Add initial plane object support 2024-05-06 17:35:32 +02:00
Pascal Serrarens
0d3678350b Debug info improvement 2024-04-26 12:43:01 +02:00
Pascal Serrarens
ebc1dfba9c Performance improvement 2024-04-26 12:12:48 +02:00
Pascal Serrarens
7614064788 Improved network perception 2024-04-25 15:22:45 +02:00
Pascal Serrarens
0ba9d55a4f Synchronizing perception 2024-04-22 16:07:24 +02:00
Pascal Serrarens
bd335a123a Update linear algebra 2024-04-19 14:45:10 +02:00
Pascal Serrarens
9f00178a2a Add lastupdatetime 2024-04-19 14:44:58 +02:00
Pascal Serrarens
855ad81345 fix objId == 0 2024-04-19 14:44:10 +02:00
Pascal Serrarens
f6a38aaa04 Use index references 2024-04-19 14:43:33 +02:00
Pascal Serrarens
6dea063a4a Objects of different type are different 2024-04-18 17:33:28 +02:00
Pascal Serrarens
c9d2990da7 Add tracked object type 2024-04-18 17:24:59 +02:00
Pascal Serrarens
16e553907a Disable sendspherical16 and 32 2024-04-18 17:24:41 +02:00
Pascal Serrarens
2a221a0c22 Update perceived objects 2024-04-18 17:24:20 +02:00
Pascal Serrarens
70b068f870 Use experimental Linear Algebra 2024-04-18 12:30:41 +02:00
Pascal Serrarens
4be5c628b2 Initial message format description 2024-04-18 12:30:27 +02:00
Pascal Serrarens
09366aa962 Add SendPolar 2024-04-18 12:30:15 +02:00
Pascal Serrarens
c000cb3a0f Add GetThingsOfType 2024-04-18 12:29:51 +02:00
Pascal Serrarens
ba1dd195a6 Added type 2024-04-18 12:29:34 +02:00
Pascal Serrarens
cf3eef7cbb Update LinearAlgebra 2024-04-17 15:23:09 +02:00
Pascal Serrarens
d55e5cbf4a Add SetVelocity 2024-04-17 15:23:00 +02:00
Pascal Serrarens
c94c9e8879 Disable debugging 2024-04-17 15:22:43 +02:00
Pascal Serrarens
e94eb397bb Disable compact angle support 2024-04-17 15:22:19 +02:00
Pascal Serrarens
4403f7a341 Disable LH tracker hack 2024-04-17 15:21:58 +02:00
Pascal Serrarens
6576a38f9b Add SetVelocity 2024-04-17 15:21:37 +02:00
Pascal Serrarens
b0d0258ad6 Improved network sync 2024-04-10 15:35:06 +02:00
Pascal Serrarens
28bf3b4682 Fixed issues 2024-04-08 17:26:24 +02:00
Pascal Serrarens
920c90163d Publish relative object 2024-04-05 12:48:36 +02:00
Pascal Serrarens
141afa2772 Fix position send message 2024-03-19 12:15:21 +01:00
Pascal Serrarens
8a248814da Add TrackedObject orientation 2024-03-18 17:45:39 +01:00
Pascal Serrarens
577df7dc1a Prepare for orienation sync 2024-03-15 17:36:34 +01:00
Pascal Serrarens
04b0f01fb4 Update LinearAlgebra 2024-03-15 17:23:25 +01:00
Pascal Serrarens
11354c5e47 Update LinearAlgebra 2024-03-14 15:27:55 +01:00
Pascal Serrarens
a8829e7613 Update LinearAlgebra 2024-03-13 17:46:54 +01:00
Pascal Serrarens
3ba71b7330 Fix tests for LinearAlgebra 2024-03-12 11:03:20 +01:00
Pascal Serrarens
61b571c1a8 Updated LinearAlgebra 2024-03-05 11:51:53 +01:00
Pascal Serrarens
730720d6e2 Using Discrete angles 2024-03-05 09:55:29 +01:00
Pascal Serrarens
c90d11ae87 Move to LinearAlgebra 2024-03-05 09:13:46 +01:00
Pascal Serrarens
81b935694d Switch to LinearAlgebra 2024-03-05 09:06:12 +01:00
Pascal Serrarens
5cfe4ec3ac Renames Vector to Linear Algebra 2024-03-05 08:59:15 +01:00
Pascal Serrarens
3110e5f5be Send position&orientation 2024-03-04 12:23:17 +01:00
Pascal Serrarens
bfcda9a848 Updated VectorAlgebra 2024-02-27 14:41:44 +01:00
Pascal Serrarens
4272d912b9 Fixed poseType check 2024-02-27 14:27:06 +01:00
Pascal Serrarens
c2daeb2657 Add typed object receiver 2024-02-27 12:51:34 +01:00
Pascal Serrarens
3705fac2e1 Diabled Arduino rebug 2024-02-26 14:20:24 +01:00
Pascal Serrarens
6369723afc Updated vectoralgebra 2024-02-26 13:20:36 +01:00
Pascal Serrarens
98119cefd4 Update VectorAlgebra 2024-02-22 11:26:05 +01:00
Pascal Serrarens
945f8af503 Added SendPose 2024-02-21 15:45:09 +01:00
Pascal Serrarens
66ab007af9 Update vectoralgebra 2024-02-14 13:48:11 +01:00
Pascal Serrarens
c41fbbc309 Network send position 2024-02-14 13:47:01 +01:00
Pascal Serrarens
08e053f05a Updated vectoralgebra 2024-02-12 12:14:27 +01:00
Pascal Serrarens
4776907262 Fix not all servos in tree moving 2024-01-31 12:13:13 +01:00
Pascal Serrarens
8672e1519a Fix test 2024-01-31 10:55:20 +01:00
Pascal Serrarens
dce905f58b Renamed spherical magnitude to distance 2024-01-31 10:37:02 +01:00
Pascal Serrarens
59fab064a6 Removed Arduino include 2024-01-31 10:18:54 +01:00
Pascal Serrarens
c48b480304 Remove arduino include 2024-01-31 10:02:50 +01:00
Pascal Serrarens
0f1d6756af Merge hierarchy support 2024-01-31 09:58:36 +01:00
Pascal Serrarens
bc63b9300f Update VectorAlgebra lib 2024-01-31 09:54:06 +01:00
Pascal Serrarens
5b417ad9ce Renamed TrackedObject to InterestingThing 2024-01-31 09:50:48 +01:00
Pascal Serrarens
fe3ca768d0 Merge branch 'Improved-servo-support' into 'main'
Improved servo support

See merge request passer/cpp/roboidcontrol!3
2024-01-29 11:00:56 +00:00
Pascal Serrarens
af3d2531b2 Fixed issues 2024-01-29 11:58:23 +01:00
Pascal Serrarens
e995d4cec9 Fixed missing IncrementalEncoder.h 2024-01-29 10:48:37 +01:00
Pascal Serrarens
ae62974562 Generic velocity control for servos 2024-01-29 10:47:00 +01:00
Pascal Serrarens
d22fc8e244 Improved encoder support 2024-01-29 10:46:36 +01:00
Pascal Serrarens
6ef3da2b25 Made range inclusive 2024-01-24 11:30:23 +01:00
Pascal Serrarens
c8ac0b645f Initial version of synchronized motors 2024-01-23 17:44:27 +01:00
Pascal Serrarens
4fcbcf80ad Add check on perception and propulsion being null 2024-01-23 17:18:47 +01:00
Pascal Serrarens
ec1da8f81c Fixed warnings 2024-01-23 16:02:29 +01:00
Pascal Serrarens
b86484d59d Clean & pid tuning 2024-01-19 14:14:28 +01:00
Pascal Serrarens
f3021c1f58 transitions -> pulses per second 2024-01-19 14:14:00 +01:00
Pascal Serrarens
8b2f9439ca Add GetTargetSpeed 2024-01-19 14:13:37 +01:00
Pascal Serrarens
d5daab436e Update test compatiblity 2024-01-17 12:54:55 +01:00
Pascal Serrarens
91c766d5ce Added test 2024-01-17 12:00:35 +01:00
Pascal Serrarens
560b41a9f1 Updated CI script 2024-01-17 11:43:02 +01:00
Pascal Serrarens
4f71f939e0 Fix tests 2024-01-17 11:36:55 +01:00
Pascal Serrarens
047f1dac29 Extended tests 2024-01-17 11:20:39 +01:00
Pascal Serrarens
723c5a1cd7 Improved testing setup 2024-01-16 17:10:51 +01:00
Pascal Serrarens
ea4f4fdb19 Merge branch 'root-main-patch-77858' into 'main'
Add License

See merge request passer/cpp/roboidcontrol!2
2024-01-15 09:35:36 +00:00
Administrator
3b27edb086 Add License 2024-01-15 09:31:43 +00:00
Pascal Serrarens
a90442b304 Bug fixes 2024-01-15 09:40:27 +01:00
Pascal Serrarens
c07f81bce3 Improved network sync 2024-01-12 17:16:08 +01:00
Pascal Serrarens
89e0bf6f77 Added generic sync functions 2024-01-11 14:51:07 +01:00
Pascal Serrarens
df8bb6a722 Cleanup 2024-01-09 17:30:12 +01:00
Pascal Serrarens
3cc37ebae9 Working contolled motor 2024-01-09 17:14:33 +01:00
Pascal Serrarens
a21485857d Using Angle::PI 2024-01-09 12:28:39 +01:00
Pascal Serrarens
edf264c302 Encoder can evaluate velocity 2024-01-09 12:19:26 +01:00
Pascal Serrarens
8359351f78 Add generic IsOff 2024-01-09 10:22:13 +01:00
Pascal Serrarens
5ecbbaf463 Added initial actuation support 2024-01-08 14:23:59 +01:00
Pascal Serrarens
b954e2a302 Added initial accelerometer support 2024-01-08 14:23:42 +01:00
Pascal Serrarens
f12a658145 Extended servo support 2024-01-04 18:03:00 +01:00
Pascal Serrarens
63260e4141 Added Accelerometer 2024-01-04 18:02:47 +01:00
Pascal Serrarens
8b869e6759 renamed Servo to ServoMotor 2024-01-04 17:25:08 +01:00
Pascal Serrarens
6ce9d78b04 Servos and Controlled motor updates 2024-01-04 17:10:29 +01:00
Pascal Serrarens
0e11b0db5f Merge branch 'main' into ControlledMotor 2024-01-04 16:54:34 +01:00
Pascal Serrarens
a31440eee2 Fixed test 2024-01-04 16:53:59 +01:00
Pascal Serrarens
af18a28fc6 Removed Placement 2024-01-04 16:49:48 +01:00
Pascal Serrarens
291a234758 Merge branch 'main' into ControlledMotor 2024-01-04 16:47:14 +01:00
Pascal Serrarens
70ba3eae9c Removed the need for placement 2024-01-04 15:27:43 +01:00
Pascal Serrarens
51c676c155 Merge branch 'ControlledMotor' of http://gitlab.passervr.com/passer/cpp/roboidcontrol into ControlledMotor 2024-01-03 12:59:14 +01:00
Pascal Serrarens
118ab5d560 Updated 2024-01-03 12:58:38 +01:00
Pascal Serrarens
a4bb2cf55a Merge branch 'main' into ControlledMotor 2024-01-03 12:56:42 +01:00
Pascal Serrarens
c3cc48e723 Updated to latest VectorAlgebra 2024-01-03 12:13:09 +01:00
Pascal Serrarens
ae327c8bac compatiblity updates 2024-01-03 11:50:40 +01:00
Pascal Serrarens
000ca8d4e3 Fixed wrong include 2024-01-03 11:31:58 +01:00
Pascal Serrarens
502121ba3b Arduino IDE compatibility 2024-01-03 11:29:11 +01:00
Pascal Serrarens
c66a3215e1 Arduino IDE compatiblity 2024-01-03 11:16:12 +01:00
Pascal Serrarens
34d033ed42 Restore controlled motor files 2024-01-02 15:00:36 +01:00
Pascal Serrarens
4957be37e7 Update documentation 2024-01-02 12:12:34 +01:00
Pascal Serrarens
846e9c048f Updated documentation 2024-01-02 12:03:02 +01:00
Pascal Serrarens
ed89b91826 Add namespace 2024-01-02 11:55:03 +01:00
Pascal Serrarens
7ef620bedb Exclude build folder from documentation 2024-01-02 11:52:32 +01:00
Pascal Serrarens
fc246c8f1c Updated documentation 2024-01-02 11:52:14 +01:00
Pascal Serrarens
2d94f61c83 Renamed perceived object to tracked object 2024-01-02 11:52:02 +01:00
Pascal Serrarens
6cce388a7d Moved position/orientation to roboid 2024-01-02 11:02:00 +01:00
Pascal Serrarens
cce691f3dd Fix basic test 2024-01-02 10:25:43 +01:00
Pascal Serrarens
89e4aef01f fix float/double conversion 2023-12-31 17:10:51 +01:00
Pascal Serrarens
93065935ad make confidence unsigned char 2023-12-31 17:10:31 +01:00
Pascal Serrarens
de5832b413 adjusted basic test (as it is failing atm :-) 2023-12-31 17:07:38 +01:00
Pascal Serrarens
63726b0663 Separated out perceived object 2023-12-31 17:07:09 +01:00
Pascal Serrarens
5e09a4d454 Update VectorAlgebra submodule commit 2023-12-31 16:49:10 +01:00
Pascal Serrarens
000174a11a Merge remote-tracking branch 'origin/main' into ObjectPerception 2023-12-31 16:47:30 +01:00
Pascal Serrarens
f4e7c01fe5 Update .gitmodules 2023-12-31 15:45:48 +00:00
Pascal Serrarens
3269b0e5b9 Merge remote-tracking branch 'origin/main' into ObjectPerception 2023-12-31 16:41:44 +01:00
Pascal Serrarens
188d8874f8 Typo 2023-12-31 16:40:54 +01:00
Pascal Serrarens
16b45a40d3 Merge remote-tracking branch 'origin/main' into ObjectPerception 2023-12-31 16:39:40 +01:00
Pascal Serrarens
238164399d Extend test script 2023-12-31 16:39:11 +01:00
Pascal Serrarens
193f557d5e Change test script to BB2B 2023-12-31 16:36:28 +01:00
Pascal Serrarens
b9be5e28aa Renamed dummy_test to bb2b_test 2023-12-31 16:33:43 +01:00
Pascal Serrarens
90d186806e Extend dummy test 2023-12-31 16:29:39 +01:00
Pascal Serrarens
9696f4bf80 Add math reference 2023-12-31 10:03:59 +01:00
Pascal Serrarens
bc5a737e41 Remove Arduino reference 2023-12-31 10:02:06 +01:00
Pascal Serrarens
c70860bd66 Remove arduino reference 2023-12-31 10:00:10 +01:00
Pascal Serrarens
8246b2708a Merge remote-tracking branch 'origin/main' into ObjectPerception 2023-12-31 09:55:44 +01:00
Pascal Serrarens
8e7be85ac6 Generic Network sync 2023-12-31 09:52:51 +01:00
Pascal Serrarens
aad76d318a Update gitignore 2023-12-31 09:34:31 +01:00
Pascal Serrarens
3de05ae621 Fixed testing (I think) 2023-12-31 09:34:06 +01:00
Pascal Serrarens
2c4f857e2d Updated gitignore 2023-12-31 09:18:17 +01:00
Pascal Serrarens
7f37a0b3e7 Add VectorAlgebra to makefiles 2023-12-31 09:08:39 +01:00
Pascal Serrarens
50999805cd Replace vector left/right with direct values 2023-12-31 09:00:29 +01:00
Pascal Serrarens
9384995e12 Typo 2023-12-31 08:53:50 +01:00
Pascal Serrarens
f559566ef4 Fixed includes 2023-12-31 08:46:39 +01:00
Pascal Serrarens
14f162c67f Added include 2023-12-31 08:42:56 +01:00
Pascal Serrarens
b55c7d5725 Extended dummy test 2023-12-31 08:42:06 +01:00
Pascal Serrarens
393a6643fd Updated doxygen style 2023-12-31 08:37:29 +01:00
Pascal Serrarens
5e6bd0e748 replace sensor scan by object scan 2023-12-30 17:26:40 +01:00
Pascal Serrarens
e120cbe020 network sync integration 2023-12-30 17:26:27 +01:00
Pascal Serrarens
7c960d2c07 Update Dummy_test.cc 2023-12-30 14:45:01 +00:00
Pascal Serrarens
46de37b772 Update .gitlab-ci.yml 2023-12-30 14:43:37 +00:00
Pascal Serrarens
ed3456a5ef Update CMakeLists.txt 2023-12-30 14:39:51 +00:00
Pascal Serrarens
393bb8f261 Update CMakeLists.txt 2023-12-30 14:38:20 +00:00
Pascal Serrarens
80d062b3fb Update CMakeLists.txt 2023-12-30 14:32:19 +00:00
Pascal Serrarens
8a86e4e223 Update .gitlab-ci.yml file 2023-12-30 14:30:12 +00:00
Pascal Serrarens
ff68de638b Add new file 2023-12-30 14:29:12 +00:00
Pascal Serrarens
871dc4849e Add new directory 2023-12-30 14:28:48 +00:00
Pascal Serrarens
ce335377e0 Update CMakeLists.txt 2023-12-30 14:28:28 +00:00
Pascal Serrarens
9a70b3d3d2 Add sensor reference for perceived objects 2023-12-30 09:28:26 +01:00
Pascal Serrarens
fe16f25859 Add external sensing support 2023-12-30 09:28:09 +01:00
Pascal Serrarens
4f7e911be1 Object perception with distance sensors 2023-12-29 15:35:56 +01:00
Pascal Serrarens
e51f5a38e0 Remove Arduino dependency 2023-12-29 12:41:04 +01:00
Pascal Serrarens
2655734d13 Update object location based on roboid pose 2023-12-29 12:40:38 +01:00
Pascal Serrarens
b9098a4ac4 Object perception 2023-12-29 10:41:39 +01:00
Pascal Serrarens
c872a63eb2 Setters for verlocity and angular velocity 2023-12-29 10:41:28 +01:00
Pascal Serrarens
a6d1b0c945 Angular velocity support 2023-12-29 10:40:58 +01:00
Pascal Serrarens
e0230a7684 improved initialization 2023-12-28 09:38:26 +01:00
Pascal Serrarens
30c74c44a4 Get Polar velocity 2023-12-28 09:08:13 +01:00
Pascal Serrarens
a502af99d4 Improved object perception 2023-12-17 12:43:50 +01:00
Pascal Serrarens
47556d1d5d Arduino compatibility 2023-12-16 09:44:17 +01:00
Pascal Serrarens
4e186b875a Add GetPerceivedObjects 2023-12-08 17:51:22 +01:00
Pascal Serrarens
470b2e21e5 Working object perception 2023-12-08 15:28:03 +01:00
Pascal Serrarens
55cca93d67 Made propulsion optional 2023-12-08 09:44:30 +01:00
Pascal Serrarens
3e969a3939 Cleanup 2023-12-07 10:35:37 +01:00
Pascal Serrarens
47dbbc5b61 Make GetDistance using direction/range 2023-12-07 10:02:08 +01:00
Pascal Serrarens
2d5b3998d7 Fixed quadcopter support 2023-12-06 13:09:13 +01:00
Pascal Serrarens
938bd7ceda Reverse merge main 2023-12-06 13:04:58 +01:00
Pascal Serrarens
2a37bb20ef Update .gitmodules to support ssh 2023-12-06 11:51:57 +00:00
Pascal Serrarens
b527aeb97b Simplified perception 2023-12-06 12:46:08 +01:00
Pascal Serrarens
733a09ce91 Crazyflie compatibility 2023-12-06 09:59:35 +01:00
Pascal Serrarens
7e7db715b8 Changed SwitchOn to ObjectNearby 2023-12-05 12:39:12 +01:00
Pascal Serrarens
da29673459 Updated Documentation 2023-12-05 12:25:27 +01:00
Pascal Serrarens
58448538fb Encode is part of ControllerMotor branch 2023-12-05 11:40:11 +01:00
Pascal Serrarens
20306d49be Servo support postponed 2023-12-05 11:37:37 +01:00
Pascal Serrarens
2c8ae025a8 Moved Quadcoptger to branch 2023-12-05 11:37:06 +01:00
Pascal Serrarens
a7020364d1 Quadcopter documentation 2023-12-05 11:36:04 +01:00
Pascal Serrarens
ecfe884992 IMU support postponed 2023-12-05 11:34:21 +01:00
Pascal Serrarens
d07ed323e2 Cleanup based on ControlledMotor branch 2023-12-05 11:28:44 +01:00
Pascal Serrarens
1b36f97e18 Moved ControlledMotor to branch 2023-12-05 11:18:38 +01:00
Pascal Serrarens
f4b0eb1743 Updated Motor documentation 2023-12-05 11:15:15 +01:00
Pascal Serrarens
f33b02311c Updated Thing 2023-12-05 11:13:13 +01:00
Pascal Serrarens
7c5a531e0c Cleanup Placement 2023-12-05 10:21:40 +01:00
Pascal Serrarens
8e432e4ef9 Percpetion constructor without sensorCount 2023-12-05 09:43:36 +01:00
Pascal Serrarens
5e057710b4 Cleanup propulsion 2023-12-05 09:43:15 +01:00
Pascal Serrarens
67ff10769a Make DiffDrive subclass of propulsion 2023-12-04 12:47:18 +01:00
Pascal Serrarens
07389498dd Replaced Sensing by perception 2023-12-04 10:52:46 +01:00
Pascal Serrarens
d348070092 Removed printfs 2023-12-04 10:44:54 +01:00
Pascal Serrarens
b2914e437b Improvements 2023-12-04 10:38:07 +01:00
Pascal Serrarens
7c68558d80 Updated VectorAlgebra submodule branch 2023-12-01 09:14:26 +01:00
Pascal Serrarens
c233488885 AVR compatibility 2023-11-29 17:03:49 +01:00
Pascal Serrarens
32909f20be Removed need for abs() 2023-11-28 16:01:47 +01:00
Pascal Serrarens
1df58e9066 Cleanup motor 2023-11-28 15:57:12 +01:00
Pascal Serrarens
bab29a01c5 Documentation 2023-11-28 15:02:24 +01:00
Pascal Serrarens
31e802b51b Added namespaces 2023-11-28 12:53:07 +01:00
Pascal Serrarens
18f1279c95 Delete DoxyWarnLogfile.txt 2023-11-28 11:24:27 +00:00
Pascal Serrarens
4e6c697af8 Updated gitignore 2023-11-28 12:23:16 +01:00
Pascal Serrarens
e1459a347a Add README.md 2023-11-28 11:12:37 +00:00
Pascal Serrarens
2d20113355 Merge branch 'master' of http://gitlab.passervr.com/passer/cpp/roboidcontrol 2023-11-27 17:03:18 +01:00
Pascal Serrarens
47131d56bc Updated doxygen settings 2023-11-27 17:03:09 +01:00
Pascal Serrarens
5a6c4fcaef controlled motor support improved 2023-11-25 16:10:08 +01:00
Pascal Serrarens
ae5ed79700 trajectory using propulsion 2023-11-24 17:48:09 +01:00
Pascal Serrarens
d2b240a514 Real trajectory 2023-11-24 17:32:21 +01:00
Pascal Serrarens
6058d27079 First trajectory 2023-11-24 17:11:18 +01:00
Pascal Serrarens
28ee532700 Initial attempt for scripting 2023-11-24 12:28:56 +01:00
Pascal Serrarens
afa459b120 Added accelerometer & magnetometer framework 2023-11-23 17:51:20 +01:00
Pascal Serrarens
438d8ba941 Added a bit of documentation 2023-11-23 16:52:21 +01:00
Pascal Serrarens
ff7ad8d3df Updated doxyfile 2023-11-23 16:43:19 +01:00
Pascal Serrarens
1b48a061d1 Merge branch 'master' of http://gitlab.passervr.com/passer/cpp/roboidcontrol 2023-11-23 15:55:59 +01:00
Pascal Serrarens
07254fd3ac Updated documentation 2023-11-23 15:55:55 +01:00
Pascal Serrarens
1f42253457 Make override possible 2023-11-23 14:54:10 +01:00
Pascal Serrarens
8d3cfdfa51 Changed from sensing to perception 2023-11-22 15:06:10 +01:00
Pascal Serrarens
66c60b66ed Added perception 2023-11-21 17:38:48 +01:00
Pascal Serrarens
bcbec5da32 Add GetDistance(angle) 2023-11-21 15:32:34 +01:00
Pascal Serrarens
2ff984b5bc Added component 2023-11-21 14:38:45 +01:00
Pascal Serrarens
c2478ce057 Added ESP-IDF component support 2023-11-21 14:35:51 +01:00
Pascal Serrarens
a227f247e0 Formatting 2023-11-16 10:45:15 +01:00
Pascal Serrarens
1abe40815e Bug fixes 2023-11-16 10:43:31 +01:00
Pascal Serrarens
48b80fb9ed Update quadcopter support 2023-11-14 17:37:08 +01:00
Pascal Serrarens
b5649216df Extended DistanceSensor 2023-11-14 17:15:17 +01:00
Pascal Serrarens
46142f6e29 Updates for Quadcopter support 2023-11-10 15:37:35 +01:00
Pascal Serrarens
d3015be69c Add quadcopter support 2023-11-07 17:36:19 +01:00
Pascal Serrarens
5c8d7df31b Simulator compatibility 2023-11-07 15:11:33 +01:00
Pascal Serrarens
a3f0af62c9 Fixed include 2023-11-06 15:33:40 +01:00
Pascal Serrarens
189ea6c689 Initial commit 2023-11-06 14:24:18 +01:00
119 changed files with 6857 additions and 57 deletions

4
.gitignore vendored
View File

@ -1,2 +1,4 @@
doxygen/html
doxygen/DoxyWarnLogfile.txt
build
.vscode
.vscode

61
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,61 @@
# This file is a template, and might need editing before it works on your project.
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
#
# A pipeline is composed of independent jobs that run scripts, grouped into stages.
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
# This file is a template, and might need editing before it works on your project.
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
#
# A pipeline is composed of independent jobs that run scripts, grouped into stages.
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
variables:
GIT_SUBMODULE_STRATEGY: recursive
default:
image: rikorose/gcc-cmake
stages:
- test
unit-test-job:
stage: test
script:
- mkdir build
- cd build
- cmake ..
- cmake --build .
- export GTEST_OUTPUT="xml:report.xml"
- ls -la
- ls -ls test
- "./test/RoboidControlTest"
artifacts:
when: always
reports:
junit: build/report.xml
sast:
stage: test
include:
- template: Security/SAST.gitlab-ci.yml

7
.gitmodules vendored Normal file
View File

@ -0,0 +1,7 @@
[submodule "LinearAlgebra"]
path = LinearAlgebra
url = ../linear-algebra.git
brnach = main
[submodule "float16"]
path = float16
url = ../float16.git

2
AbsoluteEncoder.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "AbsoluteEncoder.h"

17
AbsoluteEncoder.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include "ServoMotor.h"
namespace Passer {
namespace RoboidContol {
class AbsoluteEncoder {
public:
AbsoluteEncoder() {}
virtual Angle16 GetActualAngle() = 0;
virtual float GetActualVelocity() = 0;
};
} // namespace RoboidContol
} // namespace Passer

5
Accelerometer.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "Accelerometer.h"
Accelerometer::Accelerometer() {}
Spherical Accelerometer::GetVector() { return Spherical(); }

18
Accelerometer.h Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "LinearAlgebra/Spherical.h"
#include "Sensor.h"
namespace Passer {
namespace RoboidControl {
class Accelerometer : public Sensor {
public:
Accelerometer();
virtual Spherical GetVector();
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

46
Activation.cpp Normal file
View File

@ -0,0 +1,46 @@
#include "Activation.h"
float Activation::HeavisideStep(float inputValue, float bias) {
return (inputValue + bias > 0) ? 1.0F : 0.0F;
}
float Activation::Tanh(float inputValue) {
return (exp(inputValue) - exp(-inputValue)) / (exp(inputValue) + exp(-inputValue));
}
float Activation::Sigmoid(float inputValue) {
return 1 / (1 + expf(-inputValue));
}
float Activation::Linear(float inputValue, float minValue, float range) {
if (inputValue > minValue + range)
return 0;
if (inputValue < minValue)
return 1;
float f = (inputValue - minValue) * (1 / range); // normalize to 1..0
float influence = 1 - f; // invert
return influence;
}
float Activation::Quadratic(float inputValue, float minValue, float range) {
if (inputValue > minValue + range)
return 0;
if (inputValue < minValue)
return 1;
float f = (inputValue - minValue) * (1 / range); // normalize to 1..0
float influence = 1 - (f * f); // quadratic & invert
return influence;
}
float Activation::ParticleLife(float minValue, float maxValue, float attraction, float inputValue) {
if (inputValue < minValue)
return inputValue / minValue - 1;
if (inputValue < maxValue)
return attraction * (1 - fabs(2 * inputValue - minValue - maxValue) / (maxValue - minValue));
return 0;
}

32
Activation.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef RC_ACTIVATION_H
#define RC_ACTIVATION_H
#include <math.h>
namespace Passer {
namespace RoboidControl {
/// @brief Activation function for control
/// @note This is mainly for future use :-)
class Activation {
public:
static float HeavisideStep(float inputValue, float bias = 0); // Range: {0,1}
static float Tanh(float inputValue); // Range: (-1, 1)
static float Sigmoid(float inputValue); // Range: (0, 1)
static float Linear(float inputValue, float bias = 0, float range = 0);
static float Quadratic(float inputValue, float bias = 0,
float range = 0); // minValue = bias
static float ParticleLife(float minValue, float maxValue, float attraction,
float inputValue); // minValue = bias
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;
#endif

View File

@ -1,61 +1,65 @@
cmake_minimum_required(VERSION 3.13) # CMake version check
if(ESP_PLATFORM)
idf_component_register(
SRC_DIRS "."
INCLUDE_DIRS "."
)
else()
project(ControlCore)
add_subdirectory(LinearAlgebra)
set(CMAKE_CXX_STANDARD 11) # Enable c++11 standard
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_definitions(GTEST)
include(FetchContent)
FetchContent_Declare(
googletest
DOWNLOAD_EXTRACT_TIMESTAMP ON
URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
include_directories(
set(sourcedirs
.
LinearAlgebra
)
add_library(ControlCore STATIC
"Thing.cpp"
"LowLevelMessages.cpp"
"Messages.cpp"
"Participant.cpp"
"float16.cpp"
)
enable_testing()
file(GLOB_RECURSE test_srcs test/*_test.cc)
add_executable(
ControlCoreTest
${test_srcs}
)
target_link_libraries(
ControlCoreTest
gtest_main
ControlCore
)
if(MSVC)
target_compile_options(ControlCoreTest PRIVATE /W4 /WX)
else()
target_compile_options(ControlCoreTest PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()
set(includedirs
.
LinearAlgebra
ControlCore
)
include(GoogleTest)
gtest_discover_tests(ControlCoreTest)
idf_component_register(
SRC_DIRS ${sourcedirs}
INCLUDE_DIRS ${includedirs}
REQUIRES arduino
)
endif()
project(RoboidControl)
add_subdirectory(ControlCore)
#add_subdirectory(LinearAlgebra)
add_subdirectory(test)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_definitions(GTEST)
include(FetchContent)
FetchContent_Declare(
googletest
DOWNLOAD_EXTRACT_TIMESTAMP ON
URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
include_directories(
.
ControlCore
LinearAlgebra
)
add_library(RoboidControl STATIC
"Roboid.cpp"
"Perception.cpp"
"TrackedObject.cpp"
"Propulsion.cpp"
"Motor.cpp"
"DifferentialDrive.cpp"
"DistanceSensor.cpp"
"Sensor.cpp"
"Switch.cpp"
"Quadcopter.cpp"
#"Messages.cpp"
)
enable_testing()
include(GoogleTest)

2
ControlCore/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build
.vscode

View File

@ -0,0 +1,61 @@
cmake_minimum_required(VERSION 3.13) # CMake version check
if(ESP_PLATFORM)
idf_component_register(
SRC_DIRS "."
INCLUDE_DIRS "."
)
else()
project(ControlCore)
add_subdirectory(LinearAlgebra)
set(CMAKE_CXX_STANDARD 11) # Enable c++11 standard
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_definitions(GTEST)
include(FetchContent)
FetchContent_Declare(
googletest
DOWNLOAD_EXTRACT_TIMESTAMP ON
URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
include_directories(
.
LinearAlgebra
)
add_library(ControlCore STATIC
"Thing.cpp"
"LowLevelMessages.cpp"
"Messages.cpp"
"Participant.cpp"
"float16.cpp"
)
enable_testing()
file(GLOB_RECURSE test_srcs test/*_test.cc)
add_executable(
ControlCoreTest
${test_srcs}
)
target_link_libraries(
ControlCoreTest
gtest_main
ControlCore
)
if(MSVC)
target_compile_options(ControlCoreTest PRIVATE /W4 /WX)
else()
target_compile_options(ControlCoreTest PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()
include(GoogleTest)
gtest_discover_tests(ControlCoreTest)
endif()

View File

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.13) # CMake version check
Project(ControlCoreTest)
set(CMAKE_CXX_STANDARD 11) # Enable c++11 standard
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
add_compile_definitions(GTEST)
include(FetchContent)
FetchContent_Declare(
googletest
DOWNLOAD_EXTRACT_TIMESTAMP ON
URL https://github.com/google/googletest/archive/refs/heads/main.zip
)
# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
include_directories(
.
..
)
enable_testing()
add_executable(
ControlCoreTest
"dummy_test.cc"
)
target_link_libraries(
ControlCoreTest
gtest_main
)
include(GoogleTest)
gtest_discover_tests(ControlCoreTest)

65
ControlledMotor.cpp Normal file
View File

@ -0,0 +1,65 @@
#include "ControlledMotor.h"
ControlledMotor::ControlledMotor() {
this->type = (unsigned char)Type::ControlledMotor;
}
ControlledMotor::ControlledMotor(Motor *motor, Encoder *encoder)
: ControlledMotor() {
this->motor = motor;
this->encoder = encoder;
// this->rotationDirection = Direction::Forward;
}
#include <Arduino.h>
void ControlledMotor::SetTargetSpeed(float speed) {
this->currentTargetSpeed = speed;
// this->rotationDirection =
// (targetSpeed < 0) ? Direction::Reverse : Direction::Forward;
// this->direction = (targetSpeed < 0) ? Motor::Direction::CounterClockwise
// : Motor::Direction::Clockwise;
}
void ControlledMotor::Update(unsigned long currentTimeMs) {
this->actualSpeed = encoder->GetRevolutionsPerSecond(currentTimeMs);
if (this->currentTargetSpeed < 0)
this->actualSpeed = -this->actualSpeed;
float deltaTime = currentTimeMs - this->lastUpdateTime;
float error = this->currentTargetSpeed - this->actualSpeed;
float errorChange = (error - lastError) * deltaTime;
float delta = error * pidP + errorChange * pidD;
Serial.print(" actual Speed ");
Serial.print(actualSpeed);
Serial.print(" target Speed ");
Serial.print(this->currentTargetSpeed);
Serial.print(" motor target speed ");
Serial.print(motor->currentTargetSpeed);
Serial.print(" + ");
Serial.print(error * pidP);
Serial.print(" + ");
Serial.print(errorChange * pidD);
Serial.print(" = ");
Serial.println(motor->currentTargetSpeed + delta);
motor->SetTargetSpeed(motor->currentTargetSpeed +
delta); // or something like that
this->lastUpdateTime = currentTimeMs;
}
float ControlledMotor::GetActualSpeed() { return actualSpeed; }
bool ControlledMotor::Drive(float distance) {
if (!driving) {
targetDistance = distance;
startDistance = encoder->GetDistance();
driving = true;
}
float totalDistance = encoder->GetDistance() - startDistance;
bool completed = totalDistance > targetDistance;
return completed;
}

60
ControlledMotor.h Normal file
View File

@ -0,0 +1,60 @@
#pragma once
#include "Encoder.h"
#include "Motor.h"
namespace Passer {
namespace RoboidControl {
/// @brief A motor with speed control
/// It uses a feedback loop from an encoder to regulate the speed
/// The speed is measured in revolutions per second.
class ControlledMotor : public Motor {
public:
ControlledMotor();
ControlledMotor(Motor *motor, Encoder *encoder);
inline static bool CheckType(Thing *thing) {
return (thing->type & (int)Thing::Type::ControlledMotor) != 0;
}
float velocity;
float pidP = 0.1F;
float pidD = 0.0F;
float pidI = 0.0F;
void Update(unsigned long currentTimeMs) override;
/// @brief Set the target speed for the motor controller
/// @param speed the target in revolutions per second.
virtual void SetTargetSpeed(float speed) override;
/// @brief Get the actual speed from the encoder
/// @return The speed in revolutions per second
virtual float GetActualSpeed() override;
bool Drive(float distance);
Motor *motor;
Encoder *encoder;
protected:
float lastUpdateTime = 0;
float lastError = 0;
// float targetSpeed;
float actualSpeed;
float netDistance = 0;
float startDistance = 0;
// enum Direction { Forward = 1, Reverse = -1 };
// Direction rotationDirection;
bool driving = false;
float targetDistance = 0;
float lastEncoderPosition = 0;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

119
DifferentialDrive.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "DifferentialDrive.h"
#include "LinearAlgebra/Angle.h"
#include "LinearAlgebra/FloatSingle.h"
#include <math.h>
DifferentialDrive::DifferentialDrive() {};
DifferentialDrive::DifferentialDrive(Motor *leftMotor, Motor *rightMotor) {
this->motorCount = 2;
this->motors = new Motor *[2];
this->motors[0] = leftMotor;
this->motors[1] = rightMotor;
float distance = this->wheelSeparation / 2;
leftMotor->direction = Motor::Direction::CounterClockwise;
leftMotor->SetPosition(Spherical16(distance, Direction16::left));
// leftMotor->position.direction.horizontal = Angle16::Degrees(-90);
// leftMotor->position.distance = distance;
rightMotor->direction = Motor::Direction::Clockwise;
rightMotor->SetPosition(Spherical16(distance, Direction16::right));
// rightMotor->position.direction.horizontal = Angle16::Degrees(90);
// rightMotor->position.distance = distance;
}
void DifferentialDrive::SetDimensions(float wheelDiameter,
float wheelSeparation) {
this->wheelDiameter = wheelDiameter;
this->wheelSeparation = wheelSeparation;
this->rpsToMs = wheelDiameter * Passer::LinearAlgebra::pi;
float distance = this->wheelSeparation / 2;
Spherical16 motor0Position = this->motors[0]->GetPosition();
motor0Position.distance = distance;
this->motors[0]->SetPosition(motor0Position);
Spherical16 motor1Position = this->motors[0]->GetPosition();
motor1Position.distance = distance;
this->motors[1]->SetPosition(motor1Position);
}
void DifferentialDrive::SetMotorTargetSpeeds(float leftSpeed,
float rightSpeed) {
for (unsigned int motorIx = 0; motorIx < this->motorCount; motorIx++) {
Motor *motor = motors[motorIx];
if (motor == nullptr)
continue;
float xPosition =
motors[motorIx]->GetPosition().direction.horizontal.InDegrees();
if (xPosition < 0)
motor->SetTargetSpeed(leftSpeed);
else if (xPosition > 0)
motor->SetTargetSpeed(rightSpeed);
};
}
void DifferentialDrive::SetTwistSpeed(float forward, float yaw) {
float leftSpeed =
Float::Clamp(forward + yaw, -1, 1); // revolutions per second
float rightSpeed =
Float::Clamp(forward - yaw, -1, 1); // revolutions per second
float leftMotorSpeed = leftSpeed / rpsToMs; // meters per second
float rightMotorSpeed = rightSpeed / rpsToMs; // meters per second
SetMotorTargetSpeeds(leftMotorSpeed, rightMotorSpeed);
}
void DifferentialDrive::SetTwistSpeed(Vector2 linear, float yaw) {
SetTwistSpeed(linear.y, yaw);
}
void DifferentialDrive::SetTwistSpeed(Vector3 linear, float yaw, float pitch,
float roll) {
SetTwistSpeed(linear.Forward(), yaw);
}
// void DifferentialDrive::SetVelocity(Polar velocity) {
// SetTwistSpeed(velocity.distance, velocity.angle.InDegrees());
// }
// Spherical16 DifferentialDrive::GetVelocity() {
// Motor *leftMotor = motors[0];
// Motor *rightMotor = motors[1];
// float leftSpeed = leftMotor->GetActualSpeed(); // in revolutions per
// second float rightSpeed = rightMotor->GetActualSpeed(); // in revolutions
// per second
// leftSpeed = leftSpeed * rpsToMs; // in meters per second
// rightSpeed = rightSpeed * rpsToMs; // in meters per second
// float speed = (leftSpeed + rightSpeed) / 2;
// float direction = speed >= 0 ? 0.0F : 180.0F;
// float magnitude = fabsf(speed);
// Spherical16 velocity =
// Spherical16(magnitude, Angle16::Degrees(direction),
// Angle16::Degrees(0)); // Polar(direction, magnitude);
// return velocity;
// }
// float DifferentialDrive::GetAngularVelocity() {
// Motor *leftMotor = motors[0];
// Motor *rightMotor = motors[1];
// float leftSpeed = leftMotor->GetActualSpeed(); // in revolutions per
// second float rightSpeed = rightMotor->GetActualSpeed(); // in revolutions
// per second
// leftSpeed = leftSpeed * rpsToMs; // in meters per second
// rightSpeed = rightSpeed * rpsToMs; // in meters per second
// float angularSpeed = (leftSpeed - rightSpeed) / 2;
// float angularDistance = wheelSeparation / 2 * Passer::LinearAlgebra::pi;
// float rotationsPerSecond = angularSpeed / angularDistance;
// float degreesPerSecond =
// Angle::Normalize(Angle::Degrees(360 * rotationsPerSecond)).InDegrees();
// float angularVelocity = degreesPerSecond;
// return angularVelocity;
// }

90
DifferentialDrive.h Normal file
View File

@ -0,0 +1,90 @@
#pragma once
#include "Propulsion.h"
namespace Passer {
namespace RoboidControl {
/// @brief A two-wheeled Propulsion method
///
/// The wheels are put at either side of the roboid with the following behaviour
/// * When both wheels spin forward, the Roboid moves forward
/// * When both wheels spin backward, the Roboid moves backward
/// * When both wheels are spinning in opposite directions, the Roboid rotates
/// wihout moving forward or backward
/// * When just one wheel is spinning, the Roboid turnes while moving forward or
/// backward.
class DifferentialDrive : public Propulsion {
public:
/// @brief Default constructor
DifferentialDrive();
/// @brief Setup of the DifferentialDrive with the Placement of the motors
/// @param leftMotorPlacement Placement of the left Motor
/// @param rightMotorPlacement Placement of the right Motor
/// In this setup, the left motor Direction will be CounterClockWise when
/// driving forward, while the right motor will turn Clockwise.
/// @note When not using controlled motors, the placement of the motors is
/// irrelevant.
// DifferentialDrive(Placement leftMotorPlacement,
// Placement rightMotorPlacement);
DifferentialDrive(Motor *leftMotor, Motor *rightMotor);
void SetDimensions(float wheelDiameter, float wheelSeparation);
/// @brief Set the target speeds of the motors directly
/// @param leftSpeed The target speed of the left Motor
/// @param rightSpeed The target speed of the right Motor
void SetMotorTargetSpeeds(float leftSpeed, float rightSpeed);
/// @brief Controls the motors through forward and rotation speeds
/// @param forward The target forward speed of the Roboid
/// @param yaw The target rotation speed of the Roboid
virtual void SetTwistSpeed(float forward, float yaw) override;
/// @brief Controls the motors through forward and rotation speeds
/// @param linear The target linear speed of the Roboid
/// @param yaw The target rotation speed of the Roboid
/// @note As a DifferentialDrive cannot move sideward, this function has the
/// same effect as using the void SetTwistSpeed(float forward, float yaw)
/// function.
virtual void SetTwistSpeed(Vector2 linear, float yaw = 0.0F);
/// @brief Controls the motors through forward and rotation speeds
/// @param linear The target linear speed
/// @param yaw The target rotation speed around the vertical axis
/// @param pitch Pitch is not supported and is ignored
/// @param roll Roll is not supported and is ignores
/// @note As a DifferentialDrive cannot move sideward or vertical, this
/// function has the same effect as using the void SetTwistSpeed(float
/// forward, float yaw) function.
virtual void SetTwistSpeed(Vector3 linear, float yaw = 0.0F,
float pitch = 0.0F, float roll = 0.0F);
// virtual void SetVelocity(Polar velocity);
/// @brief Calculate the linear velocity of the roboid based on the wheel
/// velocities
/// @return The velocity of the roboid in local space
/// @details The actual values may not be accurate, depending on the available
/// information
/// @remark This will be more expanded/detailed in a future version of Roboid
/// Control
// virtual Spherical16 GetVelocity() override;
/// @brief Calculate the angular velocity of the roboid based on the wheel
/// velocities
/// @return The angular speed of the roboid in local space
/// @details The actual value may not be accurate, depending on the available
/// information
/// @remark This will be more expanded/detailed in a future version of Roboid
/// Control
// virtual float GetAngularVelocity() override;
protected:
float wheelDiameter = 1.0F; // in meters
float wheelSeparation = 1.0F; // in meters;
float rpsToMs = 1.0F; // convert revolutions per second to meters per second
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

15
DirectionalSensor.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "DirectionalSensor.h"
#include "ControlCore/LowLevelMessages.h"
DirectionalSensor::DirectionalSensor() : Sensor() {
this->type = (unsigned char)Type::DirectionalSensor;
this->vector = Spherical16::zero;
}
Spherical16 DirectionalSensor::GetVector() { return Spherical16::zero; }
void DirectionalSensor::ProcessBytes(unsigned char *data) {
unsigned char ix = 0;
this->vector = LowLevelMessages::ReceiveSpherical16(data, &ix);
}

30
DirectionalSensor.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include "Sensor.h"
namespace Passer {
namespace RoboidControl {
/// @brief A Sensor which can measure the distance to the nearest object
class DirectionalSensor : public Sensor {
public:
/// @brief Default constructor
DirectionalSensor();
// const unsigned int Type = SensorType | (unsigned
// int)Type::DirectionalSensor;
/// @brief Determine the distance to the nearest object
/// @return the measured distance in meters to the nearest object
virtual Spherical16 GetVector();
virtual void ProcessBytes(unsigned char *bytes) override;
protected:
/// @brief Distance to the closest object
Spherical16 vector = Spherical16::zero;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

37
DistanceSensor.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "DistanceSensor.h"
#include "ControlCore/LowLevelMessages.h"
#include <math.h>
DistanceSensor::DistanceSensor() : Sensor() {
this->type = (unsigned char)Type::DistanceSensor;
this->distance = INFINITY;
this->triggerDistance = 1.0F;
}
DistanceSensor::DistanceSensor(float triggerDistance) : DistanceSensor() {
this->triggerDistance = triggerDistance;
}
float DistanceSensor::GetDistance() {
if (this->distance < minRange || this->distance > maxRange)
return INFINITY; // invalid distance
float d = this->distance;
this->distance = INFINITY;
return d;
};
bool DistanceSensor::ObjectNearby() {
if (distance < minRange || distance > maxRange)
return false;
bool isOn = distance <= triggerDistance;
return isOn;
}
void DistanceSensor::ProcessBytes(unsigned char *bytes) {
unsigned char ix = 0;
this->distance = LowLevelMessages::ReceiveFloat16(bytes, &ix);
// std::cout << "received distance " << this->distance << "\n";
}

43
DistanceSensor.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include "Sensor.h"
namespace Passer {
namespace RoboidControl {
/// @brief A Sensor which can measure the distance to the nearest object
class DistanceSensor : public Sensor {
public:
/// @brief Default constructor
DistanceSensor();
/// @brief Creates a DistanceSensor with the given trigger distance
/// @param triggerDistance The distance at which the sensors indicates that a
/// object is close by
DistanceSensor(float triggerDistance);
/// @brief Determine the distance to the nearest object
/// @return the measured distance in meters to the nearest object
virtual float GetDistance();
/// @brief The minimum range at which the sensor gives reliable measurements
float minRange = 0.01F;
/// @brief The maximum range at which the sensor gives reliable measurements
float maxRange = 10.0F;
/// @brief The distance at which ObjectNearby triggers
float triggerDistance = 1;
/// @brief Indicate that an object is nearby
/// @return True when an object is nearby
bool ObjectNearby();
virtual void ProcessBytes(unsigned char *bytes) override;
protected:
/// @brief Distance to the closest object
float distance = 0;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

21
Encoder.cpp Normal file
View File

@ -0,0 +1,21 @@
/*
#include "Encoder.h"
IncrementalEncoder::IncrementalEncoder(unsigned char pulsesPerRevolution,
unsigned char distancePerRotation) {
this->pulsesPerRevolution = pulsesPerRevolution;
this->distancePerRevolution = distancePerRotation;
}
int IncrementalEncoder::GetPulseCount() { return 0; }
float IncrementalEncoder::GetDistance() { return 0; }
float IncrementalEncoder::GetPulsesPerSecond(float currentTimeMs) { return 0; }
float IncrementalEncoder::GetRevolutionsPerSecond(float currentTimeMs) {
return 0;
}
float IncrementalEncoder::GetSpeed(float currentTimeMs) { return 0; }
*/

57
Encoder.h Normal file
View File

@ -0,0 +1,57 @@
#pragma once
#include "IncrementalEncoder.h"
namespace Passer {
namespace RoboidControl {
// Deprecated, use explicit IncrementalEncoder in the future
using Encoder = IncrementalEncoder;
/*
/// @brief An Encoder measures the rotations of an axle using a rotary
/// sensor Some encoders are able to detect direction, while others can not.
class IncrementalEncoder {
public:
/// @brief Creates a sensor which measures distance from pulses
/// @param pulsesPerRevolution The number of pulse edges which make a
/// full rotation
/// @param distancePerRevolution The distance a wheel travels per full
/// rotation
IncrementalEncoder(unsigned char pulsesPerRevolution = 1,
unsigned char distancePerRevolution = 1);
/// @brief Get the total number of pulses since the previous call
/// @return The number of pulses, is zero or greater
virtual int GetPulseCount();
/// @brief Get the pulse speed since the previous call
/// @param currentTimeMs The clock time in milliseconds
/// @return The average pulses per second in the last period.
virtual float GetPulsesPerSecond(float currentTimeMs);
/// @brief Get the distance traveled since the previous call
/// @return The distance in meters.
virtual float GetDistance();
/// @brief Get the rotation speed since the previous call
/// @param currentTimeMs The clock time in milliseconds
/// @return The speed in rotations per second
virtual float GetRevolutionsPerSecond(float currentTimeMs);
/// @brief Get the speed since the previous call
/// @param currentTimeMs The clock time in milliseconds
/// @return The speed in meters per second.
/// @note this value is dependent on the accurate setting of the
/// pulsesPerRevolution and distancePerRevolution parameters;
virtual float GetSpeed(float currentTimeMs);
/// @brief The numer of pulses corresponding to a full rotation of the axle
unsigned char pulsesPerRevolution = 1;
/// @brief The number of revolutions which makes the wheel move forward 1
/// meter
unsigned char distancePerRevolution = 1;
};
*/
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

19
IncrementalEncoder.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "Encoder.h"
IncrementalEncoder::IncrementalEncoder(unsigned char pulsesPerRevolution,
unsigned char distancePerRotation) {
this->pulsesPerRevolution = pulsesPerRevolution;
this->distancePerRevolution = distancePerRotation;
}
int IncrementalEncoder::GetPulseCount() { return 0; }
float IncrementalEncoder::GetDistance() { return 0; }
float IncrementalEncoder::GetPulsesPerSecond(float currentTimeMs) { return 0; }
float IncrementalEncoder::GetRevolutionsPerSecond(float currentTimeMs) {
return 0;
}
float IncrementalEncoder::GetSpeed(float currentTimeMs) { return 0; }

51
IncrementalEncoder.h Normal file
View File

@ -0,0 +1,51 @@
#pragma once
namespace Passer {
namespace RoboidControl {
/// @brief An Encoder measures the rotations of an axle using a rotary
/// sensor Some encoders are able to detect direction, while others can not.
class IncrementalEncoder {
public:
/// @brief Creates a sensor which measures distance from pulses
/// @param pulsesPerRevolution The number of pulse edges which make a
/// full rotation
/// @param distancePerRevolution The distance a wheel travels per full
/// rotation
IncrementalEncoder(unsigned char pulsesPerRevolution = 1,
unsigned char distancePerRevolution = 1);
/// @brief Get the total number of pulses since the previous call
/// @return The number of pulses, is zero or greater
virtual int GetPulseCount();
/// @brief Get the pulse speed since the previous call
/// @param currentTimeMs The clock time in milliseconds
/// @return The average pulses per second in the last period.
virtual float GetPulsesPerSecond(float currentTimeMs);
/// @brief Get the distance traveled since the previous call
/// @return The distance in meters.
virtual float GetDistance();
/// @brief Get the rotation speed since the previous call
/// @param currentTimeMs The clock time in milliseconds
/// @return The speed in rotations per second
virtual float GetRevolutionsPerSecond(float currentTimeMs);
/// @brief Get the speed since the previous call
/// @param currentTimeMs The clock time in milliseconds
/// @return The speed in meters per second.
/// @note this value is dependent on the accurate setting of the
/// pulsesPerRevolution and distancePerRevolution parameters;
virtual float GetSpeed(float currentTimeMs);
/// @brief The numer of pulses corresponding to a full rotation of the axle
unsigned char pulsesPerRevolution = 1;
/// @brief The number of revolutions which makes the wheel move forward 1
/// meter
unsigned char distancePerRevolution = 1;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

373
LICENSE Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

78
MessageFormat.md Normal file
View File

@ -0,0 +1,78 @@
Message Format
==============
## Data type
The datatype consists of 4-bit (nibble) 2 parts: the most significant nibble is the syntax, while the least significant nibble is the sematics.
| 7 . 6 | 5 . 4| 3. 2. 1. 0 |
|-|-|-|
| angular | linear | semantics |
When the Data type is 0x00, this indicates that a second byte will follow which defines further syntax options. Currently, this has not been defined yet, but can be used to define high-resolution angles using 2 bytes per dimension.
### Syntax
The syntax defines the format of the data sent and makes it possible to parse or skip parts of the message. Every value can consist of two parts: the angular and linear part, each represented by 2 bits.
| Angular part | |
|-|-|
| 00 (0x0) | No angle |
| 01 (0x4) | 1-byte, 1D angle |
| 10 (0x8) | 2-byte, 2D angle |
| 11 (0xC) | 3-byte, 3D angle |
| Linear part | |
|-|-|
| 00 (0x0) | No magnitude |
| 01 (0x1) | 1 byte magnitude |
| 10 (0x2) | 2 byte magnitude |
| 11 (0x3) | 4 byte magnitude |
Note that these values do not actually say how the angular and linear values are encoded. A 4-byte magnitude may be a 32-bit unsigned int or a single precision float for example. This depends on the semantics.
When the angular and linear parts are combined, the size of the message can be determined. A few examples:
| Data type | Size | Description |
|-|-|-|
| 0001 (0x1) | 1 byte | A single byte of linear data, like an intensity value |
| 0100 (0x4) | 1 byte | An angle, like an angle between 0 and 360 degrees |
| 0101 (0x5) | 2 bytes | An angle with a distance, like a polar coordinate |
| 1101 (0xD) | 4 bytes | For example a quaternion, where the x,y,z = angular and w = linear part |
| 0002 (0x2) | 2 bytes | A 16-bit value, like a single short int |
| 1011 (0xB) | 6 bytes | 2D angles and a 32-bit distance, for example a spherical coordinate |
### Semantics
The semantics defines how the data should be interpreted. The following are defined:
| Semantics | |
|-|-|
| 0b0001 (0x1) | Position |
| 0b0010 (0x2) | Linear velocity |
| 0b0011 (0x3) | Linear acceleration |
| 0b0101 (0x5) | Orientation or rotation |
| ob0110 (0x6) | Angular velocity |
| 0b0111 (0x7) | Angular acceleration |
| 0b1000 (0x8) | Direction |
## Currently implemented data types
| Data type | Message |
|-|-|
| 0x62 | Polar velocity with 2-byte distance |
## Typical data types
| Data type | Interpretation |
| 0x48 | A direction in 2D space, represented by an angle. |
| 0x88 | A direction in 3D space, represented by 2 angles. |
| 0x83 | A position in 3D space, using Spherical coordinates |
| 0xD4 | An orientation represented by a quaternion |
| 0xE5 | Angular verlocity, represented in Angle-axis format |
| 0xF5 | Angular verlocity, represented in Angle-axis format using a float for the magnitude |
Note that a 2D or 3D vector is not directly supported. In alignment to the coordinate sytem of Roboid controle, these need to be converted to Polar or Spherical coordinates before they can be sent.

17
Motor.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "Motor.h"
#include <time.h>
Motor::Motor() : Thing() {
this->type = (unsigned char)Type::UncontrolledMotor;
}
float Motor::GetActualSpeed() { return this->currentTargetSpeed; }
void Motor::SetTargetSpeed(float targetSpeed) {
this->currentTargetSpeed = targetSpeed;
}
float Motor::GetTargetSpeed() { return (this->currentTargetSpeed); }
void Motor::Update(unsigned long currentTimeMs) {}

46
Motor.h Normal file
View File

@ -0,0 +1,46 @@
#pragma once
#include "ControlCore/Thing.h"
#include <time.h>
namespace Passer {
using namespace Control;
namespace RoboidControl {
/// @brief A Motor is a Thing which can move parts of the Roboid
/// @note Currently only rotational motors are supported
class Motor : public Thing {
public:
/// @brief Default constructor for the Motor
Motor();
/// @brief Motor turning direction
enum class Direction { Clockwise = 1, CounterClockwise = -1 };
/// @brief The forward turning direction of the motor
Direction direction = Direction::Clockwise;
/// @brief Set the target motor speed
/// @param speed The speed between -1 (full backward), 0 (stop) and 1 (full
/// forward)
virtual void SetTargetSpeed(float speed);
/// @brief Get the current target speed of the motor
/// @return The speed between -1 (full backward), 0 (stop) and 1 (full
/// forward)
virtual float GetTargetSpeed();
/// @brief Get the current actual speed of the motor
/// @return The speed between -1 (full backward), 0 (stop) and 1 (full
/// forward)
virtual float GetActualSpeed();
virtual void Update(unsigned long currentTimeMs);
float currentTargetSpeed = 0;
protected:
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

330
NetworkSync.cpp Normal file
View File

@ -0,0 +1,330 @@
#include "NetworkSync.h"
// #define RC_DEBUG 1
#ifdef RC_DEBUG
#include <Arduino.h>
#if ESP32
#define SERIALPORT Serial
#else
#define SERIALPORT Serial
#endif
#endif
#include "ControlCore/Messages.h"
#include "LinearAlgebra/Angle.h"
#include "LinearAlgebra/AngleUsing.h"
#include "LinearAlgebra/Spherical.h"
#include <string.h>
NetworkSync::NetworkSync(Roboid *roboid) {
this->roboid = roboid;
this->networkId = 0;
}
// #include <Arduino.h>
void NetworkSync::ReceiveMessage(Roboid *roboid, unsigned char bytecount) {
// printf("Received msgId %d, length %d\n", buffer[0], bytecount);
ReceiveData(bytecount);
}
void NetworkSync::PublishClient() {
ClientMsg msg = ClientMsg(this->networkId);
msg.Publish(this);
#ifdef RC_DEBUG
SERIALPORT.printf("Publish Device\n");
#endif
}
void NetworkSync::ProcessNetworkIdMsg(Passer::Control::NetworkIdMsg msg) {
#ifdef RC_DEBUG
SERIALPORT.printf("Received network Id %d\n", msg.networkId);
#endif
this->networkId = msg.networkId;
SendThingInfo(roboid, true);
printf("completed\n");
}
void NetworkSync::ReceiveNetworkId() {
this->networkId = buffer[1];
#ifdef RC_DEBUG
SERIALPORT.printf("Received network Id %d\n", this->networkId);
#endif
SendThingInfo(roboid, true);
printf("completed\n");
}
void NetworkSync::ProcessInvestigateMsg(InvestigateMsg msg) {
#if RC_DEBUG
printf("Received InvestigateMsg [%d/%d]\n", msg.networkId, msg.thingId);
#endif
if (msg.networkId != this->networkId)
// We only respond to investigation requests for our own objects
return;
Thing *thing = (Thing *)Thing::Get(0, msg.thingId);
if (thing != nullptr)
this->SendThingInfo(thing, true);
}
void NetworkSync::ProcessThingMsg(ThingMsg msg) {
if (msg.networkId == roboid->networkSync->networkId)
// Do not process messages for you own things
return;
printf("Received Thing message [%d/%d]\n", msg.networkId, msg.thingId);
InterestingThing *thing =
roboid->perception->FindTrackedObject(msg.networkId, msg.thingId);
if (thing != nullptr) {
thing->type = msg.thingType;
}
printf("complete\n");
}
void NetworkSync::ProcessPoseMsg(PoseMsg msg) {}
void NetworkSync::PublishState(Roboid *roboid) {
SendPose(roboid);
PublishPerception(roboid);
}
void NetworkSync::SendThingInfo(Thing *thing, bool recurse) {
if (thing == nullptr)
return;
SendThing(thing);
SendName(thing);
SendModel(thing);
SendCustom(thing);
SendPose(thing, true, false);
if (recurse) {
for (unsigned char childIx = 0; childIx < thing->childCount; childIx++) {
Thing *child = (Thing *)thing->GetChildByIndex(childIx);
if (child != nullptr)
SendThingInfo(child, true);
}
}
}
void NetworkSync::SendThing(Thing *thing) {
if (thing == nullptr)
return;
Thing *parent = (Thing *)thing->GetParent();
ThingMsg msg = ThingMsg(this->networkId, thing->id, thing->type,
parent == nullptr ? 0 : parent->id);
msg.SendTo(this);
#ifdef RC_DEBUG
printf("Sent Thing [%d/%d] %d\n", networkId, thing->id, (byte)thing->type);
#endif
}
void NetworkSync::SendName(Thing *thing) {
if (thing->name == nullptr)
return;
unsigned char len = strlen(thing->name);
if (len > 255)
return;
NameMsg msg = NameMsg(this->networkId, thing->id, thing->name, len);
msg.SendTo(this);
#ifdef RC_DEBUG
SERIALPORT.printf("Sent Name [%d/%d] %s\n", networkId, buffer[1],
thing->name);
#endif
}
void NetworkSync::SendModel(Thing *thing) {
if (thing->modelUrl == nullptr)
return;
unsigned char len = strlen(thing->modelUrl);
if (len > 255)
return;
ModelUrlMsg msg = ModelUrlMsg(this->networkId, thing->id, len,
thing->modelUrl, thing->modelScale);
msg.SendTo(this);
}
void NetworkSync::SendCustom(Thing *thing) {
CustomMsg msg = CustomMsg(this->networkId, thing);
msg.SendTo(this);
}
void NetworkSync::SendDestroy(Thing *thing) {
DestroyMsg msg = DestroyMsg(this->networkId, thing);
msg.SendTo(this);
#if RC_DEBUG
printf("Sent DestroyMsg [%d/%d]\n", thing->networkId, thing->id);
#endif
}
#include <iostream>
void NetworkSync::ProcessCustomMsg(CustomMsg msg) {
// we assume networkId == 0 as custom messages are intended for my things
Thing *thing = (Thing *)roboid->GetChild(msg.thingId, true);
if (thing != nullptr)
thing->ProcessBytes(msg.data);
}
void NetworkSync::SendPose(Thing *thing, bool force, bool recurse) {
if (this->networkId == 0) // We're not connected to a site yet
return;
thing->positionUpdated |= thing->GetLinearVelocity().distance > 0;
thing->orientationUpdated |= thing->GetAngularVelocity().distance > 0;
if (force || thing->positionUpdated || thing->orientationUpdated) {
unsigned char poseType = 0;
if (force || thing->positionUpdated)
poseType |= PoseMsg::Pose_Position;
if (force || thing->orientationUpdated)
poseType |= PoseMsg::Pose_Orientation;
if (thing->linearVelocity.distance > 0)
poseType |= PoseMsg::Pose_LinearVelocity;
if (thing->angularVelocity.distance > 0)
poseType |= PoseMsg::Pose_AngularVelocity;
PoseMsg msg = PoseMsg(this->networkId, thing->id, poseType,
thing->GetPosition(), thing->GetOrientation(),
thing->linearVelocity, thing->angularVelocity);
msg.SendTo(this);
thing->positionUpdated = false;
thing->orientationUpdated = false;
#if RC_DEBUG
if (thing->id != 0) {
Vector3 v = thing->position.ToVector3();
printf("Sent PoseMsg Thing [%d/%d] %f(%f)-(%f %f %f) %f\n",
this->networkId, thing->id, thing->position.distance,
thing->position.direction.horizontal.InDegrees(), v.Right(),
v.Up(), v.Forward(),
thing->orientation.swing.horizontal.InDegrees());
}
#endif
}
if (recurse) {
for (unsigned char childIx = 0; childIx < thing->childCount; childIx++) {
Thing *child = (Thing *)thing->GetChildByIndex(childIx);
if (child != nullptr)
SendPose(child, force, recurse);
}
}
}
void NetworkSync::PublishPerception(Roboid *roboid) {
// Perception *perception = roboid->perception;
// if (perception == nullptr)
// return;
// for (unsigned int sensorIx = 0; sensorIx < perception->sensorCount;
// sensorIx++) {
// Sensor *sensor = perception->sensors[sensorIx];
// if (sensor == nullptr)
// continue;
// }
PublishTrackedObjects(roboid, roboid->perception->GetTrackedObjects());
}
void NetworkSync::PublishTrackedObjects(Roboid *roboid,
InterestingThing **objects) {
if (networkId == 0) // We're not connected to a site yet
return;
int n = 0;
for (unsigned char objIx = 0; objIx < Perception::maxObjectCount; objIx++) {
InterestingThing *obj = objects[objIx];
if (obj == nullptr)
continue;
if (obj->confidence > 0)
PublishTrackedObject(roboid, obj);
n++;
}
}
void NetworkSync::PublishTrackedObject(Roboid *roboid,
InterestingThing *thing) {
if (thing == nullptr || thing->updated == false || thing->networkId != 0x00) {
return;
}
SwingTwist16 inv_originOrientation;
Spherical16 originPosition;
if (roboid->worldOrigin == nullptr) {
inv_originOrientation = SwingTwist16::identity;
originPosition = Spherical16::zero;
} else {
inv_originOrientation =
SwingTwist16::Inverse(roboid->worldOrigin->GetOrientation());
originPosition = roboid->worldOrigin->GetPosition();
}
// SwingTwist16 inv_originOrientation =
// SwingTwist16::Inverse(roboid->worldOrigin->orientation);
// Spherical16 originPosition = roboid->worldOrigin->position;
SwingTwist16 worldOrientation =
inv_originOrientation * thing->GetOrientation();
Spherical16 worldPosition =
inv_originOrientation * (thing->GetPosition() - originPosition);
PoseMsg msg = PoseMsg(this->networkId, thing->id,
PoseMsg::Pose_Position | PoseMsg::Pose_Orientation,
worldPosition, worldOrientation);
SendBuffer(msg.Serialize(this->buffer));
#if RC_DEBUG
printf("Sent Thing PoseMsg [%d/%d] %d\n", networkId, buffer[1], thing->type);
#endif
thing->updated = false;
}
void NetworkSync::SendText(const char *s) {
unsigned char length;
for (length = 0; length < 253; length++) {
if (s[length] == '\0')
break;
}
if (length >= 253)
return;
unsigned char ix = 0;
buffer[ix++] = 0xB0;
buffer[ix++] = length;
for (int urlIx = 0; urlIx < length; urlIx++)
buffer[ix++] = s[urlIx];
SendBuffer(ix);
#ifdef RC_DEBUG
printf("Sent Text %s\n", s);
#endif
}
#if ESP32
#include <Arduino.h>
#endif
void NetworkSync::SendInt(const int x) {
#if ESP32
String s = String(x);
char length = s.length();
unsigned char ix = 0;
buffer[ix++] = 0xB0;
buffer[ix++] = length;
for (int urlIx = 0; urlIx < length; urlIx++)
buffer[ix++] = s[urlIx];
SendBuffer(ix);
#endif
}

68
NetworkSync.h Normal file
View File

@ -0,0 +1,68 @@
#pragma once
#include "ControlCore/Participant.h"
#include "Perception.h"
#include "Roboid.h"
#include "Types.h"
namespace Passer {
namespace RoboidControl {
/// @brief Interface for synchronizaing state between clients across a network
class NetworkSync : public Participant {
public:
NetworkSync() {};
NetworkSync(Roboid *roboid);
unsigned char networkId = 0;
/// @brief Retreive and send the roboid state
/// @param roboid The roboid for which the state is updated
virtual void NetworkUpdate(Roboid *roboid) = 0;
void SendThingInfo(Thing *thing, bool recurse = false);
void SendThing(Thing *thing);
void SendName(Thing *roboid);
void SendModel(Thing *thing);
void SendCustom(Thing *thing);
/// @brief Inform that the given object is no longer being tracked
/// @param obj
void SendDestroy(Thing *thing);
typedef void (*Buffer)(UInt8 *buffer, UInt16 bufferSize);
void ReceiveMessage(Roboid *roboid, unsigned char bytecount);
void PublishState(Roboid *roboid);
void PublishPerception(Roboid *roboid);
void PublishTrackedObjects(Roboid *roboid, InterestingThing **objects);
virtual void SendPosition(Spherical16 worldPosition) {};
virtual void SendPose(Spherical16 worldPosition,
SwingTwist16 worldOrientation) {};
void SendPose(Thing *thing, bool force = 0, bool recurse = true);
virtual void SendText(const char *s);
void SendInt(const int x);
virtual void Download(const char *url) {};
protected:
Roboid *roboid;
virtual void ProcessNetworkIdMsg(Passer::Control::NetworkIdMsg msg) override;
virtual void ProcessInvestigateMsg(InvestigateMsg msg) override;
virtual void ProcessThingMsg(ThingMsg msg) override;
virtual void ProcessPoseMsg(PoseMsg msg) override;
virtual void ProcessCustomMsg(CustomMsg msg) override;
void ReceiveNetworkId();
void ReceiveCustom(unsigned char packetSize);
void PublishTrackedObject(Roboid *roboid, InterestingThing *object);
void PublishClient();
};
} // namespace RoboidControl
} // namespace Passer

576
Perception.cpp Normal file
View File

@ -0,0 +1,576 @@
#include "Perception.h"
#include "ControlCore/LinearAlgebra/Angle.h"
#include "ControlCore/Thing.h"
#include "DistanceSensor.h"
#include "NetworkSync.h"
#include "Switch.h"
#include <math.h>
// #define RC_DEBUG
#ifdef RC_DEBUG
#include <Arduino.h>
#endif
unsigned char Perception::maxObjectCount = 7; // 7 is typically the maximum
// number of object which can
// be tracked by a human
Perception::Perception() {
this->sensorCount = 0;
this->sensors = new Sensor *[0];
this->trackedObjects = new InterestingThing *[maxObjectCount];
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++)
this->trackedObjects[objIx] = nullptr;
}
Perception::Perception(Sensor **sensors, unsigned int sensorCount)
: Perception() {
this->sensorCount = sensorCount;
this->sensors = new Sensor *[this->sensorCount];
for (unsigned char sensorIx = 0; sensorIx < this->sensorCount; sensorIx++)
this->sensors[sensorIx] = sensors[sensorIx];
this->trackedObjects = new InterestingThing *[maxObjectCount];
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++)
this->trackedObjects[objIx] = nullptr;
}
unsigned int Perception::GetSensorCount() { return this->sensorCount; }
Sensor *Perception::GetSensor(unsigned int sensorId) {
if (sensorId >= this->sensorCount)
return nullptr;
Sensor *sensor = this->sensors[sensorId];
return sensor;
}
unsigned int Perception::AddSensor(Sensor *newSensor) {
unsigned int newSensorCount = this->sensorCount + 1;
Sensor **newSensors = new Sensor *[newSensorCount];
for (unsigned char sensorIx = 0; sensorIx < this->sensorCount; sensorIx++)
newSensors[sensorIx] = sensors[sensorIx];
unsigned int sensorId = this->sensorCount;
newSensors[sensorId] = newSensor;
Sensor **oldSensors = this->sensors;
this->sensors = newSensors;
this->sensorCount = newSensorCount;
delete[] oldSensors;
return sensorId;
}
Sensor *Perception::FindSensorOfType(unsigned int sensorType) {
for (unsigned int sensorIx = 0; sensorIx < this->sensorCount; sensorIx++) {
Sensor *sensor = this->sensors[sensorIx];
if (sensor->type == sensorType)
return sensor;
}
return nullptr;
}
float GetPlaneDistance(InterestingThing *plane, float horizontalAngle,
float range) {
float distance = plane->GetPosition().distance;
float deltaAngle =
AngleSingle::Normalize(
AngleSingle::Degrees(
plane->GetPosition().direction.horizontal.InDegrees() -
horizontalAngle))
.InDegrees();
if (fabsf(deltaAngle) < fabsf(range)) {
// distance = distance
// printf(" plane distance = %f (%f-%f)+%f=%f", distance,
// (float)plane->position.horizontalAngle, horizontalAngle, range,
// deltaAngle);
} else if (deltaAngle < -range) {
float angle = deltaAngle + range;
// printf(" plane distance < %f (%f-%f)+%f=%f %f", distance,
// (float)plane->position.horizontalAngle, horizontalAngle, range,
// angle, cosf(angle * Angle::Deg2Rad));
if (angle > -90)
distance = distance / cosf(angle * Passer::LinearAlgebra::Deg2Rad);
else
distance = 9999; // infinity?
} else if (deltaAngle > range) {
float angle = deltaAngle - range;
// printf(" plane distance > %f (%f-%f)-%f=%f %f", distance,
// (float)plane->position.horizontalAngle, horizontalAngle, range,
// angle, cosf(angle * Angle::Deg2Rad));
if (angle < 90)
distance = distance / cosf(angle * Passer::LinearAlgebra::Deg2Rad);
else
distance = 9999; // infinity?
}
// printf(" distance = %f\n", distance);
return distance;
}
float Perception::GetDistance(float horizontalDirection, float range) {
float minDistance = INFINITY;
if (range < 0)
range = -range;
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *obj = trackedObjects[objIx];
if (obj == nullptr)
continue;
if (obj->type == 0x080) { // plane
float planeDistance = GetPlaneDistance(obj, horizontalDirection, range);
minDistance = fminf(minDistance, planeDistance);
} else if (obj->GetPosition().direction.horizontal.InDegrees() >
horizontalDirection - range &&
obj->GetPosition().direction.horizontal.InDegrees() <
horizontalDirection + range) {
minDistance = fminf(minDistance, obj->GetPosition().distance);
}
}
return minDistance;
}
float Perception::GetDistanceOfType(unsigned char thingType,
float horizontalAngle, float range) {
float minDistance = INFINITY;
if (range < 0)
range = -range;
for (unsigned char thingIx = 0; thingIx < maxObjectCount; thingIx++) {
InterestingThing *thing = trackedObjects[thingIx];
if (thing == nullptr)
continue;
if (thing->type != thingType)
continue;
if (thing->type == 0x080) { // plane
float planeDistance = GetPlaneDistance(thing, horizontalAngle, range);
minDistance = fminf(minDistance, planeDistance);
} else if (thing->GetPosition().direction.horizontal.InDegrees() >
horizontalAngle - range &&
thing->GetPosition().direction.horizontal.InDegrees() <
horizontalAngle + range) {
minDistance = fminf(minDistance, thing->GetPosition().distance);
}
}
return minDistance;
}
float Perception::GetDistance(float horizontalDirection,
float verticalDirection, float range) {
float minDistance = INFINITY;
if (range < 0)
range = -range;
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *obj = trackedObjects[objIx];
if (obj == nullptr)
continue;
if (obj->GetPosition().direction.horizontal.InDegrees() >
horizontalDirection - range &&
obj->GetPosition().direction.horizontal.InDegrees() <
horizontalDirection + range) {
minDistance = fminf(minDistance, obj->GetPosition().distance);
}
}
return minDistance;
}
bool Perception::ObjectNearby(float direction, float range) {
if (range < 0)
range = -range;
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *obj = trackedObjects[objIx];
if (obj == nullptr)
continue;
if (obj->GetPosition().direction.horizontal.InDegrees() >
direction - range &&
obj->GetPosition().direction.horizontal.InDegrees() <
direction + range) {
if (obj->GetPosition().distance <= nearbyDistance)
return true;
}
}
return false;
}
InterestingThing *
Perception::AddTrackedObject(Sensor *sensor, Spherical16 position,
SwingTwist16 orientation, unsigned char thingType,
unsigned char thingId, unsigned char networkId) {
InterestingThing *thing = new InterestingThing(sensor, position, orientation);
if (thingId != 0x00)
thing->id = thingId;
thing->type = thingType;
unsigned char farthestObjIx = 0;
unsigned char availableSlotIx = 0;
for (unsigned char thingIx = 0; thingIx < maxObjectCount; thingIx++) {
if (this->trackedObjects[thingIx] == nullptr) {
availableSlotIx = thingIx;
}
// Do we see the same object?
else {
if (thing->IsTheSameAs(this->trackedObjects[thingIx])) {
this->trackedObjects[thingIx]->Refresh(
thing->GetPosition(), thing->GetOrientation()); //.ToQuaternion());
delete thing;
return this->trackedObjects[thingIx];
}
// Is this the fartest object we see?
else if (this->trackedObjects[farthestObjIx] == nullptr ||
(this->trackedObjects[thingIx]->GetPosition().distance >
this->trackedObjects[farthestObjIx]->GetPosition().distance)) {
farthestObjIx = thingIx;
}
}
}
// Check if an perception slot is available (we currently see less than the
// max number of objects)
if (availableSlotIx < maxObjectCount) {
// a slot is available
this->trackedObjects[availableSlotIx] = thing;
thing->networkId = networkId;
if (thingId == 0x00)
thing->id = lastObjectId++; // availableSlotIx + 1;
return thing;
}
// If this object is closer than the farthest object, then replace it
else if (thing->GetPosition().distance <
this->trackedObjects[farthestObjIx]->GetPosition().distance) {
delete this->trackedObjects[farthestObjIx];
this->trackedObjects[farthestObjIx] = thing;
thing->networkId = networkId;
if (thingId == 0x00)
thing->id = lastObjectId++; // availableSlotIx + 1;
return thing;
} else {
// No available slot, delete trackedobject
delete thing;
return nullptr;
}
}
InterestingThing *Perception::AddTrackedObject(Sensor *sensor,
unsigned char networkId,
unsigned char thingId,
Spherical16 position,
SwingTwist16 orientation) {
InterestingThing *thing = FindTrackedObject(networkId, thingId);
if (thing == nullptr) {
thing = AddTrackedObject(sensor, position, orientation, 0xFF, thingId,
networkId);
// Don't we set this above already?
thing->networkId = networkId;
thing->id = thingId;
thing->type = 0xFF; // unknown
}
return thing;
}
InterestingThing *Perception::AddTrackedObject(Sensor *sensor,
Thing *orgThing) {
InterestingThing *thing = new InterestingThing(
sensor, orgThing->GetPosition(), orgThing->GetOrientation());
thing->id = orgThing->id;
thing->networkId = 0;
thing->type = orgThing->type;
thing->name = orgThing->name;
thing->modelUrl = orgThing->modelUrl;
thing->modelScale = orgThing->modelScale;
unsigned char farthestObjIx = 0;
unsigned char availableSlotIx = 0;
for (unsigned char thingIx = 0; thingIx < maxObjectCount; thingIx++) {
if (this->trackedObjects[thingIx] == nullptr) {
availableSlotIx = thingIx;
}
// Do we see the same object?
else {
if (thing->IsTheSameAs(this->trackedObjects[thingIx])) {
this->trackedObjects[thingIx]->Refresh(
thing->GetPosition(), thing->GetOrientation()); //.ToQuaternion());
delete thing;
return this->trackedObjects[thingIx];
}
// Is this the fartest object we see?
else if (this->trackedObjects[farthestObjIx] == nullptr ||
(this->trackedObjects[thingIx]->GetPosition().distance >
this->trackedObjects[farthestObjIx]->GetPosition().distance)) {
farthestObjIx = thingIx;
}
}
}
// Check if an perception slot is available (we currently see less than the
// max number of objects)
if (availableSlotIx < maxObjectCount) {
// a slot is available
this->trackedObjects[availableSlotIx] = thing;
if (thing->id == 0x00)
thing->id = lastObjectId++; // availableSlotIx + 1;
return thing;
}
// If this object is closer than the farthest object, then replace it
else if (thing->GetPosition().distance <
this->trackedObjects[farthestObjIx]->GetPosition().distance) {
delete this->trackedObjects[farthestObjIx];
this->trackedObjects[farthestObjIx] = thing;
if (thing->id == 0x00)
thing->id = lastObjectId++; // availableSlotIx + 1;
return thing;
} else {
return nullptr;
}
}
bool Perception::IsInteresting(float distance) {
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *thing = this->trackedObjects[objIx];
if (thing == nullptr)
return true;
if (thing->GetPosition().distance > distance)
return true;
}
return false;
}
InterestingThing *Perception::FindTrackedObject(char objectId) {
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *thing = this->trackedObjects[objIx];
if (thing == nullptr)
continue;
if (thing->id == objectId) {
return thing;
}
}
return nullptr;
}
InterestingThing *Perception::FindTrackedObject(unsigned char networkId,
unsigned char objectId) {
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *thing = this->trackedObjects[objIx];
if (thing == nullptr)
continue;
if (thing->networkId == networkId && thing->id == objectId) {
return thing;
}
}
return nullptr;
}
unsigned char Perception::TrackedObjectCount() {
unsigned char objectCount = 0;
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
if (this->trackedObjects[objIx] != nullptr)
objectCount++;
}
return objectCount;
}
InterestingThing **Perception::GetTrackedObjects() {
return this->trackedObjects;
}
unsigned char Perception::ThingsOfType(unsigned char thingType,
InterestingThing *buffer[],
unsigned char bufferSize) {
unsigned char thingCount = 0;
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *thing = this->trackedObjects[objIx];
if (thing == nullptr)
continue;
// printf("[%d/%d]%d ", thing->networkId, thing->id, thing->type);
if (thing->type == thingType) {
buffer[thingCount] = thing;
thingCount++;
if (thingCount >= bufferSize) {
// printf("\n");
return bufferSize;
}
}
}
// printf("\n");
return thingCount;
}
InterestingThing *Perception::ThingOfType(unsigned char thingType) {
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *thing = this->trackedObjects[objIx];
if (thing == nullptr)
continue;
if (thing->type == thingType)
return thing;
}
return nullptr;
}
InterestingThing *Perception::GetMostInterestingThing() {
if (this->trackedObjects == nullptr)
return nullptr;
InterestingThing *closestObject = nullptr;
float closestDistance = INFINITY;
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *obj = this->trackedObjects[objIx];
if (obj != nullptr) {
if (obj->GetPosition().distance < closestDistance) {
closestObject = obj;
closestDistance = obj->GetPosition().distance;
}
}
}
return closestObject;
}
void Perception::Update(unsigned long currentTimeMs) {
float deltaTime = (float)(currentTimeMs - lastUpdateTimeMs) / 1000.0f;
if (deltaTime <= 0)
return;
lastUpdateTimeMs = currentTimeMs;
// Update sensing
for (unsigned int sensorIx = 0; sensorIx < this->sensorCount; sensorIx++) {
Sensor *sensor = sensors[sensorIx];
if (sensor == nullptr)
continue;
if (sensor->type == (unsigned char)Thing::Type::DistanceSensor) {
DistanceSensor *distanceSensor = (DistanceSensor *)sensor;
float distance = distanceSensor->GetDistance();
if (distance >= 0) {
// Angle16 angle = sensor->position.horizontal;
// Polar position = Polar(angle, distance);
// Polar position = Polar(distance, angle.ToFloat());
// AddTrackedObject(distanceSensor, position);
Spherical16 position =
Spherical16(distance, sensor->GetPosition().direction);
AddTrackedObject(distanceSensor, position);
}
} else if (sensor->type == (unsigned char)Thing::Type::Switch) {
Switch *switchSensor = (Switch *)sensor;
if (switchSensor->IsOn()) {
// Polar position = Polar(sensor->position.angle, nearbyDistance);
AngleSingle horizontal = AngleSingle::Degrees(horizontal.InDegrees());
PolarSingle position = PolarSingle(nearbyDistance, horizontal);
// AddTrackedObject(switchSensor, position);
}
} else {
sensor->Update(currentTimeMs);
}
}
for (unsigned char objIx = 0; objIx < maxObjectCount; objIx++) {
InterestingThing *thing = trackedObjects[objIx];
if (thing == nullptr)
continue;
if (thing->DegradeConfidence(deltaTime) == false) {
// delete obj
if (roboid != nullptr && roboid->networkSync != nullptr) {
// roboid->networkSync->SendDestroy((Passer::Control::Thing *)thing);
}
this->trackedObjects[objIx] = nullptr;
delete thing;
}
}
}
void Perception::UpdatePose(Polar16 translation) {
for (unsigned char thingIx = 0; thingIx < maxObjectCount; thingIx++) {
InterestingThing *thing = trackedObjects[thingIx];
if (thing == nullptr)
continue;
// We only support translations in the horizontal plane at this moment...
// This needs Spherical operator- to be implemented to work in 3d space
if (thing->type == 0x80) { // plane
// printf("[1/%d] %f (%f %f) ", thing->id, thing->position.distance,
// (float)thing->position.horizontalAngle,
// (float)thing->position.verticalAngle);
// Update the closest point to the plane
float angle =
(float)thing->GetPosition().direction.horizontal.InDegrees() +
translation.angle.InDegrees();
angle = fabsf(angle);
float deltaDistance =
translation.distance * cosf(angle * Passer::LinearAlgebra::Deg2Rad);
// printf(" | translate %f %f %f | ", (float)translation.distance,
// (float)angle, deltaDistance);
Spherical16 position = thing->GetPosition();
position.distance -= deltaDistance;
thing->SetPosition(position); //.distance -= deltaDistance;
// printf("-> %f (%f %f)\n", thing->position.distance,
// (float)thing->position.horizontalAngle,
// (float)thing->position.verticalAngle);
} else {
// Polar horizontalPosition = Polar(thing->position);
// // obj->position.ProjectOnHorizontalPlane();
// Spherical16 newPosition = Spherical16(horizontalPosition -
// translation);
Spherical16 translationS = Spherical16(
translation.distance, Angle16::Degrees(translation.angle.InDegrees()),
Angle16::Degrees(0));
Spherical16 newPosition = thing->GetPosition() + translationS;
Vector3 oldPos = thing->GetPosition().ToVector3();
Vector3 newPos = newPosition.ToVector3();
// printf(" update percepted position (%f 0 %f) -> (%f 0 %f)\n",
// oldPos.Right(), oldPos.Forward(), newPos.Right(),
// newPos.Forward());
thing->SetPosition(newPosition);
}
}
}
void Perception::UpdatePose(SwingTwist16 rotation) {
// only rotation around vertical axis is supported for now
// float rotationAngle;
// Vector3 rotationAxis;
// rotation.ToAngleAxis(&rotationAngle, &rotationAxis);
// Make sure rotation axis is positive
// if (rotationAxis.Up() < 0)
// rotationAngle = -rotationAngle;
Angle16 rotationAngle = rotation.swing.horizontal;
for (unsigned char thingIx = 0; thingIx < maxObjectCount; thingIx++) {
InterestingThing *thing = trackedObjects[thingIx];
if (thing == nullptr)
continue;
// printf("[1/%d] %f (%f %f) ", thing->id, thing->position.distance,
// (float)thing->position.horizontalAngle,
// (float)thing->position.verticalAngle);
// printf("| rotate %f | ", rotationAngle);
Spherical16 newPosition = thing->GetPosition();
newPosition.direction.horizontal - rotationAngle;
thing->SetPosition(newPosition);
// thing->position.direction.horizontal =
// thing->position.direction.horizontal - rotationAngle;
// printf("-> %f (%f %f) \n", thing->position.distance,
// (float)thing->position.horizontalAngle,
// (float)thing->position.verticalAngle);
}
}

177
Perception.h Normal file
View File

@ -0,0 +1,177 @@
#pragma once
#include "ControlCore/LinearAlgebra/Polar.h"
#include "ControlCore/LinearAlgebra/Quaternion.h"
#include "ControlCore/LinearAlgebra/Spherical.h"
#include "Sensor.h"
#include "TrackedObject.h"
// #include <vector.h>
namespace Passer {
namespace RoboidControl {
class Roboid;
/// @brief Module to which keeps track of objects around the roboid
class Perception {
public:
/// @brief Default Constructor
Perception();
/// @brief Create a perception setup with the given Sensors
/// @param sensors The Placement of Sensors on the Roboid
/// @param sensorCount The number of sensors in the placement array
Perception(Sensor **sensors, unsigned int sensorCount);
/// @brief The roboid of this perception system
Roboid *roboid = nullptr;
unsigned int AddSensor(Sensor *sensor);
/// @brief Get the number of Sensors
/// @return The number of sensors, zero when no sensors are present
unsigned int GetSensorCount();
Sensor *GetSensor(unsigned int sensorId);
/// @brief Find the first sensor of the given type
/// @param sensorType The type of sensor as is defined in the Thing class (for
/// example Thing::SensorType)
/// @return The first sensor found or a nullptr which no sensor has been found
/// of the given type
Sensor *FindSensorOfType(unsigned int sensorType);
/// @brief Gets the distance to the closest object
/// @param direction The direction to look for objects
/// @param range The range in which objects should be looked for
/// @return The distance to the closest object in meters
float GetDistance(float direction, float range = 10.0F);
float GetDistanceOfType(unsigned char thingType, float horizontalAngle,
float range = 10.0F);
/// @brief Gets the distance to the closest object
/// @param horizontalDirection The direction in the horizontal plane to look
/// for objects
/// @param verticalDirection The direction in the vertical plane to look for
/// objects
/// @param range The range in which objects should be looked for
/// @return The distance to the closest object in meters
/// @details The directions can be thought of as the polar angle (vertical)
/// and azimuthal angle (horizontal) in the spherical coordinate system.
float GetDistance(float horizontalDirection, float verticalDirection,
float range = 10.0F);
/// @brief Checks if an object is nearby
/// @param direction The direction to look for objects
/// @param range The range in which objects should be looked for
/// @return True when an object is close, False otherwise
/// @details Wether an object is closeby depends on the sensor. This can be a
/// sensor like a Switch or a DistanceSensor. The latter uses the
/// DistanceSensor::triggerDistance to check if an object is nearby.
bool ObjectNearby(float direction, float range = 10.0F);
/// @brief Checks if an object is nearby
/// @param horizontalDirection The direction in the horizontal plane to look
/// for objects
/// @param verticalDirection The direction in the vertical plane to look for
/// objects
/// @param range The range in which objects should be looked for
/// @return True when an object is close, False otherwise
/// @details Wether an object is closeby depends on the sensor. This can be a
/// sensor like a Switch or a DistanceSensor. The latter uses the
/// DistanceSensor::triggerDistance to check if an object is nearby.
///
/// The directions can be thought of as the polar angle (vertical) and
/// azimuthal angle (horizontal) in the spherical coordinate system.
// bool ObjectNearby(float horizontalDirection, float verticalDirection,
// float range = 10.0F);
/// @brief Add or update an object detected by the given sensor
/// @param sensor The sensor which has detected the object
/// @param position The position of the sensor in polar coordinates local to
/// the roboid
// void AddTrackedObject(Sensor* sensor,
// Spherical16 position,
// unsigned char objectType = 0x00,
// unsigned char networkId = 0x00);
InterestingThing *
AddTrackedObject(Sensor *sensor, Spherical16 position,
SwingTwist16 orientation = SwingTwist16::identity,
unsigned char objectType = 0xFF,
unsigned char objectId = 0x00,
unsigned char networkId = 0x00);
InterestingThing *
AddTrackedObject(Sensor *sensor, unsigned char networkId,
unsigned char objectId, Spherical16 position,
SwingTwist16 orientation = SwingTwist16::identity);
InterestingThing *AddTrackedObject(Sensor *sensor, Thing *thing);
bool IsInteresting(float distance);
InterestingThing *FindTrackedObject(char objectId);
InterestingThing *FindTrackedObject(unsigned char networkId,
unsigned char objectId);
/// @brief Retrieve the number of objects currently being tracked by the
/// roboid
/// @return The object of objects, which is always lower than
/// maxObjectCount
unsigned char TrackedObjectCount();
/// @brief Retreive the objects currently tracked by the roboid
/// @return An array of current objects
/// @details The returned array this should never be a nullptr, but
/// each array entry may be a nullptr when less than maxObjectCount objects is
/// currently being tracked.
InterestingThing **GetTrackedObjects();
unsigned char ThingsOfType(unsigned char objectType,
InterestingThing *buffer[],
unsigned char bufferSize);
InterestingThing *ThingOfType(unsigned char objectType);
InterestingThing *GetMostInterestingThing();
// mainly used for confidence update
/// @brief Update the state of the perception.
/// @param currentTimeMs The current time in milliseconds
/// @details This will update the perceptoin of object. It will retrieve the
/// latest state for each sensor and update the confidence of the tracked
/// objects.
void Update(unsigned long currentTimeMs);
/// @brief Update the position/orientation of the preceived objects from the
/// given roboid translation
/// @param translation The translation of the roboid in world space in polar
/// coordinates
/// @details This function will be called through Roboid::SetPosition. It
/// is advised to use that function to update the roboid position instead of
/// this function.
void UpdatePose(Polar16 translation);
/// @brief Update the orientation of the perceived objecst from the given
/// roboid rotation
/// @param rotation The rotation of the roboid in world space
void UpdatePose(SwingTwist16 rotation);
/// @brief Objects with a distance closed that this value will be considered
/// nearby.
/// @details This value is used by the ObjectNearby function to select the
/// objects
float nearbyDistance = 0.02F;
public:
/// @brief The Sensors used for Perception
Sensor **sensors = nullptr;
/// @brief The number of Sensors used for Perception
unsigned int sensorCount = 0;
unsigned long lastUpdateTimeMs = 0;
unsigned char lastObjectId = 1;
static unsigned char maxObjectCount; // = 7; // 7 is typically the maximum
// number of object which can
// be tracked by a human
InterestingThing **trackedObjects;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

48
Propulsion.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "Propulsion.h"
#include "Roboid.h"
#include "LinearAlgebra/FloatSingle.h"
Propulsion::Propulsion() {
this->motors = nullptr;
this->motorCount = 0;
}
unsigned int Propulsion::GetMotorCount() { return this->motorCount; }
Motor *Propulsion::GetMotor(unsigned int motorId) {
if (motorId >= this->motorCount)
return nullptr;
Motor *motor = this->motors[motorId];
return motor;
}
void Propulsion::Update(unsigned long currentTimeMs) {
for (unsigned char motorIx = 0; motorIx < this->motorCount; motorIx++) {
Motor *motor = this->motors[motorIx];
if (motor == nullptr)
continue;
motor->Update(currentTimeMs);
}
}
void Propulsion::SetTwistSpeed(float forward, float yaw) {}
void Propulsion::SetTwistSpeed(Vector2 linear, float yaw) {}
void Propulsion::SetTwistSpeed(Vector3 linear, float yaw, float pitch,
float roll) {}
void Propulsion::SetVelocity(Spherical16 velocity) {
this->linearVelocity = velocity;
}
void Propulsion::SetAngularVelocity(Spherical16 velocity) {
this->angularVelocity = velocity;
}
Spherical16 Propulsion::GetVelocity() { return this->linearVelocity; }
Spherical16 Propulsion::GetAngularVelocity() { return this->angularVelocity; }

90
Propulsion.h Normal file
View File

@ -0,0 +1,90 @@
#pragma once
#include "ControlCore/LinearAlgebra/Polar.h"
#include "ControlCore/LinearAlgebra/Quaternion.h"
#include "ControlCore/LinearAlgebra/Vector2.h"
#include "Motor.h"
namespace Passer {
namespace RoboidControl {
class Roboid;
/// @brief The Propulsion module for a Roboid is used to move the Roboid in
/// space
/// @details Usually, a specific implementation of the propulsion module is used
/// for a robot. This base class does not implement the functions to move the
/// Roboid around.
class Propulsion {
public:
/// @brief Default Constructor for Propulsion
Propulsion();
/// @brief Update the propulsion state of the Roboid
/// @param currentTimeMs The time in milliseconds when calling this
void Update(unsigned long currentTimeMs);
/// @brief Get the number of motors in this roboid
/// @return The number of motors. Zero when no motors are present
unsigned int GetMotorCount();
/// @brief Get a specific motor
/// @param motorIx The index of the motor
/// @return Returns the motor or a nullptr when no motor with the given index
/// could be found
Motor *GetMotor(unsigned int motorIx);
/// @brief Get the Placement of a specific Motor
/// @param motorIx The index of the Motor
/// @return Returns the Placement or a nullptr when no Placement with the give
/// index could be found
// Placement *GetMotorPlacement(unsigned int motorIx);
/// @brief Sets the forward and rotation speed of a (grounded) Roboid
/// @param forward The target forward speed
/// @param yaw The target rotation speed around the vertical axis
/// This function is typically used for Roboid which are driving on the
/// ground.
virtual void SetTwistSpeed(float forward, float yaw = 0.0F);
/// @brief Sets the forward, sideward and rotation speed of a (grounded)
/// Roboid
/// @param linear The target linear (forward, sideward) speed
/// @param yaw The target rotation speed around the vertical axis
/// This function is typically used for Roboid which are driving on the ground
/// which have to ability to move sideward
virtual void SetTwistSpeed(Vector2 linear, float yaw = 0.0F);
/// @brief Set the target 3D linear and 3D rotation speed of a (flying) Roboid
/// @param linear The target linear speed
/// @param yaw The target rotation speed around the vertical axis
/// @param pitch The target rotation speed around the sideward axis
/// @param roll The target rotation speed around hte forward axis
virtual void SetTwistSpeed(Vector3 linear, float yaw = 0.0F,
float pitch = 0.0F, float roll = 0.0F);
virtual void SetVelocity(Spherical16 velocity);
virtual void SetAngularVelocity(Spherical16 velocity);
/// @brief Retrieve the current velocity of the roboid
/// @return The velocity in polar coordinates
/// The actual units of the velocity depend on the implementation
virtual Spherical16 GetVelocity();
/// @brief Retrieve the current angular velocity of the roboid
/// @return The angular velocity
/// The actual unit of the angular velocity depend on the implementation
virtual Spherical16 GetAngularVelocity();
/// @brief The roboid of this propulsion system
Roboid *roboid = nullptr;
protected:
/// @brief The number of motors used for Propulsion
unsigned int motorCount = 0;
/// @brief The Placement of the motors used for Propulsion
// Placement *placement = nullptr;
Motor **motors = nullptr;
Spherical16 linearVelocity = Spherical16::zero;
Spherical16 angularVelocity = Spherical16::zero;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

38
Quadcopter.cpp Normal file
View File

@ -0,0 +1,38 @@
#include "Quadcopter.h"
Quadcopter::Quadcopter() {}
void Quadcopter::SetTwistSpeed(float forward, float yaw) {
this->velocity = Vector3::forward * forward;
this->yawSpeed = yaw;
}
void Quadcopter::SetTwistSpeed(Vector2 linear, float yaw) {
this->velocity = Vector3(linear.x, 0.0F, linear.y);
this->yawSpeed = yaw;
}
void Quadcopter::SetTwistSpeed(Vector3 velocity,
float yaw,
float pitch,
float roll) {
this->velocity = velocity;
this->yawSpeed = yaw;
this->rollSpeed = roll;
this->pitchSpeed = pitch;
}
Vector3 Quadcopter::GetTargetVelocity() {
return this->velocity;
}
float Quadcopter::GetPitchSpeed() {
return this->pitchSpeed;
}
float Quadcopter::GetYawSpeed() {
return this->yawSpeed;
}
float Quadcopter::GetRollSpeed() {
return this->rollSpeed;
}

36
Quadcopter.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include "ControlCore/Thing.h"
#include "LinearAlgebra/Vector3.h"
#include "Propulsion.h"
namespace Passer {
namespace RoboidControl {
/// @brief Support for Quadcopter as a propulsion method
/// @note This is work in progress
class Quadcopter : public Propulsion {
public:
/// @brief Default constuctor
Quadcopter();
virtual void SetTwistSpeed(float forward, float yaw = 0.0F) override;
virtual void SetTwistSpeed(Vector2 linear, float yaw = 0.0F) override;
virtual void SetTwistSpeed(Vector3 linear, float yaw = 0.0F,
float pitch = 0.0F, float roll = 0.0F) override;
Vector3 GetTargetVelocity();
float GetYawSpeed();
float GetPitchSpeed();
float GetRollSpeed();
protected:
Vector3 velocity = Vector3::zero;
float pitchSpeed = 0.0F;
float yawSpeed = 0.0F;
float rollSpeed = 0.0F;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

19
README.md Normal file
View File

@ -0,0 +1,19 @@
RoboidControl is a cross platform framework to control autonomous robots. This library contains the generic functionality. Most projects will use one of the platform-specific implementations:
* [RoboidControl for Arduino](https://gitlab.passervr.com/passer/arduino/roboidcontrol)
Network Sync Protocol
=====================
The client connects to a Roboid Site using a Serial or WiFi connection.
It will then send a 'Client (0xA0)' message to the Site
The Site will respond with a 'NetworkId (0xA1)' message containing the NetworkId of this new client.
Then the client can start sending normal messages.
When the client sends a 'Pose (0x10)' message for a thing which is not known by the Site
(the networkId/thingId combination is not known), the Site will send an 'Investigate (0x81)'
message to the client.
The client shall respond with a 'NewThing (0x80)' message containing the type of the thing.
Optionally, the client can send a 'ModelURL (0x90)' message containing a link to the OBJ model of the thing.
The same mechanism work the other way round, when the client receives a pose for an unknown object.
The deviation is that the Site will (currently) not send 'ModelURL (0x90)' messages.

93
Roboid.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "Roboid.h"
#include "LinearAlgebra/FloatSingle.h"
#include "NetworkSync.h"
#include <string.h>
// #define RC_DEBUG
#ifdef RC_DEBUG
#include <Arduino.h>
#endif
Roboid::Roboid() : Thing() {
#ifdef RC_DEBUG
Serial.begin(115200);
#endif
this->type = (unsigned char)Type::Roboid;
this->perception = new Perception();
this->perception->roboid = this;
this->propulsion = new Propulsion();
this->networkSync = nullptr;
this->position = Spherical16::zero;
this->orientation = SwingTwist16::identity;
this->lastUpdateTimeMs = 0;
}
Roboid::Roboid(Propulsion *propulsion) : Roboid() {
this->propulsion = propulsion;
if (propulsion != nullptr)
propulsion->roboid = this;
}
void Roboid::Update(unsigned long currentTimeMs) {
if (this->lastUpdateTimeMs == 0)
this->lastUpdateTimeMs = currentTimeMs;
// if (perception != nullptr)
// perception->Update(currentTimeMs);
if (propulsion != nullptr) {
propulsion->Update(currentTimeMs);
float deltaTime = (float)(currentTimeMs - lastUpdateTimeMs) / 1000;
this->angularVelocity = this->propulsion->GetAngularVelocity();
SwingTwist16 rotation =
SwingTwist16::AngleAxis(this->angularVelocity.distance * deltaTime,
this->angularVelocity.direction);
SetOrientation(this->orientation * rotation);
this->linearVelocity = this->propulsion->GetVelocity();
Spherical16 translation =
this->orientation * this->linearVelocity * deltaTime;
SetPosition(this->position + translation);
}
if (children != nullptr) {
for (unsigned char childIx = 0; childIx < this->childCount; childIx++)
children[childIx]->Update(currentTimeMs);
}
if (networkSync != nullptr)
networkSync->NetworkUpdate(this);
lastUpdateTimeMs = currentTimeMs;
}
// void Roboid::AddChild(Thing *child) {
// std::cout << "Roboid add child";
// Thing::AddChild(child);
// if (child->IsSensor()) {
// Sensor *childSensor = (Sensor *)child;
// this->perception->AddSensor(childSensor);
// }
// }
void Passer::RoboidControl::Roboid::Release(Thing *child) {
if (RemoveChild(child) != nullptr) {
child->SetPosition(this->position);
child->SetOrientation(this->orientation);
// this creates an new thing, I wish I could avoid this.
this->perception->AddTrackedObject(nullptr, child);
}
}
void Roboid::LoadModel(const char *url) {
this->modelUrl = url;
if (this->networkSync == nullptr)
return;
this->networkSync->Download(url);
}

85
Roboid.h Normal file
View File

@ -0,0 +1,85 @@
#pragma once
#include "Perception.h"
#include "Propulsion.h"
#include "ServoMotor.h"
namespace Passer {
namespace RoboidControl {
class NetworkSync;
/// @brief A Roboid is used to control autonomous robots
class Roboid : public Thing {
public:
/// @brief Default constructor for a Roboid
Roboid();
/// @brief Creates a Roboid with Perception and Propulsion abilities
/// @param perception The Perception implementation to use for this Roboid
/// @param propulsion The Propulsion implementation to use for this Roboid
Roboid(Propulsion *propulsion);
/// @brief Update the state of the Roboid
/// @param currentTimeMs The time in milliseconds when calling this
/// function
void Update(unsigned long currentTimeMs);
/// @brief The Perception module of this Roboid
Perception *perception = nullptr;
/// @brief The Propulsion module of this Roboid
Propulsion *propulsion = nullptr;
// ServoMotor *actuation = nullptr;
/// @brief The reference to the module to synchronize states across a network
NetworkSync *networkSync = nullptr;
/// @brief Retrieve the current position of the roboid
/// @return The position in carthesian coordinates in world space
/// @details The origin and units of the position depends on the position
/// tracking system used. This value will be Vector3::zero unless a position
/// is received through network synchronisation
// virtual Spherical16 GetPosition();
// Vector2 GetPosition2D();
/// @brief Retrieve the current orientation of the roboid
/// @return The orientation quaternion in world space
/// @details The origin orientation depends on the position tracking system
/// used. This value will be Quaternion::identity unless an orientation is
/// received though network synchronization
// virtual SwingTwist16 GetOrientation();
/// @brief Update the current position of the roboid
/// @param worldPosition The position of the roboid in carthesian coordinates
/// in world space
/// @details The use of this function will also update the positions and
/// orientations of the perceived objects by the roboid
/// (roboid->perception->perceivedObjects), as these are local to the
/// roboid's position.
// virtual void SetPosition(Spherical16 worldPosition);
/// @brief Update the current orientation of the roboid
/// @param worldOrientation The orientation of the roboid in world space
/// @details The use of this function will also update the orientations of the
/// perceived objects by the roboid (roboid->perception->perceivedObjets),
/// as these are local to the roboid' orientation.
// virtual void SetOrientation(SwingTwist16 worldOrientation);
// virtual void AddChild(Thing *child) override;
void Release(Thing *child);
Thing *worldOrigin =
nullptr; // thing to track the world origin to be able to transform
// world coordinates into roboid or local coordinates
// Perhaps this will move to perception at some point
/// @brief Loads the model and adds the skeleton (if any) to the roboid
/// @param url The url of the model
/// @remark The only supported model format is .gltf
void LoadModel(const char *url);
private:
unsigned long lastUpdateTimeMs = 0;
};
} // namespace RoboidControl
} // namespace Passer
using namespace Passer::RoboidControl;

View File

@ -0,0 +1,8 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}

42
Sensor.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "Sensor.h"
#include "Roboid.h"
Sensor::Sensor() : Thing() {
// this->type = (unsigned char)Type::Sensor;
}
// void Sensor::SetParent(Thing *parent) {
// this->parent = parent;
// if (this->parent != nullptr &&
// this->parent->GetParent() == nullptr) { // Is the parent a root object?
// // Then it is a roboid
// Roboid *roboidParent = (Roboid *)this->parent;
// roboidParent->perception->AddSensor(this);
// }
// }
void Sensor::ConnectTo(Thing *oldThing) {
this->name = oldThing->name;
this->id = oldThing->id;
Thing *oldParent = oldThing->GetParent();
oldParent->RemoveChild(oldThing);
oldParent->AddChild(this);
for (int childIx = 0; childIx < oldThing->childCount; childIx++) {
Thing *child = oldThing->GetChildByIndex(childIx);
this->AddChild(child);
}
this->position = oldThing->GetPosition();
this->orientation = oldThing->GetOrientation();
// delete (thing); // can we do this?
}
void Sensor::ConnectTo(Thing *rootThing, const char *thingName) {
Thing *thing = rootThing->FindThing(thingName);
if (thing != nullptr)
this->ConnectTo(thing);
}

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