mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-27 02:01:42 +00:00
Compare commits
988 Commits
v2023.4.2
...
v2025.0.0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7173dbd3c | ||
|
|
2ff7033edf | ||
|
|
ca92ef89d3 | ||
|
|
b8c2571638 | ||
|
|
d2b1aa1869 | ||
|
|
76a3a60712 | ||
|
|
f5df6f88c8 | ||
|
|
7f5970b27a | ||
|
|
25865759f4 | ||
|
|
e2893fc1a3 | ||
|
|
b6bd798f9e | ||
|
|
66c0abb732 | ||
|
|
e884221a8d | ||
|
|
3a0ee5c9a7 | ||
|
|
bb8480c690 | ||
|
|
d3aa7f85dd | ||
|
|
3d6b710293 | ||
|
|
ae6954c78f | ||
|
|
a087544933 | ||
|
|
b9935c9885 | ||
|
|
3617a95260 | ||
|
|
b0cc84a9c7 | ||
|
|
e2dcbd016d | ||
|
|
72ae751b9a | ||
|
|
27cbbfe2ab | ||
|
|
65c6306047 | ||
|
|
a0efc9ca31 | ||
|
|
917b5dde66 | ||
|
|
300595da9e | ||
|
|
0606da64c9 | ||
|
|
1c884b2260 | ||
|
|
5b94421b5a | ||
|
|
ad18fa62ee | ||
|
|
5221069bcc | ||
|
|
df4694c9df | ||
|
|
b99d9c1710 | ||
|
|
d6b66bfa55 | ||
|
|
8def7b2222 | ||
|
|
afaf7e2c3f | ||
|
|
5f8c842223 | ||
|
|
bdc42532ed | ||
|
|
21e970f2cd | ||
|
|
38ee6476f2 | ||
|
|
a97904ed1f | ||
|
|
1828fdaaa4 | ||
|
|
7751f6d1d2 | ||
|
|
7c8a36f3eb | ||
|
|
ae8e4289b9 | ||
|
|
c1fc86033a | ||
|
|
9782abbcb1 | ||
|
|
0ad4cd69d0 | ||
|
|
76685fe7e8 | ||
|
|
3b8d8a367b | ||
|
|
a6ac4228c3 | ||
|
|
98fcbdb44e | ||
|
|
958387ddd3 | ||
|
|
a2f2502f70 | ||
|
|
fbfef85f45 | ||
|
|
cdbd64c3df | ||
|
|
eb3635e622 | ||
|
|
9ef6d13b27 | ||
|
|
e2545231b8 | ||
|
|
4252a36668 | ||
|
|
f1e072fc98 | ||
|
|
221d568bd9 | ||
|
|
c62396ce4e | ||
|
|
f42bc45ee8 | ||
|
|
8c107e4b75 | ||
|
|
652c721895 | ||
|
|
7e00f2d3eb | ||
|
|
5c5e5af0c6 | ||
|
|
237ebfd0f2 | ||
|
|
dc0e9712e6 | ||
|
|
d05c7c125b | ||
|
|
294c9946ae | ||
|
|
6220c6be4d | ||
|
|
72a6d22d9a | ||
|
|
8834cb1de4 | ||
|
|
ae655a3a71 | ||
|
|
65f4505e3c | ||
|
|
badd090538 | ||
|
|
2fd8dae503 | ||
|
|
27efd37c52 | ||
|
|
0c822b45ab | ||
|
|
58751338ec | ||
|
|
0b5aec82ff | ||
|
|
820f68dc08 | ||
|
|
8c420fa4c1 | ||
|
|
ab315e24c8 | ||
|
|
0f45fe9486 | ||
|
|
7fc17811fa | ||
|
|
7fbbecb5b7 | ||
|
|
b0d3bf4ddf | ||
|
|
40b35f0d51 | ||
|
|
637647b941 | ||
|
|
0a967e0e62 | ||
|
|
4ce8f3f935 | ||
|
|
178fe99f12 | ||
|
|
305a0657e2 | ||
|
|
fb3e0e1ecb | ||
|
|
2e828ae053 | ||
|
|
d3af27be94 | ||
|
|
4cb2edbb98 | ||
|
|
d88c71ffdc | ||
|
|
6c9dcc157e | ||
|
|
dc00a13d83 | ||
|
|
bdc7344df1 | ||
|
|
a6dd95eb9e | ||
|
|
2563ff9f18 | ||
|
|
f77d01c085 | ||
|
|
408980462f | ||
|
|
2e71e85b8d | ||
|
|
6a73ca8c08 | ||
|
|
9ed2f66914 | ||
|
|
d3060d8eba | ||
|
|
27babe5584 | ||
|
|
7596aeda10 | ||
|
|
c76b358290 | ||
|
|
bad56bcbe8 | ||
|
|
e172aa66f7 | ||
|
|
9c7120e6bf | ||
|
|
0afc35f336 | ||
|
|
ae4bcefefc | ||
|
|
513d1a0a15 | ||
|
|
a85e7693de | ||
|
|
5359112b15 | ||
|
|
7601b7250a | ||
|
|
a9cfd0d0f9 | ||
|
|
c71db8ea9c | ||
|
|
70417f64da | ||
|
|
f5e08652f8 | ||
|
|
eec99eb653 | ||
|
|
9cae707065 | ||
|
|
0f8aa8aedf | ||
|
|
ac32f921f6 | ||
|
|
67fe11f9cd | ||
|
|
1ec089c7f9 | ||
|
|
1727c74b80 | ||
|
|
890185acee | ||
|
|
fd363fdf5a | ||
|
|
1e4a647918 | ||
|
|
39d33bfca6 | ||
|
|
5edc652c05 | ||
|
|
d9eb3691d8 | ||
|
|
a42ffb8fa4 | ||
|
|
d4e6a068ac | ||
|
|
cdfa2ece6f | ||
|
|
962bf7ff10 | ||
|
|
2cd3935aa8 | ||
|
|
427b7dcc11 | ||
|
|
e73050a8fa | ||
|
|
3e6c0d0b71 | ||
|
|
dc4c63568a | ||
|
|
b620b6a4dd | ||
|
|
d7dfa63ae9 | ||
|
|
e89c8c1008 | ||
|
|
abfe2488ff | ||
|
|
3e5187ff32 | ||
|
|
7bc0380694 | ||
|
|
98d2f45fa9 | ||
|
|
d14dfed828 | ||
|
|
f26adc556d | ||
|
|
3c14d87006 | ||
|
|
77536e68f0 | ||
|
|
c88be31ec2 | ||
|
|
74f648689e | ||
|
|
2def62a1ef | ||
|
|
3a5d24ab1d | ||
|
|
02c78bc9b6 | ||
|
|
998340296d | ||
|
|
d26e6d9ecc | ||
|
|
fbb3669546 | ||
|
|
c46847b32a | ||
|
|
33f12f0e31 | ||
|
|
25ad6eafd5 | ||
|
|
84a55d13f3 | ||
|
|
4a548935d3 | ||
|
|
85ea5f8497 | ||
|
|
c32e7db8e3 | ||
|
|
2392c9f278 | ||
|
|
0dbdbb2aac | ||
|
|
b38540e1af | ||
|
|
ff929d4a5f | ||
|
|
b2113d3a9a | ||
|
|
5370f249a1 | ||
|
|
74057543aa | ||
|
|
b4674bacb9 | ||
|
|
fd4424eb89 | ||
|
|
c10f7d91b7 | ||
|
|
0b13459469 | ||
|
|
a1af2357e8 | ||
|
|
3116f790ea | ||
|
|
0e013dc021 | ||
|
|
f74f6f1d42 | ||
|
|
11c60df3e0 | ||
|
|
3d9152a461 | ||
|
|
fbd239d15e | ||
|
|
7cd4a75323 | ||
|
|
973bb55e66 | ||
|
|
7bd8c44570 | ||
|
|
38c128fe6a | ||
|
|
18e57f7872 | ||
|
|
ccb4cbed63 | ||
|
|
c19ee8b0fe | ||
|
|
e64c20346d | ||
|
|
f1a1ffd7fc | ||
|
|
c27ddf5ef9 | ||
|
|
8b669330eb | ||
|
|
ca6e307ea5 | ||
|
|
607682b687 | ||
|
|
4b94a64b06 | ||
|
|
63d9e945b8 | ||
|
|
0ad6b3acb3 | ||
|
|
02aed35c6e | ||
|
|
a8a352ed8c | ||
|
|
0cdab55e5b | ||
|
|
ba15844c28 | ||
|
|
6afff99640 | ||
|
|
d4d0545dc1 | ||
|
|
9ed0631ec9 | ||
|
|
fb947fe998 | ||
|
|
6b6a55b72e | ||
|
|
1e168f363e | ||
|
|
da3abade83 | ||
|
|
62cba9a4d3 | ||
|
|
3207795d0d | ||
|
|
e506e09a06 | ||
|
|
163f7ee704 | ||
|
|
e9c744c456 | ||
|
|
300419c151 | ||
|
|
1db3936965 | ||
|
|
4f9d73783b | ||
|
|
3b2a2381b6 | ||
|
|
6cc7e52de7 | ||
|
|
d4533a8900 | ||
|
|
90bb6cfffa | ||
|
|
cb094e4ff6 | ||
|
|
60c6ed9812 | ||
|
|
ee15cc172a | ||
|
|
1016e95242 | ||
|
|
19f1903959 | ||
|
|
53ebb6679e | ||
|
|
177132fa2a | ||
|
|
bbb230491a | ||
|
|
84ef71ace0 | ||
|
|
68736d802d | ||
|
|
d895a0c09f | ||
|
|
64a9d413bf | ||
|
|
a70e83ae2e | ||
|
|
47652d7a3c | ||
|
|
be78552db7 | ||
|
|
3acae550d6 | ||
|
|
9d55941ce5 | ||
|
|
51d92c7027 | ||
|
|
9206b47d67 | ||
|
|
6fc16264ce | ||
|
|
ad18f35477 | ||
|
|
0c6bd846bc | ||
|
|
19c1556472 | ||
|
|
3928ed5647 | ||
|
|
e408f3ad27 | ||
|
|
7957f4a625 | ||
|
|
1241dfdf68 | ||
|
|
4d109309c9 | ||
|
|
7560d18e09 | ||
|
|
f518e143d0 | ||
|
|
6fab87fa4c | ||
|
|
42c41785ac | ||
|
|
1a7eeb6282 | ||
|
|
98c0827236 | ||
|
|
57aa8ca0dd | ||
|
|
789af2ad26 | ||
|
|
9a5366bb83 | ||
|
|
77c09b9ce2 | ||
|
|
9ec27c1202 | ||
|
|
d653408873 | ||
|
|
24a24c9051 | ||
|
|
0e5eb3f35c | ||
|
|
4b15c73f64 | ||
|
|
a274e297cd | ||
|
|
d198605562 | ||
|
|
dfaad7ca22 | ||
|
|
2df82ec957 | ||
|
|
3661f485af | ||
|
|
7f9389f101 | ||
|
|
ca35bcd827 | ||
|
|
9227d09960 | ||
|
|
370126db38 | ||
|
|
1330235918 | ||
|
|
d392570659 | ||
|
|
a2d45dbca4 | ||
|
|
30965b20cf | ||
|
|
5bc942f532 | ||
|
|
97828bd325 | ||
|
|
6da21c4943 | ||
|
|
ecf1755e3e | ||
|
|
154d920e67 | ||
|
|
d2ee423749 | ||
|
|
7e3678b0a4 | ||
|
|
4a55d830e4 | ||
|
|
420020c0d5 | ||
|
|
077c8f4092 | ||
|
|
84e3a22baa | ||
|
|
b482321c0d | ||
|
|
d181e353a0 | ||
|
|
2386e44f3a | ||
|
|
fa5b604f16 | ||
|
|
67e8306819 | ||
|
|
1981b8debd | ||
|
|
ba9c21cf38 | ||
|
|
211c2a375c | ||
|
|
75b2fa1cc3 | ||
|
|
84b089b209 | ||
|
|
ce550705d7 | ||
|
|
3989617bde | ||
|
|
f1836e1321 | ||
|
|
d05f179a9a | ||
|
|
b1b03bed85 | ||
|
|
fa63fbf446 | ||
|
|
4809f3d0fc | ||
|
|
dd90965362 | ||
|
|
8659372d08 | ||
|
|
a2e4d0b15d | ||
|
|
0a46a3a618 | ||
|
|
7c26bc70ab | ||
|
|
f94e3d81b9 | ||
|
|
6bed82a18e | ||
|
|
4595f84719 | ||
|
|
707cb06105 | ||
|
|
3e40b9e5da | ||
|
|
106518c3f8 | ||
|
|
19cb2a8eb4 | ||
|
|
13f4460e00 | ||
|
|
4210f5635d | ||
|
|
0f060afb55 | ||
|
|
f29a7d2e50 | ||
|
|
6e58db398d | ||
|
|
4ac0720385 | ||
|
|
44db3e0ac0 | ||
|
|
73c7d87db7 | ||
|
|
25636b712f | ||
|
|
01fb98baaa | ||
|
|
5c424248c4 | ||
|
|
c486972c55 | ||
|
|
783acb9b72 | ||
|
|
99ab836894 | ||
|
|
ad0859a8c9 | ||
|
|
5579219716 | ||
|
|
98f06911c7 | ||
|
|
e1d49b975c | ||
|
|
8a0bf2b7a4 | ||
|
|
91d8837c11 | ||
|
|
e7c9f27683 | ||
|
|
8aca706217 | ||
|
|
7d3e4ddba9 | ||
|
|
ec3cb3dcba | ||
|
|
495585b25d | ||
|
|
f9aabc5ab2 | ||
|
|
c16946c0ec | ||
|
|
b7f4eb2811 | ||
|
|
f419a62b38 | ||
|
|
938bf45fd9 | ||
|
|
c34debe012 | ||
|
|
07183765de | ||
|
|
af46034b7f | ||
|
|
636ef58d94 | ||
|
|
cc631d2a69 | ||
|
|
09f76b32c2 | ||
|
|
47c5fd8620 | ||
|
|
24a76be694 | ||
|
|
9333951736 | ||
|
|
6a2d3c30a6 | ||
|
|
e07de37e64 | ||
|
|
141241d2d6 | ||
|
|
f2c2bab7dc | ||
|
|
5659038443 | ||
|
|
8aeee03626 | ||
|
|
55508706ff | ||
|
|
ab78b930e9 | ||
|
|
795d4be9fd | ||
|
|
7aa9ad44b8 | ||
|
|
92c81d0791 | ||
|
|
1ce617be07 | ||
|
|
2441b57156 | ||
|
|
21d1972d7a | ||
|
|
c29e8c66cf | ||
|
|
ab309e34ef | ||
|
|
22a322c9f3 | ||
|
|
1dba26c937 | ||
|
|
ef1cb3f41e | ||
|
|
aeb1a4aa33 | ||
|
|
c1178d5add | ||
|
|
4e4a468d4d | ||
|
|
d1793f077d | ||
|
|
43fb6e9f87 | ||
|
|
bcef6c5398 | ||
|
|
4059e0cd9f | ||
|
|
0b2cfb3abc | ||
|
|
df5e439b0c | ||
|
|
0ff7478968 | ||
|
|
6f23d32fe1 | ||
|
|
35a1c52788 | ||
|
|
e4e2bafdb1 | ||
|
|
3d201c71f7 | ||
|
|
f02984159f | ||
|
|
a004c9e05f | ||
|
|
0b4c6a1546 | ||
|
|
ab15dae887 | ||
|
|
9599c1f56f | ||
|
|
f87c64af8a | ||
|
|
8798700cec | ||
|
|
85c9ae6eff | ||
|
|
7c8b7a97ad | ||
|
|
d9b504bc84 | ||
|
|
906b810136 | ||
|
|
56e5b404d1 | ||
|
|
8723ee5c39 | ||
|
|
192a28af47 | ||
|
|
d40bdd70ba | ||
|
|
7bfadf32e5 | ||
|
|
a770110438 | ||
|
|
54a55b8b53 | ||
|
|
7d4e515a6b | ||
|
|
5200316c14 | ||
|
|
ddf79a25d4 | ||
|
|
a71adef316 | ||
|
|
39a0bf4b98 | ||
|
|
f5fc101fda | ||
|
|
38bf024c96 | ||
|
|
9d11544c18 | ||
|
|
28deba20f5 | ||
|
|
c2971c0bb3 | ||
|
|
41cfc961e4 | ||
|
|
14c3ade155 | ||
|
|
90757b9e90 | ||
|
|
2676b77873 | ||
|
|
d32c10487c | ||
|
|
9bc5fcf886 | ||
|
|
d431abba3b | ||
|
|
2bb1409b82 | ||
|
|
66172ab288 | ||
|
|
e8f8c0ceb0 | ||
|
|
890992a849 | ||
|
|
a583ca01e1 | ||
|
|
ca272de400 | ||
|
|
76ae090570 | ||
|
|
5172ab8fd0 | ||
|
|
96914143ba | ||
|
|
464e6121ef | ||
|
|
5dad46cd45 | ||
|
|
54ab65a63a | ||
|
|
7ed900ae3a | ||
|
|
74b85b76a9 | ||
|
|
30816111db | ||
|
|
5cc923de33 | ||
|
|
1144115da0 | ||
|
|
ac7d726ac3 | ||
|
|
e09be72ee0 | ||
|
|
0f9ebe92d9 | ||
|
|
9fa28eb07a | ||
|
|
ca684ac207 | ||
|
|
51eecef2bd | ||
|
|
4fcf0b25a1 | ||
|
|
9b8011aa67 | ||
|
|
e00a0e84c1 | ||
|
|
23dd591394 | ||
|
|
b0719942f0 | ||
|
|
7bc89c4322 | ||
|
|
841ea682d1 | ||
|
|
a74db52dae | ||
|
|
a7eb422662 | ||
|
|
544b231d4d | ||
|
|
31cd015970 | ||
|
|
9280054eab | ||
|
|
2aba97c610 | ||
|
|
c80b2d2017 | ||
|
|
3c0652c18a | ||
|
|
95716eb0cb | ||
|
|
423fd75fa8 | ||
|
|
dfdea9c992 | ||
|
|
ca81ced409 | ||
|
|
437cc91af5 | ||
|
|
25b7dca46b | ||
|
|
bb05e20247 | ||
|
|
35744a036e | ||
|
|
80d7ad58ea | ||
|
|
f8d983b154 | ||
|
|
4a44210ee3 | ||
|
|
bdc8620d55 | ||
|
|
0ca1e9b5f9 | ||
|
|
cc30824409 | ||
|
|
b1fad062f7 | ||
|
|
ead9ae5a69 | ||
|
|
cfbff32185 | ||
|
|
7d90d0bcc3 | ||
|
|
7755e45aac | ||
|
|
3985c031da | ||
|
|
7a87fe4b60 | ||
|
|
09f3ed6a5f | ||
|
|
79dd795bc0 | ||
|
|
e117274a67 | ||
|
|
a8b80ca256 | ||
|
|
b3a9c3e96b | ||
|
|
0f8129677b | ||
|
|
d105f9e3e9 | ||
|
|
c5f2f6a0fb | ||
|
|
c1a57e422a | ||
|
|
78ebc6e9ec | ||
|
|
9ada181866 | ||
|
|
95fa5ec72f | ||
|
|
b6f2d3cc14 | ||
|
|
cc2cbeb04c | ||
|
|
fa6b171e1c | ||
|
|
d504639bbe | ||
|
|
3a1194be40 | ||
|
|
70392cbbcb | ||
|
|
17c1bd5a83 | ||
|
|
e69a9efeba | ||
|
|
14dcd0d26f | ||
|
|
ec1d261984 | ||
|
|
63dbf5c614 | ||
|
|
b2e7be9250 | ||
|
|
201a42a3cd | ||
|
|
04a781b4d7 | ||
|
|
87a8a1ced4 | ||
|
|
f1a82828fe | ||
|
|
2a04e12c6f | ||
|
|
33e0089afb | ||
|
|
d06fa633d5 | ||
|
|
049732afb8 | ||
|
|
87f7c19f90 | ||
|
|
6b53ef47cf | ||
|
|
8a3a268ae6 | ||
|
|
1c35d42cd0 | ||
|
|
ddc8db6c26 | ||
|
|
c6aff2c431 | ||
|
|
a9c5b18a39 | ||
|
|
9540b6922d | ||
|
|
83a7d33c47 | ||
|
|
a4a8ad9c75 | ||
|
|
9eecf2a456 | ||
|
|
9536a311cb | ||
|
|
8d5e6737fc | ||
|
|
07e13d60a2 | ||
|
|
1713386869 | ||
|
|
35472f5fc9 | ||
|
|
ed168b522c | ||
|
|
3e7ba2cc6f | ||
|
|
80c47da237 | ||
|
|
abe1cec90c | ||
|
|
cdf981abba | ||
|
|
04dcd80adb | ||
|
|
49920234ac | ||
|
|
366b715942 | ||
|
|
3ba501f947 | ||
|
|
ec569a58ef | ||
|
|
b91317fd36 | ||
|
|
2ab4fcbc24 | ||
|
|
98c14f1692 | ||
|
|
60bcdeded9 | ||
|
|
c87f8fd538 | ||
|
|
ad80eb3a0b | ||
|
|
c7d6ad5a0b | ||
|
|
8a8e220792 | ||
|
|
cfc6a47f76 | ||
|
|
8efa586ace | ||
|
|
23ea188e60 | ||
|
|
928e87b4f4 | ||
|
|
63ef585d4b | ||
|
|
b03a7668f9 | ||
|
|
3f08bcde54 | ||
|
|
196d963dc4 | ||
|
|
f4cbcbc984 | ||
|
|
ec0f7fefb0 | ||
|
|
3d618bdbfd | ||
|
|
1fa7445667 | ||
|
|
269b9647da | ||
|
|
bee32f080e | ||
|
|
25dad5a531 | ||
|
|
4a93581f1a | ||
|
|
abb2857e03 | ||
|
|
b14a61e1c0 | ||
|
|
cf54d9ccb7 | ||
|
|
ecb7cfa9ef | ||
|
|
7c6fe56cf2 | ||
|
|
85147bf69e | ||
|
|
244163acad | ||
|
|
820728503d | ||
|
|
45f307d87e | ||
|
|
4ce4d63efc | ||
|
|
579007ceb3 | ||
|
|
3f3a169149 | ||
|
|
7501e4ac88 | ||
|
|
99630d2e78 | ||
|
|
02cbbc997d | ||
|
|
ed93889e17 | ||
|
|
da70e4c262 | ||
|
|
e814595ea7 | ||
|
|
f98c943445 | ||
|
|
b3eb64b0f7 | ||
|
|
7d9ba256c2 | ||
|
|
1f6492e3d8 | ||
|
|
638f04f626 | ||
|
|
210255bfff | ||
|
|
896772c750 | ||
|
|
fd427f6c82 | ||
|
|
c0b4c6cce6 | ||
|
|
9a0aafd8ab | ||
|
|
1c724884ca | ||
|
|
5b0db6b93e | ||
|
|
f8cbbbac12 | ||
|
|
b9944be09c | ||
|
|
de5e4eda6c | ||
|
|
227e660e20 | ||
|
|
36f94c9f21 | ||
|
|
741d166457 | ||
|
|
1d23513945 | ||
|
|
ff1849052e | ||
|
|
58e8474368 | ||
|
|
fb07b0da49 | ||
|
|
81893ad73d | ||
|
|
faa1e665ba | ||
|
|
a789632052 | ||
|
|
8f60ab5182 | ||
|
|
33243f982b | ||
|
|
420f2f7c80 | ||
|
|
2b63e35ded | ||
|
|
be939cb636 | ||
|
|
69a54de202 | ||
|
|
fef03a3ff5 | ||
|
|
8b7c6852cf | ||
|
|
1d19e09ca9 | ||
|
|
58141d6eb5 | ||
|
|
6576d9b474 | ||
|
|
a4030c670f | ||
|
|
0960f11eba | ||
|
|
cb1bd0a3be | ||
|
|
4831277ffe | ||
|
|
3eb372c25a | ||
|
|
1fec8596a4 | ||
|
|
f7e47d03f3 | ||
|
|
a331ed2374 | ||
|
|
8d2cbfce16 | ||
|
|
48facb9cef | ||
|
|
aecbcb08fc | ||
|
|
5e295dfbda | ||
|
|
c7c7e05d9d | ||
|
|
c92bad52cb | ||
|
|
d404af5f24 | ||
|
|
e56f1a3632 | ||
|
|
8f5bcad244 | ||
|
|
703dedc4a6 | ||
|
|
c69a0d7504 | ||
|
|
66358d103e | ||
|
|
4be8384a76 | ||
|
|
90288f06a6 | ||
|
|
9e9583412e | ||
|
|
d4fcd80b7b | ||
|
|
7b70e66772 | ||
|
|
5f651df5d5 | ||
|
|
65b26738d5 | ||
|
|
d0305951ad | ||
|
|
e8d4a20331 | ||
|
|
2b58bbde0b | ||
|
|
dd5612fbee | ||
|
|
eab44534c3 | ||
|
|
5ab54ff760 | ||
|
|
1b6ec5a95d | ||
|
|
07a0d22fe6 | ||
|
|
97021f074a | ||
|
|
87ce1e3761 | ||
|
|
6ef94de9b5 | ||
|
|
c395b29fb4 | ||
|
|
c4643ba047 | ||
|
|
51dcb8b55a | ||
|
|
daf7702007 | ||
|
|
e67df8c180 | ||
|
|
7be290147c | ||
|
|
9fe258427a | ||
|
|
633c5a8a22 | ||
|
|
b265a68eea | ||
|
|
e93c233d60 | ||
|
|
5383589f99 | ||
|
|
40b552be4a | ||
|
|
202a75fe08 | ||
|
|
8896515eb7 | ||
|
|
ae59a2fba2 | ||
|
|
3b51ecc35b | ||
|
|
17f1062885 | ||
|
|
bb39900353 | ||
|
|
cb99517838 | ||
|
|
25b0622d4c | ||
|
|
34e7849605 | ||
|
|
e9e611c9d8 | ||
|
|
94f58cc536 | ||
|
|
4da5aee88a | ||
|
|
2e3ddf5502 | ||
|
|
19a8850fb1 | ||
|
|
9047682202 | ||
|
|
575348b81c | ||
|
|
12e2043b77 | ||
|
|
4bac4dd0f4 | ||
|
|
494cfd78c1 | ||
|
|
43a727e868 | ||
|
|
ad4b017321 | ||
|
|
4f2114d6f5 | ||
|
|
e7e927fe26 | ||
|
|
205a40c895 | ||
|
|
707444f000 | ||
|
|
3b79cb6ed3 | ||
|
|
bc7f23a632 | ||
|
|
57b2d6f254 | ||
|
|
339ef1ea39 | ||
|
|
7a9a901a73 | ||
|
|
298f8a6e33 | ||
|
|
d7ef817bae | ||
|
|
c3fb31fd0e | ||
|
|
bd64f81cf9 | ||
|
|
66e6bd81ea | ||
|
|
4fa56fd884 | ||
|
|
f63d958995 | ||
|
|
a9ab08f48b | ||
|
|
8e05983a4a | ||
|
|
3a33ce918b | ||
|
|
a6157f184d | ||
|
|
e9f612f581 | ||
|
|
1a6df6fec6 | ||
|
|
9b3f7fb548 | ||
|
|
814f18c7f5 | ||
|
|
ac23f92451 | ||
|
|
a750bee54d | ||
|
|
8e2465f8a0 | ||
|
|
10d4f5b5df | ||
|
|
b2dd59450b | ||
|
|
99f66b1e24 | ||
|
|
383289bc4b | ||
|
|
45e7720ec1 | ||
|
|
4e0d785356 | ||
|
|
3c04580a57 | ||
|
|
cf19102c4a | ||
|
|
171375f440 | ||
|
|
89add5d05b | ||
|
|
a8d4b162ab | ||
|
|
39a73b5b58 | ||
|
|
36d514eae7 | ||
|
|
52297ffe29 | ||
|
|
67043a8eeb | ||
|
|
51b0fb1492 | ||
|
|
b7657a8e28 | ||
|
|
ea17f90f87 | ||
|
|
f1d7b05723 | ||
|
|
d7264ff597 | ||
|
|
ab3bf39e0e | ||
|
|
165ebe4c79 | ||
|
|
8e2a7fd306 | ||
|
|
e322ab8e46 | ||
|
|
360fb835f4 | ||
|
|
9d86624c00 | ||
|
|
969979d6c7 | ||
|
|
0d2d989e84 | ||
|
|
cf86af7166 | ||
|
|
a0c029a35b | ||
|
|
349141b91b | ||
|
|
7889b35b67 | ||
|
|
b3ef536677 | ||
|
|
ed895815b5 | ||
|
|
2e4ad35e36 | ||
|
|
8f3d6a1d4b | ||
|
|
7c20fa1b18 | ||
|
|
89e738262c | ||
|
|
96f7fa662e | ||
|
|
7a2d336d52 | ||
|
|
f9e2757d8f | ||
|
|
0cf6e37dc1 | ||
|
|
6953a303b3 | ||
|
|
7a37e3a496 | ||
|
|
186b409e16 | ||
|
|
03764dfe93 | ||
|
|
394cfeadbd | ||
|
|
a4b7fde767 | ||
|
|
8121566258 | ||
|
|
b542e01a0b | ||
|
|
e2e1b763b2 | ||
|
|
86d7bbc4e4 | ||
|
|
e8b5d44752 | ||
|
|
38c198fa64 | ||
|
|
00450c3548 | ||
|
|
faf3cecd83 | ||
|
|
6b896a38dc | ||
|
|
c01814b80e | ||
|
|
b5bd0771eb | ||
|
|
84ed8aec05 | ||
|
|
999f677d8c | ||
|
|
338f37d302 | ||
|
|
75cbd9d6d0 | ||
|
|
e2c190487b | ||
|
|
c52dad609e | ||
|
|
e2d17a24a6 | ||
|
|
3ad5d2e42d | ||
|
|
b46a872494 | ||
|
|
d8c59ccc71 | ||
|
|
0552c8621d | ||
|
|
90e37a129f | ||
|
|
d83a6edc20 | ||
|
|
6db2c42966 | ||
|
|
21439b606c | ||
|
|
7496e0d208 | ||
|
|
0c93aded8a | ||
|
|
815a8403e5 | ||
|
|
35a8b129d9 | ||
|
|
26d6e68c8f | ||
|
|
6aa469ae45 | ||
|
|
a01b6467d3 | ||
|
|
d814f1d123 | ||
|
|
98f074b072 | ||
|
|
e9858c10e9 | ||
|
|
12dda24f06 | ||
|
|
fc75d31755 | ||
|
|
a95994fff6 | ||
|
|
2ba8fbb6f4 | ||
|
|
b8cdf97621 | ||
|
|
552f4b76b5 | ||
|
|
1938251436 | ||
|
|
873c2a6c10 | ||
|
|
99b88be4f3 | ||
|
|
d125711023 | ||
|
|
c3fab7f1f2 | ||
|
|
5ec7f18bdc | ||
|
|
c065ae1fcf | ||
|
|
44acca7c00 | ||
|
|
88b11832ec | ||
|
|
fb57d82e52 | ||
|
|
3a6e40a44b | ||
|
|
8dae5af271 | ||
|
|
fc56f8049a | ||
|
|
ef155438bd | ||
|
|
86e91e6724 | ||
|
|
72a4543493 | ||
|
|
657338715d | ||
|
|
1af224c21b | ||
|
|
0b91ca6d5a | ||
|
|
6f7cdd460e | ||
|
|
c69e34c80c | ||
|
|
335e7dd89d | ||
|
|
14f30752ab | ||
|
|
70b60e3a74 | ||
|
|
593767c8c7 | ||
|
|
daf022d3da | ||
|
|
9b8d90b852 | ||
|
|
1f6428ab63 | ||
|
|
17eb9161cd | ||
|
|
3c4b58ae1e | ||
|
|
aaea85ff16 | ||
|
|
7ac932996a | ||
|
|
efe1987e8b | ||
|
|
828bc5276f | ||
|
|
701df9eb87 | ||
|
|
e5452e3f69 | ||
|
|
7a099cb02a | ||
|
|
b250a03944 | ||
|
|
a6463ed761 | ||
|
|
f031513470 | ||
|
|
f8e74e2f7c | ||
|
|
fd5699b240 | ||
|
|
e2d385d80a | ||
|
|
d37f990ce3 | ||
|
|
a7a8b874ac | ||
|
|
3a61deedde | ||
|
|
96145de7db | ||
|
|
fffe6a7b9a | ||
|
|
6b5817836d | ||
|
|
3233883f3e | ||
|
|
c4fc21838f | ||
|
|
89fc51f0d4 | ||
|
|
663bf25aaf | ||
|
|
fe32127ea8 | ||
|
|
c1a01569b4 | ||
|
|
1fca519fb4 | ||
|
|
90602cc135 | ||
|
|
34412ac57e | ||
|
|
61aa60f0e3 | ||
|
|
ebae341a91 | ||
|
|
5d3a133f9f | ||
|
|
3a0e484691 | ||
|
|
eb3810c765 | ||
|
|
c4dc697192 | ||
|
|
0eccc3f247 | ||
|
|
f4dda4bac0 | ||
|
|
1c20c69793 | ||
|
|
1501607e48 | ||
|
|
991f4b0f62 | ||
|
|
f5b0d1484b | ||
|
|
2ce248f66c | ||
|
|
5fc4aee2d2 | ||
|
|
50b90ceb54 | ||
|
|
316cd2a453 | ||
|
|
d4ea5fa902 | ||
|
|
d6bd72d738 | ||
|
|
25ad5017a9 | ||
|
|
5c2addda0f | ||
|
|
c3e04a6ea2 | ||
|
|
d5ed9fb859 | ||
|
|
901ab693d4 | ||
|
|
9d53231b01 | ||
|
|
d466933963 | ||
|
|
652d1c44e3 | ||
|
|
6414be0e5d | ||
|
|
7ab5800487 | ||
|
|
59905ea721 | ||
|
|
753cb49a5e | ||
|
|
1c00a52b67 | ||
|
|
91cbcea841 | ||
|
|
d57d1a4598 | ||
|
|
5acc5e22aa | ||
|
|
d3c9316a97 | ||
|
|
1ea868081a | ||
|
|
5fac18ff4a | ||
|
|
a94a998002 | ||
|
|
125f6ea101 | ||
|
|
51066a5a8a | ||
|
|
282c032b60 | ||
|
|
073d19cb69 | ||
|
|
01490fc77b | ||
|
|
c9b612c986 | ||
|
|
eed1e6e3cb | ||
|
|
c976f40364 | ||
|
|
4d28bdc19e | ||
|
|
e0f851871f | ||
|
|
063c8cbedc | ||
|
|
96e41c0447 | ||
|
|
fd294bdd71 | ||
|
|
d223e4040b | ||
|
|
abc19bcb43 | ||
|
|
e909f2e687 | ||
|
|
52bd5b972d | ||
|
|
3876a2523a | ||
|
|
c82fcb1975 | ||
|
|
15ba95df7e | ||
|
|
77c2124fc5 | ||
|
|
27fb47ab10 | ||
|
|
102e4f2566 | ||
|
|
463a90f1df | ||
|
|
7a90475eec | ||
|
|
218cfea16b | ||
|
|
91392823ff | ||
|
|
258b7cc48b | ||
|
|
26cc43bee1 | ||
|
|
ac4da9b1cb | ||
|
|
21d4244cf7 | ||
|
|
1dff81bea7 | ||
|
|
7ce75574bf | ||
|
|
576bd646ae | ||
|
|
ee3b4621e5 | ||
|
|
40ca094686 | ||
|
|
9cbeb841f5 | ||
|
|
a63d06ff77 | ||
|
|
b6c43322a3 | ||
|
|
5162d0001c | ||
|
|
90fabe9651 | ||
|
|
24828afd11 | ||
|
|
e099948a77 | ||
|
|
fd2d8cb9c1 | ||
|
|
ba8c64bcff | ||
|
|
f53c6813d5 | ||
|
|
663703d370 | ||
|
|
aa34aacf6e | ||
|
|
63512bbbb8 | ||
|
|
9227b2166e | ||
|
|
fbf92e9190 | ||
|
|
2108a61362 | ||
|
|
0a66479693 | ||
|
|
b510c17ef6 | ||
|
|
e7a7eb2e93 | ||
|
|
a465f2d8f0 | ||
|
|
a3364422fa | ||
|
|
df3242a40a | ||
|
|
00abb8c1e0 | ||
|
|
c886273fd7 | ||
|
|
53b5fd2ace | ||
|
|
56b758320f | ||
|
|
08f298e4cd | ||
|
|
6d0c5b19db | ||
|
|
0d22cf5ff7 | ||
|
|
32ec5b3f75 | ||
|
|
e5c4c6b1a7 | ||
|
|
099d048d9e | ||
|
|
4af84a1c12 | ||
|
|
ce3686b80d |
164
.clang-format
164
.clang-format
@@ -1,111 +1,179 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
AccessModifierOffset: -1
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterAttributes: Always
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: true
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: true
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
Macros:
|
||||
- 'HAL_ENUM(name)=enum name'
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Never
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: NextLine
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 1
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 200
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
RawStringFormats:
|
||||
- Language: Cpp
|
||||
Delimiters:
|
||||
@@ -132,34 +200,72 @@ RawStringFormats:
|
||||
- PARSE_TEXT_PROTO
|
||||
- ParseTextOrDie
|
||||
- ParseTextProtoOrDie
|
||||
CanonicalDelimiter: ''
|
||||
- ParseTestProto
|
||||
- ParsePartialTestProto
|
||||
CanonicalDelimiter: pb
|
||||
BasedOnStyle: google
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterForeachMacros: true
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++20
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- BOOST_PP_STRINGIZE
|
||||
- CF_SWIFT_NAME
|
||||
- NS_SWIFT_NAME
|
||||
- PP_STRINGIZE
|
||||
- STRINGIZE
|
||||
...
|
||||
|
||||
@@ -35,7 +35,6 @@ Checks:
|
||||
bugprone-unhandled-self-assignment,
|
||||
bugprone-unused-raii,
|
||||
bugprone-virtual-near-miss,
|
||||
cert-dcl58-cpp,
|
||||
cert-err52-cpp,
|
||||
cert-err60-cpp,
|
||||
cert-mem57-cpp,
|
||||
@@ -50,7 +49,6 @@ Checks:
|
||||
google-build-namespaces,
|
||||
google-explicit-constructor,
|
||||
google-global-names-in-headers,
|
||||
google-readability-avoid-underscore-in-googletest-name,
|
||||
google-readability-casting,
|
||||
google-runtime-operator,
|
||||
misc-definitions-in-headers,
|
||||
|
||||
6
.gersemirc
Normal file
6
.gersemirc
Normal file
@@ -0,0 +1,6 @@
|
||||
color: false
|
||||
definitions: [cmake/modules]
|
||||
line_length: 100
|
||||
list_expansion: favour-inlining
|
||||
quiet: false
|
||||
unsafe: false
|
||||
8
.gitattributes
vendored
8
.gitattributes
vendored
@@ -1,4 +1,12 @@
|
||||
*.cpp text eol=lf
|
||||
*.gradle text eol=lf
|
||||
*.h text eol=lf
|
||||
*.inc text eol=lf
|
||||
*.java text eol=lf
|
||||
*.jinja text eol=lf
|
||||
*.json text eol=lf
|
||||
*.md text eol=lf
|
||||
*.xml text eol=lf
|
||||
|
||||
# Generated files
|
||||
*/src/generated/** linguist-generated
|
||||
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -29,8 +29,6 @@
|
||||
|
||||
/wpilibNewCommands/ @wpilibsuite/commandbased
|
||||
|
||||
/wpilibOldCommands/ @wpilibsuite/commandbased
|
||||
|
||||
/wpilibcExamples/ @wpilibsuite/wpilib @wpilibsuite/documentation
|
||||
|
||||
/wpilibjExamples/ @wpilibsuite/wpilib @wpilibsuite/documentation
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -15,6 +15,8 @@ Steps to reproduce the behavior:
|
||||
1. ...
|
||||
2. ...
|
||||
|
||||
- Link to code:
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
@@ -22,10 +24,8 @@ A clear and concise description of what you expected to happen.
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- WPILib Version: [e.g. 2021.3.1]
|
||||
- OS: [e.g. Windows 11]
|
||||
- Java version [e.g. 1.10.2]
|
||||
- C++ version [e.g. 17]
|
||||
- Project Information: [In Visual Studio Code, press the WPILib button and choose WPILib: Open Project Information. Press the copy button and paste the data here. If not using VS Code, please include WPILib version, Gradle version, Java version, C++ version (if applicable), and any third party libraries and versions]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
69
.github/workflows/cmake.yml
vendored
69
.github/workflows/cmake.yml
vendored
@@ -14,43 +14,78 @@ jobs:
|
||||
include:
|
||||
- os: ubuntu-22.04
|
||||
name: Linux
|
||||
container: wpilib/roborio-cross-ubuntu:2023-22.04
|
||||
flags: ""
|
||||
- os: macOS-11
|
||||
container: wpilib/roborio-cross-ubuntu:2024-22.04
|
||||
flags: "-DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON"
|
||||
- os: macOS-14
|
||||
name: macOS
|
||||
container: ""
|
||||
flags: "-DWITH_JAVA=OFF"
|
||||
env: "PATH=\"/opt/homebrew/opt/protobuf@3/bin:$PATH\""
|
||||
flags: "-DCMAKE_BUILD_TYPE=Release -DWITH_JAVA=OFF -DWITH_EXAMPLES=ON -DCMAKE_LIBRARY_PATH=/opt/homebrew/opt/protobuf@3/lib -DProtobuf_INCLUDE_DIR=/opt/homebrew/opt/protobuf@3/include -DProtobuf_PROTOC_EXECUTABLE=/opt/homebrew/opt/protobuf@3/bin/protoc"
|
||||
|
||||
name: "Build - ${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv4.5-java python-is-python3
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv4.5-java libprotobuf-dev protobuf-compiler ninja-build
|
||||
|
||||
- name: Install opencv (macOS)
|
||||
run: brew install opencv
|
||||
- name: Install dependencies (macOS)
|
||||
run: brew install opencv protobuf@3 ninja
|
||||
if: runner.os == 'macOS'
|
||||
|
||||
- name: Set up Python 3.8 (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.5
|
||||
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: configure
|
||||
run: mkdir build && cd build && cmake ${{ matrix.flags }} ..
|
||||
run: cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ${{ matrix.flags }}
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc)
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
- name: test
|
||||
working-directory: build
|
||||
run: ctest --output-on-failure
|
||||
|
||||
build-windows:
|
||||
name: "Build - Windows"
|
||||
runs-on: windows-2022
|
||||
steps:
|
||||
- uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||
|
||||
- name: Install CMake
|
||||
uses: lukka/get-cmake@v3.29.3
|
||||
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.5
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run vcpkg
|
||||
uses: lukka/run-vcpkg@v11.5
|
||||
with:
|
||||
vcpkgDirectory: ${{ runner.workspace }}/vcpkg
|
||||
vcpkgGitCommitId: 37c3e63a1306562f7f59c4c3c8892ddd50fdf992 # HEAD on 2024-02-24
|
||||
|
||||
- name: configure
|
||||
run: cmake -S . -B build -G "Ninja" -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_BUILD_TYPE=Release -DWITH_JAVA=OFF -DWITH_EXAMPLES=ON -DUSE_SYSTEM_FMTLIB=ON -DUSE_SYSTEM_LIBUV=ON -DUSE_SYSTEM_EIGEN=OFF -DCMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_INSTALL_OPTIONS=--clean-after-build -DVCPKG_TARGET_TRIPLET=x64-windows-release -DVCPKG_HOST_TRIPLET=x64-windows-release
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc)
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
- name: test
|
||||
working-directory: build
|
||||
# UnitTest_test segfaults on exit occasionally
|
||||
run: ctest --output-on-failure -E 'UnitTest'
|
||||
|
||||
26
.github/workflows/command-robotpy-pr.yml
vendored
Normal file
26
.github/workflows/command-robotpy-pr.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Comment on PR for robotpy
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
paths:
|
||||
- 'wpilibNewCommands/**'
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: 'This PR modifies commands. Please open a corresponding PR in [Python Commands](https://github.com/robotpy/robotpy-commands-v2/) and include a link to this PR.'
|
||||
})
|
||||
30
.github/workflows/comment-command.yml
vendored
30
.github/workflows/comment-command.yml
vendored
@@ -9,22 +9,22 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: React Rocket
|
||||
uses: actions/github-script@v4
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const {owner, repo} = context.issue
|
||||
github.reactions.createForIssueComment({
|
||||
github.rest.reactions.createForIssueComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: "rocket",
|
||||
});
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.COMMENT_COMMAND_PAT_TOKEN }}
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Checkout PR
|
||||
@@ -33,25 +33,19 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.COMMENT_COMMAND_PAT_TOKEN }}"
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
python-version: '3.10'
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@v3
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- name: Install clang-format
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo sh -c "echo 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main' >> /etc/apt/sources.list.d/proposed-repositories.list"
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -y clang-format-14
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
run: pip3 install wpiformat==2024.34
|
||||
- name: Run wpiformat
|
||||
run: wpiformat -clang 14
|
||||
run: wpiformat
|
||||
- name: Run spotlessApply
|
||||
run: ./gradlew spotlessApply
|
||||
- name: Commit
|
||||
|
||||
50
.github/workflows/documentation.yml
vendored
50
.github/workflows/documentation.yml
vendored
@@ -16,49 +16,51 @@ jobs:
|
||||
if: github.repository_owner == 'wpilibsuite' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
concurrency: ci-docs-publish
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Set environment variables (Development)
|
||||
run: |
|
||||
echo "TARGET_FOLDER=$BASE_PATH/development" >> $GITHUB_ENV
|
||||
echo "BRANCH=development" >> $GITHUB_ENV
|
||||
if: github.ref == 'refs/heads/main'
|
||||
- name: Set environment variables (Tag)
|
||||
run: |
|
||||
echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
echo "TARGET_FOLDER=$BASE_PATH/beta" >> $GITHUB_ENV
|
||||
echo "BRANCH=beta" >> $GITHUB_ENV
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Set environment variables (Release)
|
||||
run: |
|
||||
echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
echo "TARGET_FOLDER=$BASE_PATH/release" >> $GITHUB_ENV
|
||||
echo "BRANCH=release" >> $GITHUB_ENV
|
||||
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'alpha') && !contains(github.ref, 'beta')
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew docs:generateJavaDocs docs:doxygen -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
- name: Install SSH Client 🔑
|
||||
uses: webfactory/ssh-agent@v0.7.0
|
||||
uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.GH_DEPLOY_KEY }}
|
||||
- name: Deploy Java 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
- name: Deploy 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@v4.6.1
|
||||
with:
|
||||
SSH: true
|
||||
REPOSITORY_NAME: wpilibsuite/wpilibsuite.github.io
|
||||
BRANCH: main
|
||||
CLEAN: true
|
||||
FOLDER: docs/build/docs/javadoc
|
||||
TARGET_FOLDER: ${{ env.TARGET_FOLDER }}/java
|
||||
- name: Deploy C++ 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.1
|
||||
ssh-key: true
|
||||
repository-name: wpilibsuite/wpilibsuite.github.io
|
||||
branch: allwpilib-${{ env.BRANCH }}
|
||||
clean: true
|
||||
single-commit: true
|
||||
folder: docs/build/docs
|
||||
- name: Trigger Workflow
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
SSH: true
|
||||
REPOSITORY_NAME: wpilibsuite/wpilibsuite.github.io
|
||||
BRANCH: main
|
||||
CLEAN: true
|
||||
FOLDER: docs/build/docs/doxygen/html
|
||||
TARGET_FOLDER: ${{ env.TARGET_FOLDER }}/cpp
|
||||
github-token: ${{ secrets.DISPATCH_PAT_TOKEN }}
|
||||
script: |
|
||||
github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: 'wpilibsuite.github.io',
|
||||
workflow_id: 'static.yml',
|
||||
ref: 'main',
|
||||
})
|
||||
|
||||
42
.github/workflows/fix_compile_commands.py
vendored
Executable file
42
.github/workflows/fix_compile_commands.py
vendored
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Fix compile_commands.json generated by Gradle"
|
||||
)
|
||||
parser.add_argument("filename", help="compile_commands.json location")
|
||||
cmd_args = parser.parse_args()
|
||||
|
||||
# Read JSON
|
||||
with open(cmd_args.filename) as f:
|
||||
data = json.load(f)
|
||||
|
||||
for obj in data:
|
||||
out_args = []
|
||||
|
||||
# Filter out -isystem flags that cause false positives
|
||||
iter_args = iter(obj["arguments"])
|
||||
for arg in iter_args:
|
||||
if arg == "-isystem":
|
||||
next_arg = next(iter_args)
|
||||
|
||||
# /usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/include/xmmintrin.h:54:1:
|
||||
# error: conflicting types for '_mm_prefetch' [clang-diagnostic-error]
|
||||
if not next_arg.startswith("/usr/lib/gcc/"):
|
||||
out_args += ["-isystem", next_arg]
|
||||
else:
|
||||
out_args.append(arg)
|
||||
|
||||
obj["arguments"] = out_args
|
||||
|
||||
# Write JSON
|
||||
with open(cmd_args.filename, "w") as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -10,5 +10,5 @@ jobs:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
- uses: actions/checkout@v4
|
||||
- uses: gradle/actions/wrapper-validation@v3
|
||||
|
||||
138
.github/workflows/gradle.yml
vendored
138
.github/workflows/gradle.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- container: wpilib/roborio-cross-ubuntu:2023-22.04
|
||||
- container: wpilib/roborio-cross-ubuntu:2024-22.04
|
||||
artifact-name: Athena
|
||||
build-options: "-Ponlylinuxathena"
|
||||
- container: wpilib/raspbian-cross-ubuntu:bullseye-22.04
|
||||
@@ -26,27 +26,42 @@ jobs:
|
||||
build-options: "-Ponlylinuxx86-64"
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ubuntu-22.04
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Free Disk Space
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set release environment variable
|
||||
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build --build-cache -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: ${{ matrix.container }}
|
||||
options: -v ${{ github.workspace }}:/work -w /work -e ARTIFACTORY_PUBLISH_USERNAME -e ARTIFACTORY_PUBLISH_PASSWORD -e GITHUB_REF -e CI
|
||||
run: df . && rm -f semicolon_delimited_script && echo $GITHUB_REF && ./gradlew build --build-cache -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
env:
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- name: Check free disk space
|
||||
run: df .
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: build/allOutputs
|
||||
|
||||
build-host:
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.15
|
||||
MACOSX_DEPLOYMENT_TARGET: 13
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -55,18 +70,30 @@ jobs:
|
||||
artifact-name: Win64Debug
|
||||
architecture: x64
|
||||
task: "build"
|
||||
build-options: "-PciDebugOnly --max-workers 1"
|
||||
build-options: "-PciDebugOnly"
|
||||
outputs: "build/allOutputs"
|
||||
- os: windows-2022
|
||||
artifact-name: Win64Release
|
||||
architecture: x64
|
||||
build-options: "-PciReleaseOnly --max-workers 1"
|
||||
build-options: "-PciReleaseOnly"
|
||||
task: "copyAllOutputs"
|
||||
outputs: "build/allOutputs"
|
||||
- os: macOS-11
|
||||
artifact-name: macOS
|
||||
- os: windows-2022
|
||||
artifact-name: WinArm64Debug
|
||||
architecture: x64
|
||||
task: "build"
|
||||
build-options: "-PciDebugOnly -Pbuildwinarm64 -Ponlywindowsarm64"
|
||||
outputs: "build/allOutputs"
|
||||
- os: windows-2022
|
||||
artifact-name: WinArm64Release
|
||||
architecture: x64
|
||||
build-options: "-PciReleaseOnly -Pbuildwinarm64 -Ponlywindowsarm64"
|
||||
task: "copyAllOutputs"
|
||||
outputs: "build/allOutputs"
|
||||
- os: macOS-14
|
||||
artifact-name: macOS
|
||||
architecture: aarch64
|
||||
task: "build"
|
||||
outputs: "build/allOutputs"
|
||||
- os: windows-2022
|
||||
artifact-name: Win32
|
||||
@@ -76,16 +103,16 @@ jobs:
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
architecture: ${{ matrix.architecture }}
|
||||
- name: Import Developer ID Certificate
|
||||
uses: wpilibsuite/import-signing-certificate@v1
|
||||
uses: wpilibsuite/import-signing-certificate@v2
|
||||
with:
|
||||
certificate-data: ${{ secrets.APPLE_CERTIFICATE_DATA }}
|
||||
certificate-passphrase: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
@@ -105,6 +132,9 @@ jobs:
|
||||
- name: Set Java Heap Size
|
||||
run: sed -i 's/-Xmx2g/-Xmx1g/g' gradle.properties
|
||||
if: matrix.artifact-name == 'Win32'
|
||||
- name: Check disk free space (Windows)
|
||||
run: wmic logicaldisk get caption, freespace
|
||||
if: matrix.os == 'windows-2022'
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew ${{ matrix.task }} --build-cache -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
env:
|
||||
@@ -115,7 +145,10 @@ jobs:
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- uses: actions/upload-artifact@v3
|
||||
- name: Check disk free space (Windows)
|
||||
run: wmic logicaldisk get caption, freespace
|
||||
if: matrix.os == 'windows-2022'
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: ${{ matrix.outputs }}
|
||||
@@ -124,13 +157,13 @@ jobs:
|
||||
name: "Build - Documentation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Set release environment variable
|
||||
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
@@ -139,7 +172,7 @@ jobs:
|
||||
env:
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Documentation
|
||||
path: docs/build/outputs
|
||||
@@ -149,28 +182,51 @@ jobs:
|
||||
needs: [build-docker, build-host, build-documentation]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Free Disk Space
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
with:
|
||||
repository: wpilibsuite/build-tools
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
with:
|
||||
path: combiner/products/build/allOutputs
|
||||
- name: Flatten Artifacts
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
run: rsync -a --delete combiner/products/build/allOutputs/*/* combiner/products/build/allOutputs/
|
||||
- name: Check version number exists
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
run: |
|
||||
cat combiner/products/build/allOutputs/version.txt
|
||||
test -s combiner/products/build/allOutputs/version.txt
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 11
|
||||
- name: Combine
|
||||
- uses: actions/setup-java@v4
|
||||
if: |
|
||||
!startsWith(github.ref, 'refs/tags/v') &&
|
||||
github.ref != 'refs/heads/main'
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib
|
||||
- name: Combine (Master)
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
- name: Combine (Main)
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
github.ref == 'refs/heads/main'
|
||||
@@ -188,7 +244,25 @@ jobs:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
|
||||
with:
|
||||
name: Maven
|
||||
path: ~/releases
|
||||
|
||||
dispatch:
|
||||
name: dispatch
|
||||
needs: [combine]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: peter-evans/repository-dispatch@v3
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
token: ${{ secrets.TOOL_REPO_ACCESS_TOKEN }}
|
||||
repository: wpilibsuite/smartdashboard
|
||||
event-type: tag
|
||||
client-payload: '{"package_name": "allwpilib", "package_version": "${{ github.ref_name }}"}'
|
||||
|
||||
69
.github/workflows/lint-format.yml
vendored
69
.github/workflows/lint-format.yml
vendored
@@ -15,33 +15,27 @@ jobs:
|
||||
name: "wpiformat"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/allwpilib/allwpilib
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install clang-format
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo sh -c "echo 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main' >> /etc/apt/sources.list.d/proposed-repositories.list"
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -y clang-format-14
|
||||
python-version: '3.10'
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
run: pip3 install wpiformat==2024.34
|
||||
- name: Run
|
||||
run: wpiformat -clang 14
|
||||
run: wpiformat
|
||||
- name: Check output
|
||||
run: git --no-pager diff --exit-code HEAD
|
||||
- name: Generate diff
|
||||
run: git diff HEAD > wpiformat-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: wpiformat fixes
|
||||
path: wpiformat-fixes.patch
|
||||
@@ -57,43 +51,44 @@ jobs:
|
||||
tidy:
|
||||
name: "clang-tidy"
|
||||
runs-on: ubuntu-22.04
|
||||
container: wpilib/roborio-cross-ubuntu:2023-22.04
|
||||
container: wpilib/roborio-cross-ubuntu:2024-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/allwpilib/allwpilib
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v4
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install clang-tidy
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo sh -c "echo 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main' >> /etc/apt/sources.list.d/proposed-repositories.list"
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -y clang-tidy-14 clang-format-14
|
||||
python-version: '3.10'
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
run: pip3 install wpiformat==2024.34
|
||||
- name: Create compile_commands.json
|
||||
run: ./gradlew generateCompileCommands -Ptoolchain-optional-roboRio
|
||||
run: |
|
||||
./gradlew generateCompileCommands -Ptoolchain-optional-roboRio
|
||||
./.github/workflows/fix_compile_commands.py build/TargetedCompileCommands/linuxx86-64release/compile_commands.json
|
||||
./.github/workflows/fix_compile_commands.py build/TargetedCompileCommands/linuxx86-64debug/compile_commands.json
|
||||
- name: List changed files
|
||||
run: wpiformat -list-changed-files
|
||||
- name: Run clang-tidy
|
||||
run: wpiformat -clang 14 -no-format -tidy-changed -compile-commands=build/compile_commands/linuxx86-64 -vv
|
||||
- name: Run clang-tidy release
|
||||
run: wpiformat -no-format -tidy-changed -compile-commands=build/TargetedCompileCommands/linuxx86-64release -vv
|
||||
- name: Run clang-tidy debug
|
||||
run: wpiformat -no-format -tidy-changed -compile-commands=build/TargetedCompileCommands/linuxx86-64debug -vv
|
||||
javaformat:
|
||||
name: "Java format"
|
||||
runs-on: ubuntu-22.04
|
||||
container: wpilib/ubuntu-base:22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git config --global --add safe.directory /__w/allwpilib/allwpilib
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Run Java format
|
||||
@@ -107,12 +102,12 @@ jobs:
|
||||
name: "Documentation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 13
|
||||
distribution: 'temurin'
|
||||
java-version: 21
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew docs:zipDocs -PbuildServer -PdocWarningsAsErrors ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
|
||||
50
.github/workflows/pregenerate.yml
vendored
Normal file
50
.github/workflows/pregenerate.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: Check Pregenerated Files
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
update:
|
||||
name: "Update"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
- name: Install protobuf dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler && wget https://github.com/HebiRobotics/QuickBuffers/releases/download/1.3.3/protoc-gen-quickbuf-1.3.3-linux-x86_64.exe && chmod +x protoc-gen-quickbuf-1.3.3-linux-x86_64.exe
|
||||
- name: Run hal
|
||||
run: ./hal/generate_usage_reporting.py
|
||||
- name: Run ntcore
|
||||
run: ./ntcore/generate_topics.py
|
||||
- name: Run wpimath
|
||||
run: ./wpimath/generate_numbers.py && ./wpimath/generate_quickbuf.py --quickbuf_plugin=protoc-gen-quickbuf-1.3.3-linux-x86_64.exe
|
||||
- name: Run HIDs
|
||||
run: ./wpilibj/generate_hids.py && ./wpilibc/generate_hids.py && ./wpilibNewCommands/generate_hids.py
|
||||
- name: Run PWM Controllers
|
||||
run: ./wpilibj/generate_pwm_motor_controllers.py && ./wpilibc/generate_pwm_motor_controllers.py
|
||||
- name: Add untracked files to index so they count as changes
|
||||
run: git add -A
|
||||
- name: Check output
|
||||
run: git --no-pager diff --exit-code HEAD
|
||||
- name: Generate diff
|
||||
run: git diff HEAD > pregenerated-files-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pregenerated-files-fixes
|
||||
path: pregenerated-files-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
18
.github/workflows/sanitizers.yml
vendored
18
.github/workflows/sanitizers.yml
vendored
@@ -26,22 +26,26 @@ jobs:
|
||||
ctest-flags: ""
|
||||
name: "${{ matrix.name }}"
|
||||
runs-on: ubuntu-22.04
|
||||
container: wpilib/roborio-cross-ubuntu:2023-22.04
|
||||
container: wpilib/roborio-cross-ubuntu:2024-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv4.5-java python-is-python3 clang-14
|
||||
run: sudo apt-get update && sudo apt-get install -y libopencv-dev libopencv4.5-java clang-14 libprotobuf-dev protobuf-compiler ninja-build
|
||||
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.5
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: configure
|
||||
run: mkdir build && cd build && cmake -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang-14 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++-14 ${{ matrix.cmake-flags }} ..
|
||||
run: mkdir build && cd build && cmake -G Ninja -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/clang-14 -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/clang++-14 -DWITH_JAVA=OFF ${{ matrix.cmake-flags }} ..
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc)
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
|
||||
- name: test
|
||||
working-directory: build
|
||||
|
||||
144
.github/workflows/tools.yml
vendored
Normal file
144
.github/workflows/tools.yml
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
name: Tools
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
YEAR: 2024
|
||||
|
||||
jobs:
|
||||
build-artifacts:
|
||||
name: "Build - WPILib"
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
DISPLAY: ':10'
|
||||
steps:
|
||||
- name: Free Disk Space
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: false
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build WPILib with Gradle
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
image: wpilib/roborio-cross-ubuntu:2024-22.04
|
||||
options: -v ${{ github.workspace }}:/work -w /work -e GITHUB_REF -e CI -e DISPLAY
|
||||
run: df . && rm -f semicolon_delimited_script && ./gradlew :wpilibc:publish :wpilibj:publish :wpilibNewCommands:publish :hal:publish :cameraserver:publish :ntcore:publish :cscore:publish :wpimath:publish :wpinet:publish :wpiutil:publish :apriltag:publish :wpiunits:publish :simulation:halsim_gui:publish :simulation:halsim_ds_socket:publish -x test -x Javadoc -x doxygen --build-cache && cp -r /root/releases/maven/development /work
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: MavenArtifacts
|
||||
path: |
|
||||
development
|
||||
retention-days: 1
|
||||
|
||||
Robotbuilder:
|
||||
name: "Build - RobotBuilder"
|
||||
needs: [build-artifacts]
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
DISPLAY: ':10'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: wpilibsuite/robotbuilder
|
||||
fetch-depth: 0
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MavenArtifacts
|
||||
- name: Patch RobotBuilder to use local development
|
||||
run: cd src/main/resources/export && echo "wpi.maven.useLocal = false" >> java/build.gradle && echo "wpi.maven.useFrcMavenLocalDevelopment = true" >> java/build.gradle && echo "wpi.versions.wpilibVersion = '$YEAR.424242.+'" >> java/build.gradle && echo "wpi.versions.wpimathVersion = '$YEAR.424242.+'" >> java/build.gradle && echo "wpi.maven.useLocal = false" >> cpp/build.gradle && echo "wpi.maven.useFrcMavenLocalDevelopment = true" >> cpp/build.gradle && echo "wpi.versions.wpilibVersion = '$YEAR.424242.+'" >> cpp/build.gradle && echo "wpi.versions.wpimathVersion = '$YEAR.424242.+'" >> cpp/build.gradle
|
||||
- name: Install and run xvfb
|
||||
run: sudo apt-get update && sudo apt-get install -y xvfb && Xvfb $DISPLAY &
|
||||
- name: Move artifacts
|
||||
run: mkdir -p ~/releases/maven/development && cp -r edu ~/releases/maven/development
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
- name: Build RobotBuilder with Gradle
|
||||
run: ./gradlew build test --tests 'robotbuilder.exporters.*' -x htmlSanityCheck -PbuildServer -PreleaseMode ; cat build/test-results/test/TEST-robotbuilder.exporters.*.xml ;
|
||||
- name: Summarize RobotBuilder Test Results
|
||||
uses: EnricoMi/publish-unit-test-result-action@v2
|
||||
if: always()
|
||||
with:
|
||||
files: |
|
||||
build/test-results/test/TEST*.xml
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: TestResults
|
||||
path: |
|
||||
build/reports/
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: RobotBuilder Build
|
||||
path: |
|
||||
build/libs/
|
||||
retention-days: 7
|
||||
|
||||
Shuffleboard:
|
||||
name: "Build - Shuffleboard"
|
||||
needs: [build-artifacts]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: wpilibsuite/shuffleboard
|
||||
fetch-depth: 0
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MavenArtifacts
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
- name: Move artifacts
|
||||
run: mkdir -p ~/releases/maven/development && cp -r edu ~/releases/maven/development
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -y libgtk2.0-0
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build -x Javadoc
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Shuffleboard Build
|
||||
path: |
|
||||
build/allOutputs/
|
||||
retention-days: 7
|
||||
|
||||
PathWeaver:
|
||||
name: "Build - PathWeaver"
|
||||
needs: [build-artifacts]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: wpilibsuite/PathWeaver
|
||||
fetch-depth: 0
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: MavenArtifacts
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
- name: Move artifacts
|
||||
run: mkdir -p ~/releases/maven/development && cp -r edu ~/releases/maven/development
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: PathWeaver Build
|
||||
path: |
|
||||
build/allOutputs/
|
||||
retention-days: 7
|
||||
27
.github/workflows/upstream-utils.yml
vendored
27
.github/workflows/upstream-utils.yml
vendored
@@ -15,24 +15,21 @@ jobs:
|
||||
name: "Update"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f main origin/main
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Configure committer identity
|
||||
run: |
|
||||
git config --global user.email "you@example.com"
|
||||
git config --global user.name "Your Name"
|
||||
- name: Run update_drake.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_drake.py
|
||||
- name: Run update_eigen.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
@@ -41,6 +38,14 @@ jobs:
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_fmt.py
|
||||
- name: Run update_gcem.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_gcem.py
|
||||
- name: Run update_json.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_json.py
|
||||
- name: Run update_libuv.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
@@ -61,6 +66,14 @@ jobs:
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_memory.py
|
||||
- name: Run update_protobuf.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_protobuf.py
|
||||
- name: Run update_sleipnir.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_sleipnir.py
|
||||
- name: Add untracked files to index so they count as changes
|
||||
run: git add -A
|
||||
- name: Check output
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -205,6 +205,7 @@ NO
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
CMakeSettings.json
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
|
||||
@@ -10,6 +10,7 @@ cppSrcFileInclude {
|
||||
}
|
||||
|
||||
modifiableFileExclude {
|
||||
cmake/toolchains/
|
||||
\.patch$
|
||||
gradlew
|
||||
}
|
||||
@@ -19,6 +20,7 @@ generatedFileExclude {
|
||||
simulation/gz_msgs/src/include/simulation/gz_msgs/msgs\.h$
|
||||
fieldImages/src/main/native/resources/
|
||||
apriltag/src/test/resources/
|
||||
wpilibc/src/generated/
|
||||
}
|
||||
|
||||
repoRootNameOverride {
|
||||
@@ -29,8 +31,9 @@ includeOtherLibs {
|
||||
^Eigen/
|
||||
^cameraserver/
|
||||
^cscore
|
||||
^drake/
|
||||
^fmt/
|
||||
^gtest/
|
||||
^google/
|
||||
^hal/
|
||||
^imgui
|
||||
^implot
|
||||
|
||||
334
CMakeLists.txt
334
CMakeLists.txt
@@ -1,25 +1,33 @@
|
||||
# Disable in-source builds to prevent source tree corruption.
|
||||
if(" ${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL " ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
message(FATAL_ERROR "
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: In-source builds are not allowed.
|
||||
You should create a separate directory for build files.
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
set(CMAKE_SYSTEM_VERSION 10.0.18362.0 CACHE STRING INTERNAL FORCE)
|
||||
set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION 10.0.18362.0 CACHE STRING INTERNAL FORCE)
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
project(allwpilib)
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
# Make timestamps of extracted files from FetchContent the time of extraction
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
message(STATUS "Platform version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
|
||||
|
||||
set(WPILIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
INCLUDE(CPack)
|
||||
include(CPack)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
@@ -30,31 +38,33 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/bin)
|
||||
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${WPILIB_BINARY_DIR}/jar)
|
||||
|
||||
# use, i.e. don't skip the full RPATH for the build tree
|
||||
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
set(CMAKE_SKIP_BUILD_RPATH FALSE)
|
||||
|
||||
# when building, don't use the install RPATH already
|
||||
# (but later on when installing)
|
||||
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
|
||||
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
|
||||
# add the automatically determined parts of the RPATH
|
||||
# which point to directories outside the build tree to the install RPATH
|
||||
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
# the RPATH to be used when installing, but only if it's not a system directory
|
||||
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
|
||||
IF("${isSystemDir}" STREQUAL "-1")
|
||||
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
ENDIF("${isSystemDir}" STREQUAL "-1")
|
||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
|
||||
if("${isSystemDir}" STREQUAL "-1")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
endif()
|
||||
|
||||
# Options for building certain parts of the repo. Everything is built by default.
|
||||
option(BUILD_SHARED_LIBS "Build with shared libs (needed for JNI)" ON)
|
||||
option(WITH_JAVA "Include java and JNI in the build" ON)
|
||||
option(WITH_JAVA "Include Java and JNI in the build" ON)
|
||||
option(WITH_JAVA_SOURCE "Build Java source jars" ${WITH_JAVA})
|
||||
option(WITH_CSCORE "Build cscore (needs OpenCV)" ON)
|
||||
option(WITH_NTCORE "Build ntcore" ON)
|
||||
option(WITH_WPIMATH "Build wpimath" ON)
|
||||
option(WITH_WPILIB "Build hal, wpilibc/j, and myRobot (needs OpenCV)" ON)
|
||||
option(WITH_WPIUNITS "Build wpiunits" ON)
|
||||
option(WITH_WPILIB "Build hal, wpilibc/j, and developerRobot (needs OpenCV)" ON)
|
||||
option(WITH_EXAMPLES "Build examples" OFF)
|
||||
option(WITH_TESTS "Build unit tests (requires internet connection)" ON)
|
||||
option(WITH_GUI "Build GUI items" ON)
|
||||
@@ -69,136 +79,157 @@ option(USE_SYSTEM_FMTLIB "Use system fmtlib" OFF)
|
||||
option(USE_SYSTEM_LIBUV "Use system libuv" OFF)
|
||||
option(USE_SYSTEM_EIGEN "Use system eigen" OFF)
|
||||
|
||||
# Options for installation.
|
||||
option(WITH_FLAT_INSTALL "Use a flat install directory" OFF)
|
||||
|
||||
# Options for location of OpenCV Java.
|
||||
set(OPENCV_JAVA_INSTALL_DIR "" CACHE PATH "Location to search for the OpenCV jar file")
|
||||
|
||||
# Options for compilation flags.
|
||||
option(NO_WERROR "Disable -Werror flag during compilation" OFF)
|
||||
|
||||
# Set default build type to release with debug info (i.e. release mode optimizations
|
||||
# are performed, but debug info still exists).
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
# We always want flat install with MSVC.
|
||||
if (MSVC)
|
||||
set(WITH_FLAT_INSTALL ON)
|
||||
endif()
|
||||
|
||||
if (WITH_JAVA AND NOT BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "
|
||||
if(WITH_JAVA AND NOT BUILD_SHARED_LIBS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build static libs with Java enabled.
|
||||
Static libs requires both BUILD_SHARED_LIBS=OFF and
|
||||
WITH_JAVA=OFF
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (WITH_SIMULATION_MODULES AND NOT BUILD_SHARED_LIBS)
|
||||
message(FATAL_ERROR "
|
||||
if(WITH_SIMULATION_MODULES AND NOT BUILD_SHARED_LIBS)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build static libs with simulation modules enabled.
|
||||
Static libs requires both BUILD_SHARED_LIBS=OFF and
|
||||
WITH_SIMULATION_MODULES=OFF
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_JAVA OR NOT WITH_CSCORE)
|
||||
if(NOT WITH_JAVA OR NOT WITH_CSCORE)
|
||||
if(NOT "${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
|
||||
message(WARNING "
|
||||
message(
|
||||
WARNING
|
||||
"
|
||||
WARNING: OpenCV Java dir set but java is not enabled!
|
||||
It will be ignored.
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT WITH_WPILIB AND WITH_SIMULATION_MODULES)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_WPILIB AND WITH_SIMULATION_MODULES)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build simulation modules with wpilib disabled.
|
||||
Enable wpilib by setting WITH_WPILIB=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_CSCORE)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_CSCORE)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build cameraserver without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_GUI)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_GUI)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build GUI modules without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_SIMULATION_MODULES)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_SIMULATION_MODULES)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build simulation modules without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_NTCORE AND WITH_WPILIB)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_NTCORE AND WITH_WPILIB)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build wpilib without ntcore.
|
||||
Enable ntcore by setting WITH_NTCORE=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT WITH_WPIMATH AND WITH_WPILIB)
|
||||
message(FATAL_ERROR "
|
||||
if(NOT WITH_WPIMATH AND WITH_WPILIB)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build wpilib without wpimath.
|
||||
Enable wpimath by setting WITH_WPIMATH=ON
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
set( wpilib_dest "")
|
||||
set( include_dest include )
|
||||
set( main_lib_dest lib )
|
||||
set( java_lib_dest java )
|
||||
set( jni_lib_dest jni )
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (wpilib_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (wpilib_config_dir share/wpilib)
|
||||
if(NOT WITH_WPIUNITS AND WITH_WPIMATH AND WITH_JAVA)
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"
|
||||
FATAL: Cannot build Java wpimath without wpiunits.
|
||||
Enable wpiunits by setting WITH_WPIUNITS=ON or disable the Java build by setting WITH_JAVA=OFF
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (USE_SYSTEM_LIBUV)
|
||||
set (LIBUV_SYSTEM_REPLACE "
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(libuv REQUIRED IMPORTED_TARGET libuv)
|
||||
")
|
||||
set(include_dest include)
|
||||
set(java_lib_dest java)
|
||||
set(jni_lib_dest jni)
|
||||
if(WITH_JAVA)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
endif()
|
||||
|
||||
if (USE_SYSTEM_EIGEN)
|
||||
set (EIGEN_SYSTEM_REPLACE "find_package(Eigen3 CONFIG)")
|
||||
if(USE_SYSTEM_LIBUV)
|
||||
set(LIBUV_SYSTEM_REPLACE
|
||||
"
|
||||
find_dependency(libuv CONFIG)
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(USE_SYSTEM_EIGEN)
|
||||
set(EIGEN_SYSTEM_REPLACE "find_package(Eigen3 CONFIG)")
|
||||
endif()
|
||||
|
||||
find_package(LIBSSH 0.7.1)
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set(WPIUTIL_DEP_REPLACE "include($\{SELF_DIR\}/wpiutil-config.cmake)")
|
||||
set(WPINET_DEP_REPLACE "include($\{SELF_DIR\}/wpinet-config.cmake)")
|
||||
set(NTCORE_DEP_REPLACE "include($\{SELF_DIR\}/ntcore-config.cmake)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cscore-config.cmake)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cameraserver-config.cmake)")
|
||||
set(HAL_DEP_REPLACE_IMPL "include(\${SELF_DIR}/hal-config.cmake)")
|
||||
set(WPIMATH_DEP_REPLACE "include($\{SELF_DIR\}/wpimath-config.cmake)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "include(\${SELF_DIR}/wpilibc-config.cmake)")
|
||||
set(WPILIBNEWCOMMANDS_DEP_REPLACE "include(\${SELF_DIR}/wpilibNewcommands-config.cmake)")
|
||||
else()
|
||||
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
|
||||
set(WPINET_DEP_REPLACE "find_dependency(wpinet)")
|
||||
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
set(APRILTAG_DEP_REPLACE "find_dependency(apriltag)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
|
||||
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
|
||||
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
|
||||
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
|
||||
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
|
||||
set(WPILIBJ_DEP_REPLACE "find_dependency(wpilibj)")
|
||||
set(WPILIBNEWCOMMANDS_DEP_REPLACE "find_dependency(wpilibNewCommands)")
|
||||
endif()
|
||||
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
|
||||
set(WPINET_DEP_REPLACE "find_dependency(wpinet)")
|
||||
set(WPIUNITS_DEP_REPLACE "find_dependency(wpiunits)")
|
||||
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
|
||||
|
||||
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
|
||||
set(SELF_DIR "$\{SELF_DIR\}")
|
||||
@@ -216,7 +247,15 @@ if(isMultiConfig)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES Ubsan)
|
||||
endif()
|
||||
else()
|
||||
set(allowedBuildTypes Asan Tsan Ubsan Debug Release RelWithDebInfo MinSizeRel)
|
||||
set(allowedBuildTypes
|
||||
Asan
|
||||
Tsan
|
||||
Ubsan
|
||||
Debug
|
||||
Release
|
||||
RelWithDebInfo
|
||||
MinSizeRel
|
||||
)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")
|
||||
|
||||
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
|
||||
@@ -225,54 +264,90 @@ else()
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS_ASAN
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C compiler for Asan build type or configuration." FORCE)
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler for Asan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_ASAN
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C++ compiler for Asan build type or configuration." FORCE)
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler for Asan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_ASAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
|
||||
"Linker flags to be used to create executables for Asan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create executables for Asan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ASAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Asan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create shared libraries for Asan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS_TSAN
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C compiler for Tsan build type or configuration." FORCE)
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler for Tsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_TSAN
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C++ compiler for Tsan build type or configuration." FORCE)
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler for Tsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_TSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread" CACHE STRING
|
||||
"Linker flags to be used to create executables for Tsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create executables for Tsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_TSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread" CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Tsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create shared libraries for Tsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS_UBSAN
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C compiler for Ubsan build type or configuration." FORCE)
|
||||
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C compiler for Ubsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_UBSAN
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING
|
||||
"Flags used by the C++ compiler for Ubsan build type or configuration." FORCE)
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer"
|
||||
CACHE STRING
|
||||
"Flags used by the C++ compiler for Ubsan build type or configuration."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_UBSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all" CACHE STRING
|
||||
"Linker flags to be used to create executables for Ubsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create executables for Ubsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_UBSAN
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined" CACHE STRING
|
||||
"Linker lags to be used to create shared libraries for Ubsan build type." FORCE)
|
||||
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined"
|
||||
CACHE STRING
|
||||
"Linker flags to be used to create shared libraries for Ubsan build type."
|
||||
FORCE
|
||||
)
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(googletest)
|
||||
include(GoogleTest)
|
||||
@@ -280,54 +355,65 @@ endif()
|
||||
|
||||
add_subdirectory(wpiutil)
|
||||
|
||||
if (WITH_NTCORE)
|
||||
if(WITH_NTCORE)
|
||||
add_subdirectory(wpinet)
|
||||
add_subdirectory(ntcore)
|
||||
endif()
|
||||
|
||||
if (WITH_WPIMATH)
|
||||
if(WITH_WPIMATH)
|
||||
if(WITH_JAVA)
|
||||
add_subdirectory(wpiunits)
|
||||
endif()
|
||||
add_subdirectory(wpimath)
|
||||
endif()
|
||||
|
||||
if (WITH_GUI)
|
||||
if(WITH_WPIUNITS AND NOT WITH_WPIMATH)
|
||||
# In case of building wpiunits standalone
|
||||
add_subdirectory(wpiunits)
|
||||
endif()
|
||||
|
||||
if(WITH_GUI)
|
||||
add_subdirectory(fieldImages)
|
||||
add_subdirectory(imgui)
|
||||
add_subdirectory(wpigui)
|
||||
add_subdirectory(glass)
|
||||
add_subdirectory(outlineviewer)
|
||||
if (LIBSSH_FOUND)
|
||||
add_subdirectory(sysid)
|
||||
if(LIBSSH_FOUND)
|
||||
add_subdirectory(roborioteamnumbersetter)
|
||||
add_subdirectory(datalogtool)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_WPILIB OR WITH_SIMULATION_MODULES)
|
||||
if(WITH_WPILIB OR WITH_SIMULATION_MODULES)
|
||||
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(hal)
|
||||
endif()
|
||||
|
||||
if (WITH_CSCORE)
|
||||
if(WITH_CSCORE)
|
||||
set(CSCORE_DEP_REPLACE ${CSCORE_DEP_REPLACE_IMPL})
|
||||
set(CAMERASERVER_DEP_REPLACE ${CAMERASERVER_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(cscore)
|
||||
add_subdirectory(cameraserver)
|
||||
endif()
|
||||
|
||||
if (WITH_WPILIB)
|
||||
if(WITH_WPILIB)
|
||||
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(apriltag)
|
||||
add_subdirectory(wpilibj)
|
||||
add_subdirectory(wpilibc)
|
||||
add_subdirectory(wpilibNewCommands)
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory(romiVendordep)
|
||||
add_subdirectory(xrpVendordep)
|
||||
if(WITH_EXAMPLES)
|
||||
add_subdirectory(wpilibcExamples)
|
||||
endif()
|
||||
add_subdirectory(myRobot)
|
||||
add_subdirectory(developerRobot)
|
||||
endif()
|
||||
|
||||
if (WITH_SIMULATION_MODULES AND NOT WITH_EXTERNAL_HAL)
|
||||
if(WITH_SIMULATION_MODULES AND NOT WITH_EXTERNAL_HAL)
|
||||
add_subdirectory(simulation)
|
||||
endif()
|
||||
|
||||
configure_file(wpilib-config.cmake.in ${WPILIB_BINARY_DIR}/wpilib-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/wpilib-config.cmake DESTINATION ${wpilib_config_dir})
|
||||
configure_file(wpilib-config.cmake.in ${WPILIB_BINARY_DIR}/wpilib-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/wpilib-config.cmake DESTINATION share/wpilib)
|
||||
|
||||
@@ -12,11 +12,11 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
|
||||
## General Contribution Rules
|
||||
|
||||
- Everything in the library must work for the 3000+ teams that will be using it.
|
||||
- Everything in the library must work for the 4000+ teams that will be using it.
|
||||
- We need to be able to maintain submitted changes, even if you are no longer working on the project.
|
||||
- Tool suite changes must be generally useful to a broad range of teams
|
||||
- Excluding bug fixes, changes in one language generally need to have corresponding changes in other languages.
|
||||
- Some features, such the addition of C++11 for WPILibC or Functional Interfaces for WPILibJ, are specific to that version of WPILib only.
|
||||
- Some features, such the addition of C++23 for WPILibC or Functional Interfaces for WPILibJ, are specific to that version of WPILib only. New language features added to C++ must be wrappable in Python for [RobotPy](https://github.com/robotpy).
|
||||
- Substantial changes often need to have corresponding LabVIEW changes. To do this, we will work with NI on these large changes.
|
||||
- Changes should have tests.
|
||||
- Code should be well documented.
|
||||
@@ -27,7 +27,8 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
- Bug reports and fixes
|
||||
- We will generally accept bug fixes without too much question. If they are only implemented for one language, we will implement them for any other necessary languages. Bug reports are also welcome, please submit them to our GitHub issue tracker.
|
||||
- While we do welcome improvements to the API, there are a few important rules to consider:
|
||||
- Features must be added to both WPILibC and WPILibJ, with rare exceptions.
|
||||
- Features must be added to Java (WPILibJ), C++ (WPILibC), with rare exceptions.
|
||||
- Most of Python (RobotPy) is created by wrapping WPILibC with pybind11 via robotpy-build. However, new features to the command framework should also be submitted to [robotpy-commands-v2](https://github.com/robotpy/robotpy-commands-v2) as the command framework is reimplemented in Python.
|
||||
- During competition season, we will not merge any new feature additions. We want to ensure that the API is stable during the season to help minimize issues for teams.
|
||||
- Ask about large changes before spending a bunch of time on them! You can create a new issue on our GitHub tracker for feature request/discussion and talk about it with us there.
|
||||
- Features that make it easier for teams with less experience to be more successful are more likely to be accepted.
|
||||
@@ -79,6 +80,8 @@ xₖ₊₁ = Axₖ + Buₖ
|
||||
|
||||
Changes should be submitted as a Pull Request against the main branch of WPILib. For most changes, commits will be squashed upon merge. For particularly large changes, multiple commits are ok, but assume one commit unless asked otherwise. We may ask you to break a PR into multiple standalone PRs or commits for rebase within one PR to separate unrelated changes. No change will be merged unless it is up to date with the current main branch. We do this to make sure that the git history isn't too cluttered.
|
||||
|
||||
During the build season, breaking changes or other changes intended for the next season can be created as a pull request against the development branch of WPILib. After the season is over, the changes in the development branch will be merged into main.
|
||||
|
||||
### Merge Process
|
||||
|
||||
When you first submit changes, GitHub Actions will attempt to run `./gradlew check` on your change. If this fails, you will need to fix any issues that it sees. Once Actions passes, we will begin the review process in more earnest. One or more WPILib team members will review your change. This will be a back-and-forth process with the WPILib team and the greater community. Once we are satisfied that your change is ready, we will allow our hosted instance to test it. This will run the full gamut of checks, including integration tests on actual hardware. Once all tests have passed and the team is satisfied, we will merge your change into the WPILib repository.
|
||||
|
||||
@@ -4,17 +4,22 @@ This article contains instructions on building projects using a development buil
|
||||
|
||||
**Note:** This only applies to Java/C++ teams.
|
||||
|
||||
> [!WARNING]
|
||||
> **There are no stability or compatibility guarantees for builds outside of [tagged releases](https://github.com/wpilibsuite/allwpilib/releases). Changes may not be fully documented. Use them at your own risk!**
|
||||
>
|
||||
> Development builds may be non-functional between the end of the season and the start of beta testing. Development builds are also likely to be incompatible with vendor libraries during this time.
|
||||
|
||||
## Development Build
|
||||
|
||||
Development builds are the per-commit build hosted every time a commit is pushed to the [allwpilib](https://github.com/wpilibsuite/allwpilib/) repository. These builds are then hosted on [artifactory](https://frcmaven.wpi.edu/artifactory/webapp/#/home).
|
||||
|
||||
To build a project using a development build, find the build.gradle file and open it. Then, add the following code below the plugin section and replace YEAR with the year of the development version. It is also necessary to use a 2023 GradleRIO version, ie `2023.0.0-alpha-1`
|
||||
To build a project using a development build, find the build.gradle file and open it. Then, add the following code below the plugin section and replace YEAR with the year of the development version. It is also necessary to use a 2024 GradleRIO version, ie `2024.0.0-alpha-1`
|
||||
|
||||
```groovy
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useDevelopment = true
|
||||
wpi.versions.wpilibVersion = 'YEAR.+'
|
||||
wpi.versions.wpimathVersion = 'YEAR.+
|
||||
wpi.versions.wpimathVersion = 'YEAR.+'
|
||||
```
|
||||
|
||||
The top of your ``build.gradle`` file should now look similar to the code below. Ignore any differences in versions.
|
||||
@@ -23,13 +28,13 @@ Java
|
||||
```groovy
|
||||
plugins {
|
||||
id "java"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
id "edu.wpi.first.GradleRIO" version "2024.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useDevelopment = true
|
||||
wpi.versions.wpilibVersion = '2023.+'
|
||||
wpi.versions.wpimathVersion = '2023.+'
|
||||
wpi.versions.wpilibVersion = '2024.+'
|
||||
wpi.versions.wpimathVersion = '2024.+'
|
||||
```
|
||||
|
||||
C++
|
||||
@@ -37,13 +42,13 @@ C++
|
||||
plugins {
|
||||
id "cpp"
|
||||
id "google-test-test-suite"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
id "edu.wpi.first.GradleRIO" version "2024.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useDevelopment = true
|
||||
wpi.versions.wpilibVersion = '2023.+'
|
||||
wpi.versions.wpimathVersion = '2023.+'
|
||||
wpi.versions.wpilibVersion = '2024.+'
|
||||
wpi.versions.wpimathVersion = '2024.+'
|
||||
```
|
||||
|
||||
### Development Build Documentation
|
||||
@@ -59,7 +64,7 @@ Java
|
||||
```groovy
|
||||
plugins {
|
||||
id "java"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
id "edu.wpi.first.GradleRIO" version "2024.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
@@ -73,7 +78,7 @@ C++
|
||||
plugins {
|
||||
id "cpp"
|
||||
id "google-test-test-suite"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
id "edu.wpi.first.GradleRIO" version "2024.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
@@ -84,15 +89,4 @@ wpi.versions.wpimathVersion = 'YEAR.424242.+'
|
||||
|
||||
# roboRIO Development
|
||||
|
||||
This repo contains a myRobot project built in way to do full project development without needing to do a full publish into GradleRIO. These also only require building the minimum amount of binaries for the roboRIO, so the builds are much faster as well.
|
||||
|
||||
The setup only works if the roboRIO is USB connected. If an alternate IP address is preferred, the `address` block in myRobot\build.gradle can be changed to point to another address.
|
||||
|
||||
The following 3 tasks can be used for deployment:
|
||||
* `:myRobot:deployShared` deploys the C++ project using shared dependencies. Prefer this one for most C++ development.
|
||||
* `:myRobot:deployStatic` deploys the C++ project with all dependencies statically linked.
|
||||
* `:myRobot:deployJava` deploys the Java project and all required dependencies. Also installs the JRE if not currently installed.
|
||||
|
||||
Deploying any of these to the roboRIO will disable the current startup project until it is redeployed.
|
||||
|
||||
From here, ssh into the roboRIO using the `lvuser` account and run `frcRunRobot.sh` (It's in path).
|
||||
See the [developerRobot](developerRobot/README.md) subproject.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2022 FIRST and other WPILib contributors
|
||||
Copyright (c) 2009-2024 FIRST and other WPILib contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## Publishing Third Party Dependencies
|
||||
Currently the 3rd party deps are imgui, opencv, and google test
|
||||
Currently the 3rd party deps are imgui, opencv, google test, libssh, and apriltaglib
|
||||
|
||||
For publishing these dependencies, the version needs to be manually updated in the publish.gradle file of their respective repository.
|
||||
Then, in the azure build for the dependency you want to build for, manually start a pipeline build (As of current, this is the `Run Pipeline` button).
|
||||
@@ -18,10 +18,10 @@ Desktop tools publish to the development repo on every push to main. To publish
|
||||
|
||||
## Publishing VS Code
|
||||
Before publishing, make sure to update the gradlerio version in `vscode-wpilib/resources/gradle/version.txt` Also make sure the gradle wrapper version matches the wrapper required by gradlerio.
|
||||
Upon pushing a tag, a release will be built, and the files will be uploaded to the releases on GitHub. For publishing to the marketplace, you need a Microsoft account and to be added as a maintainer.
|
||||
Upon pushing a tag, a release will be built, and the files will be uploaded to the releases on GitHub.
|
||||
|
||||
## Publishing GradleRIO
|
||||
Before publishing, make sure to update the version in build.gradle. Publishing must happen locally, using the command `./gradlew publishPlugin`. This does require your API key for publishing to be set.
|
||||
|
||||
## Building the installer
|
||||
Update the GradleRIO version in gradle.properties, and in the scripts folder in vscode, update the vscode extension. Then push, it will build the installer on azure.
|
||||
Update the GradleRIO version in gradle.properties, and in the scripts folder in vscode, update the vscode extension. To publish a release build, upload a new tag, and a release will automatically be built and published to artifactory and cloudflare.
|
||||
|
||||
@@ -16,7 +16,7 @@ We provide two base types of artifacts.
|
||||
|
||||
The first types are Java artifacts. These are usually published as `jar` files. Usually, the actual jar file is published with no classifier. The sources are published with the `-sources` classifier, and the javadocs are published with the `-javadoc` classifier.
|
||||
|
||||
The second types are native artifacts. These are usually published as `zip` files (except for the `JNI` artifact types, which are `jar` files. See below for information on this). The `-sources` and `-headers` classifiers contain the sources and headers respecively for the library. Each artifact also contains a classifier for each platform we publish. This platform is in the format `{os}{arch}`. The platform artifact only contains the binaries for a specific platform. In addition, we provide a `-all` classifier. This classifer combines all of the platform artifacts into a single artifact. This is useful for tools that cannot determine what version to use during builds. However, we recommend using the platform specific classifier when possible. Note that the binary artifacts never contain the headers, you always need the `-headers` classifier to get those.
|
||||
The second types are native artifacts. These are usually published as `zip` files (except for the `JNI` artifact types, which are `jar` files. See below for information on this). The `-sources` and `-headers` classifiers contain the sources and headers respectively for the library. Each artifact also contains a classifier for each platform we publish. This platform is in the format `{os}{arch}`. The platform artifact only contains the binaries for a specific platform. In addition, we provide a `-all` classifier. This classifier combines all of the platform artifacts into a single artifact. This is useful for tools that cannot determine what version to use during builds. However, we recommend using the platform specific classifier when possible. Note that the binary artifacts never contain the headers, you always need the `-headers` classifier to get those.
|
||||
|
||||
## Artifact Names
|
||||
|
||||
@@ -145,6 +145,11 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* wpinet
|
||||
* wpiutil
|
||||
|
||||
* wpiunits
|
||||
|
||||
* apriltag
|
||||
* wpiutil
|
||||
* wpimath
|
||||
|
||||
### Third Party Artifacts
|
||||
|
||||
@@ -152,6 +157,7 @@ This repository provides the builds of the following third party software.
|
||||
|
||||
All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
|
||||
|
||||
* apriltaglib
|
||||
* googletest
|
||||
* imgui
|
||||
* opencv
|
||||
|
||||
153
README-CMAKE.md
153
README-CMAKE.md
@@ -1,25 +1,41 @@
|
||||
# WPILib CMake Support
|
||||
|
||||
WPILib is normally built with Gradle, however for some systems, such as Linux based coprocessors, Gradle doesn't work correctly, especially if cscore is needed, which requires OpenCV. Furthermore, the CMake build can be used for C++ development because it provides better build caching compared to Gradle. We provide the CMake build for these cases. Although it is supported on Windows, these docs will only go over Linux builds.
|
||||
WPILib is normally built with Gradle, however for some systems, such as Linux based coprocessors, Gradle doesn't work correctly, especially if cscore is needed, which requires OpenCV. Furthermore, the CMake build can be used for C++ development because it provides better build caching compared to Gradle. We provide the CMake build for these cases. Although macOS is supported, these docs will only go over Linux and Windows builds, but should mostly work for macOS as well. If you are stuck, you can look at the GitHub workflows for any OS to see how it works.
|
||||
|
||||
## Libraries that get built
|
||||
* wpiutil
|
||||
* ntcore
|
||||
* cscore
|
||||
* apriltag
|
||||
* cameraserver
|
||||
* hal
|
||||
* wpilib
|
||||
* halsim
|
||||
* cscore
|
||||
* hal (simulation HAL only)
|
||||
* ntcore
|
||||
* romiVendordep
|
||||
* simulation extensions
|
||||
* wpigui
|
||||
* wpilib (wpilibc, wpilibj, and myRobot)
|
||||
* wpilibNewCommands
|
||||
* wpimath
|
||||
* wpinet
|
||||
* wpiunits
|
||||
* wpiutil
|
||||
* xrpVendordep
|
||||
|
||||
By default, all libraries except for the HAL and WPILib get built with a default CMake setup. The libraries are built as shared libraries, and include the JNI libraries as well as building the Java JARs.
|
||||
## GUI apps that get built
|
||||
* datalogtool
|
||||
* glass
|
||||
* outlineviewer
|
||||
* roborioteamnumbersetter
|
||||
* sysid
|
||||
* halsim_gui (if simulation extensions are enabled)
|
||||
|
||||
By default, all libraries get built with a default CMake setup. The libraries are built as shared libraries, and include the JNI libraries as well as building the Java JARs. Data Log Tool and the roboRIO Team Number Setter are only built if libssh is available.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The most common prerequisite is going to be OpenCV. OpenCV needs to be findable by CMake. On systems like the Jetson, this is installed by default. Otherwise, you will need to build OpenCV from source and install it.
|
||||
The protobuf library and compiler are needed for protobuf generation.
|
||||
|
||||
In addition, if you want JNI and Java, you will need a JDK of at least version 11 installed. In addition, you need a `JAVA_HOME` environment variable set properly and set to the JDK directory.
|
||||
OpenCV needs to be findable by CMake. On systems like the Jetson, this is installed by default. Otherwise, you will need to build OpenCV from source and install it.
|
||||
|
||||
If you want JNI and Java, you will need a JDK of at least version 17 installed. In addition, you need a `JAVA_HOME` environment variable set properly and set to the JDK directory.
|
||||
|
||||
If you are building with unit tests or simulation modules, you will also need an Internet connection for the initial setup process, as CMake will clone google-test and imgui from GitHub.
|
||||
|
||||
@@ -27,32 +43,38 @@ If you are building with unit tests or simulation modules, you will also need an
|
||||
|
||||
The following build options are available:
|
||||
|
||||
* `WITH_JAVA` (ON Default)
|
||||
* This option will enable Java and JNI builds. If this is on, `WITH_SHARED_LIBS` must be on. Otherwise CMake will error.
|
||||
* `WITH_SHARED_LIBS` (ON Default)
|
||||
* This option will cause cmake to build static libraries instead of shared libraries. If this is off, `WITH_JAVA` must be off. Otherwise CMake will error.
|
||||
* `BUILD_SHARED_LIBS` (ON Default)
|
||||
* This option will cause CMake to build static libraries instead of shared libraries. If this is off, `WITH_JAVA` must be off. Otherwise CMake will error.
|
||||
* `WITH_CSCORE` (ON Default)
|
||||
* This option will cause cscore to be built. Turning this off will implicitly disable cameraserver, the hal and wpilib as well, irrespective of their specific options. If this is off, the OpenCV build requirement is removed.
|
||||
* This option will cause cscore to be built. Turning this off will implicitly disable cameraserver. If this is off, the OpenCV build requirement is removed.
|
||||
* `WITH_EXAMPLES` (OFF Default)
|
||||
* This option will build C++ examples.
|
||||
* `WITH_GUI` (ON Default)
|
||||
* This option will build GUI items. If this is off, and `WITH_SIMULATION_MODULES` is on, the simulation GUI will not be built.
|
||||
* `WITH_JAVA` (ON Default)
|
||||
* This option will enable Java and JNI builds. If this is on, `BUILD_SHARED_LIBS` must be on. Otherwise CMake will error.
|
||||
* `WITH_JAVA_SOURCE` (`WITH_JAVA` Default)
|
||||
* This option will build Java source JARs for each enabled Java library. This does not require `WITH_JAVA` to be on, allowing source JARs to be built without the compiled JARs if desired.
|
||||
* `WITH_NTCORE` (ON Default)
|
||||
* This option will cause ntcore to be built. Turning this off will implicitly disable wpinet and wpilib as well, irrespective of their specific options.
|
||||
* This option will cause ntcore to be built. Turning this off will implicitly disable wpinet, and will cause an error if `WITH_WPILIB` is enabled.
|
||||
* `WITH_SIMULATION_MODULES` (ON Default)
|
||||
* This option will build simulation modules.
|
||||
* `WITH_TESTS` (ON Default)
|
||||
* This option will build C++ unit tests. These can be run via `ctest -C <config>`, where `<config>` is the build configuration, e.g. `Debug` or `Release`.
|
||||
* `WITH_WPILIB` (ON Default)
|
||||
* This option will build the HAL and wpilibc/j during the build. The HAL is the simulation HAL, unless the external HAL options are used. The CMake build has no capability to build for the roboRIO.
|
||||
* `WITH_WPIMATH` (ON Default)
|
||||
* This option will build the wpimath library. This option must be on to build wpilib.
|
||||
* `WITH_WPILIB` (ON Default)
|
||||
* This option will build the hal and wpilibc/j during the build. The HAL is the simulator hal, unless the external hal options are used. The cmake build has no capability to build for the RoboRIO.
|
||||
* `WITH_EXAMPLES` (ON Default)
|
||||
* This option will build C++ examples.
|
||||
* `WITH_TESTS` (ON Default)
|
||||
* This option will build C++ unit tests. These can be run via `make test`.
|
||||
* `WITH_GUI` (ON Default)
|
||||
* This option will build GUI items.
|
||||
* `WITH_SIMULATION_MODULES` (ON Default)
|
||||
* This option will build simulation modules, including wpigui and the HALSim plugins.
|
||||
* `WITH_WPIUNITS` (ON Default)
|
||||
* This option will build the wpiunits library. This option must be on to build the Java wpimath library and requires `WITH_JAVA` to also be on.
|
||||
* `WITH_EXTERNAL_HAL` (OFF Default)
|
||||
* TODO
|
||||
* This option will build wpilib with an externally built HAL.
|
||||
* `EXTERNAL_HAL_FILE`
|
||||
* TODO
|
||||
* Set this option to the CMake File of the externally built HAL. NOTE: set it to the file itself, not the folder the file is located in!
|
||||
* `OPENCV_JAVA_INSTALL_DIR`
|
||||
* Set this option to the location of the archive of the OpenCV Java bindings (it should be called opencv-xxx.jar, with the x'es being version numbers). NOTE: set it to the LOCATION of the file, not the file itself!
|
||||
* `NO_WERROR` (OFF Default)
|
||||
* This option will disable the `-Werror` compilation flag for non-MSVC builds.
|
||||
|
||||
## Build Setup
|
||||
|
||||
@@ -66,24 +88,28 @@ cmake path/to/allwpilib/root
|
||||
|
||||
If you want to change any of the options, add `-DOPTIONHERE=VALUE` to the `cmake` command. This will check for any dependencies. If everything works properly this will succeed. If not, please check out the troubleshooting section for help.
|
||||
|
||||
If you want, you can also use `ccmake` in order to visually set these properties as well. [Here](https://cmake.org/cmake/help/v3.0/manual/ccmake.1.html) is the link to the documentation for that program.
|
||||
If you want, you can also use `ccmake` in order to visually set these properties as well. [Here](https://cmake.org/cmake/help/v3.0/manual/ccmake.1.html) is the link to the documentation for that program. On Windows, you can use `cmake-gui` instead.
|
||||
|
||||
Note that if you are cross-compiling, you will need to override the protobuf options manually to point to the libraries for the target platform. Leave the protoc binary location as the path to the binary for the host platform, since protoc needs to execute on the host platform.
|
||||
|
||||
## Building
|
||||
|
||||
Once you have cmake setup. run `make` from the directory you configured CMake in. This will build all libraries possible. If you have a multicore system, we recommend running `make` with multiple jobs. The usual rule of thumb is 1.5x the number of cores you have. To run a multiple job build, run the following command with x being the number of jobs you want.
|
||||
Once you have CMake setup. run `cmake --build .` from the directory you configured CMake in. This will build all libraries possible. We recommend running `cmake --build .` with multiple jobs. For allwpilib, a good rule of thumb is one worker for every 2 GB of available RAM. To run a multiple job build, run the following command with x being the number of jobs you want.
|
||||
|
||||
```
|
||||
make -jx
|
||||
cmake --build . --parallel x
|
||||
```
|
||||
|
||||
The `ninja` generator is also supported, and can be enabled by passing `-GNinja` to the initial `cmake` command.
|
||||
Note: wpimath takes gigabytes of RAM to compile. Because of this, the compilers may crash while building due to a lack of memory and your computer may slow down. If you have less than 16 GB of RAM available, you may want to consider building it separately first by adding `--target wpimath` and running it with ~3 jobs to prevent crashes from running out of memory.
|
||||
|
||||
To build with a certain configuration, like `Debug` or `Release`, add `--config <config>`, where `<config>` is the name of the configuration you want to build with.
|
||||
|
||||
## Installing
|
||||
|
||||
After build, the easiest way to use the libraries is to install them. Run the following command to install the libraries. This will install them so that they can be used from external cmake projects.
|
||||
After build, the easiest way to use the libraries is to install them. Run the following command to install the libraries. This will install them so that they can be used from external CMake projects.
|
||||
|
||||
```
|
||||
sudo make install
|
||||
sudo cmake --build . --target install
|
||||
```
|
||||
|
||||
## Using the installed libraries for C++.
|
||||
@@ -92,8 +118,8 @@ Using the libraries from C++ is the easiest way to use the built libraries.
|
||||
|
||||
To do so, create a new folder to contain your project. Add the following code below to a `CMakeLists.txt` file in that directory.
|
||||
|
||||
```
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
project(vision_app) # Project Name Here
|
||||
|
||||
find_package(wpilib REQUIRED)
|
||||
@@ -102,7 +128,7 @@ add_executable(my_vision_app main.cpp) # executable name as first parameter
|
||||
target_link_libraries(my_vision_app cameraserver ntcore cscore wpiutil)
|
||||
```
|
||||
|
||||
If you are using them, `wpilibc` and `hal` should be added before the `cameraserver` declaration in the `target_link_libraries` function.
|
||||
If you want to use other libraries or are building a robot program, `wpilibc` and `hal` should be added in the `target_link_libraries` function, along with any other libraries you plan on using, e.g. `wpimath`.
|
||||
|
||||
Add a `main.cpp` file to contain your code, and create a build folder. Move into the build folder, and run
|
||||
|
||||
@@ -110,11 +136,43 @@ Add a `main.cpp` file to contain your code, and create a build folder. Move into
|
||||
cmake /path/to/folder/containing/CMakeLists
|
||||
```
|
||||
|
||||
After that, run `make`. That will create your executable. Then you should be able to run `./my_vision_app` to run your application.
|
||||
After that, run `cmake --build .`. That will create your executable. Then you should be able to run `./my_vision_app` to run your application.
|
||||
|
||||
|
||||
## Using the installed libraries for Java
|
||||
TODO
|
||||
|
||||
Using the built JARs is move involved than using the C++ libraries, but mostly consists of adding the correct directories to PATH.
|
||||
|
||||
Add the directory where the JARs are located (e.g, `/usr/local/java`) to PATH. If you are on Windows, you also need to add the `lib`, `bin`, and `share` directories to PATH. Then, create a new folder to contain your project. Add the following code below to a `CMakeLists.txt` file in that directory.
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
project(robot)
|
||||
|
||||
find_package(Java REQUIRED COMPONENTS Development)
|
||||
include(UseJava)
|
||||
find_package(wpilib REQUIRED)
|
||||
find_jar(opencvJar opencv-xxx PATHS ENV PATH) # Change to OpenCV version
|
||||
|
||||
file(GLOB_RECURSE JAVA_SOURCES *.java)
|
||||
# If you want Gradle compatibility or you are using one of the templates/examples, comment out the above line and uncomment this line instead:
|
||||
# file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
add_jar(robot ${JAVA_SOURCES}
|
||||
INCLUDE_JARS apriltag_jar cscore_jar hal_jar ntcore_jar wpilibNewCommands_jar wpimath_jar wpinet_jar wpiutil_jar wpiunits_jar wpilibj_jar ${opencvJar})
|
||||
export_jars(TARGETS robot FILE robot.jar)
|
||||
```
|
||||
This includes all the built JARs except for the vendordeps. If you are not using a JAR/library, you may remove it.
|
||||
Add a `Main.java` file to contain your code, and create a build folder. Move into the build folder, and run
|
||||
|
||||
```
|
||||
cmake /path/to/folder/containing/CMakeLists
|
||||
```
|
||||
|
||||
After that, run `cmake --build .` to create your JAR file. To execute the JAR file, you need to include the wpilib JARs and your JAR in the classpath, and execute your Java program's entry point. If you are using cscore or cameraserver, you also need to include the path to the OpenCV JAR. If you built it from source, it will be in your OpenCV build directory. If it's installed on the system, CMake may find it from PATH, but you will likely need to locate the JAR and manually give CMake the JAR directory. If you are on Linux, you will also need to add the path of the libraries to `LD_LIBRARY_PATH`. This can be done by prepending `LD_LIBRARY_PATH=/path/to/libraries` to the Java command. If you need to add more paths, separate them with colons. The final command should look like `java -cp "robot.jar:/path/to/library_jars/*" main.package.Main`, using a semicolon to separate paths instead of a colon if you are on Windows. If you are on Linux, the final command should look more like `LD_LIBRARY_PATH=/path/to/libraries java -cp robot.jar:/path/to/library_jars/* main.package.Main`.
|
||||
|
||||
## Using vendordeps
|
||||
|
||||
Vendordeps are not included as part of the `wpilib` CMake package. However, if you want to use a vendordep, you need to use `find_package(VENDORDEP)`, where `VENDORDEP` is the name of the vendordep (case-sensitive), like `xrpVendordep` or `romiVenderdep`. Note that wpilibNewCommands, while a vendordep in normal robot projects, is not built as a vendordep in CMake, and is instead included as part of the `wpilib` CMake package. After you used `find_package`, you can reference the vendordep library like normal, either by using `target_link_libraries` for C++ or `add_jar` for Java.
|
||||
|
||||
## Troubleshooting
|
||||
Below are some common issues that are run into when building.
|
||||
@@ -141,7 +199,7 @@ CMake Error at cscore/CMakeLists.txt:3 (find_package):
|
||||
installed.
|
||||
```
|
||||
|
||||
If you get that, you need make sure opencv was installed, and then reattempt to configure. If that doesn't work, set the `OpenCV_DIR` variable to the directory where you built OpenCV.
|
||||
If you get that, you need make sure OpenCV was installed, and then reattempt to configure. If that doesn't work, set the `OpenCV_DIR` variable to the directory where you built OpenCV.
|
||||
|
||||
#### Missing Java
|
||||
|
||||
@@ -155,3 +213,18 @@ CMake Error at /usr/share/cmake-3.5/Modules/FindPackageHandleStandardArgs.cmake:
|
||||
If this happens, make sure you have a JDK of at least version 8 installed, and that your JAVA_HOME variable is set properly to point to the JDK.
|
||||
|
||||
In addition, if you do not need Java, you can disable it with `-DWITH_JAVA=OFF`.
|
||||
|
||||
#### Java: Can't find dependent libraries
|
||||
|
||||
If one of the libraries can't be found, you will get an error similar to this one:
|
||||
|
||||
```
|
||||
java.io.IOException: wpiHaljni could not be loaded from path or an embedded resource.
|
||||
attempted to load for platform /windows/x86-64/
|
||||
Last Load Error:
|
||||
C:\Program Files (x86)\allwpilib\bin\wpiHaljni.dll: Can't find dependent libraries
|
||||
```
|
||||
|
||||
If you get this error, that's usually an indication that not all your libraries are in your PATH. The two libraries that should be in your PATH are OpenCV and protobuf. If the error is coming from cscore, it's likely you're missing OpenCV. Otherwise, it's likely you're missing protobuf.
|
||||
|
||||
Note that Linux will not have this specific type of error, as it will usually tell you the dependent library you are missing. In that case, you most likely need to add the library to `LD_LIBRARY_PATH`.
|
||||
|
||||
52
README.md
52
README.md
@@ -17,13 +17,14 @@ Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WP
|
||||
- [Custom toolchain location](#custom-toolchain-location)
|
||||
- [Formatting/Linting](#formattinglinting)
|
||||
- [CMake](#cmake)
|
||||
- [Running examples in simulation](#running-examples-in-simulation)
|
||||
- [Publishing](#publishing)
|
||||
- [Structure and Organization](#structure-and-organization)
|
||||
- [Contributing to WPILib](#contributing-to-wpilib)
|
||||
- [Contributing to WPILib](./CONTRIBUTING.md)
|
||||
|
||||
## WPILib Mission
|
||||
|
||||
The WPILib Mission is to enable FIRST Robotics teams to focus on writing game-specific software rather than focusing on hardware details - "raise the floor, don't lower the ceiling". We work to enable teams with limited programming knowledge and/or mentor experience to be as successful as possible, while not hampering the abilities of teams with more advanced programming capabilities. We support Kit of Parts control system components directly in the library. We also strive to keep parity between major features of each language (Java, C++, and NI's LabVIEW), so that teams aren't at a disadvantage for choosing a specific programming language. WPILib is an open source project, licensed under the BSD 3-clause license. You can find a copy of the license [here](LICENSE.md).
|
||||
The WPILib Mission is to enable FIRST Robotics teams to focus on writing game-specific software rather than focusing on hardware details - "raise the floor, don't lower the ceiling". We work to enable teams with limited programming knowledge and/or mentor experience to be as successful as possible, while not hampering the abilities of teams with more advanced programming capabilities. We support Kit of Parts control system components directly in the library. We also strive to keep parity between major features of each language (Java, C++, Python, and NI's LabVIEW), so that teams aren't at a disadvantage for choosing a specific programming language. WPILib is an open source project, licensed under the BSD 3-clause license. You can find a copy of the license [here](LICENSE.md).
|
||||
|
||||
# Quick Start
|
||||
|
||||
@@ -40,11 +41,11 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen
|
||||
|
||||
## Requirements
|
||||
|
||||
- [JDK 11](https://adoptium.net/temurin/releases/?version=11)
|
||||
- [JDK 17](https://adoptium.net/temurin/releases/?version=17)
|
||||
- Note that the JRE is insufficient; the full JDK is required
|
||||
- On Ubuntu, run `sudo apt install openjdk-11-jdk`
|
||||
- On Windows, install the JDK 11 .msi from the link above
|
||||
- On macOS, install the JDK 11 .pkg from the link above
|
||||
- On Ubuntu, run `sudo apt install openjdk-17-jdk`
|
||||
- On Windows, install the JDK 17 .msi from the link above
|
||||
- On macOS, install the JDK 17 .pkg from the link above
|
||||
- C++ compiler
|
||||
- On Linux, install GCC 11 or greater
|
||||
- On Windows, install [Visual Studio Community 2022](https://visualstudio.microsoft.com/vs/community/) and select the C++ programming language during installation (Gradle can't use the build tools for Visual Studio)
|
||||
@@ -59,9 +60,9 @@ On macOS ARM, run `softwareupdate --install-rosetta`. This is necessary to be ab
|
||||
|
||||
## Setup
|
||||
|
||||
Clone the WPILib repository and follow the instructions above for installing any required tooling.
|
||||
Clone the WPILib repository and follow the instructions above for installing any required tooling. The build process uses versioning information from git. Downloading the source is not sufficient to run the build.
|
||||
|
||||
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/main/README.md) for wpiformat setup instructions. We use clang-format 14.
|
||||
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/main/README.md) for wpiformat setup instructions.
|
||||
|
||||
## Building
|
||||
|
||||
@@ -87,9 +88,24 @@ If opening from a fresh clone, generated java dependencies will not exist. Most
|
||||
|
||||
`./gradlew build` builds _everything_, which includes debug and release builds for desktop and all installed cross compilers. Many developers don't need or want to build all of this. Therefore, common tasks have shortcuts to only build necessary components for common development and testing tasks.
|
||||
|
||||
`./gradlew testDesktopCpp` and `./gradlew testDesktopJava` will build and run the tests for `wpilibc` and `wpilibj` respectively. They will only build the minimum components required to run the tests.
|
||||
`./gradlew testDesktopCpp` and `./gradlew testDesktopJava` will build and run the tests for `wpilibc` and `wpilibj` respectively. They will only build the minimum components required to run the tests. `./gradlew testDesktop` will run both `testDesktopJava` and `testDesktopCpp`.
|
||||
|
||||
`testDesktopCpp` and `testDesktopJava` tasks also exist for the projects `wpiutil`, `ntcore`, `cscore`, `hal` `wpilibNewCommands` and `cameraserver`. These can be ran with `./gradlew :projectName:task`.
|
||||
`testDesktopCpp`, `testDesktopJava`, and `testDesktop` tasks also exist for the following projects:
|
||||
|
||||
- `apriltag`
|
||||
- `cameraserver`
|
||||
- `cscore`
|
||||
- `hal`
|
||||
- `ntcore`
|
||||
- `wpilibNewCommands`
|
||||
- `wpimath`
|
||||
- `wpinet`
|
||||
- `wpiunits`
|
||||
- `wpiutil`
|
||||
- `romiVendordep`
|
||||
- `xrpVendordep`
|
||||
|
||||
These can be ran with `./gradlew :projectName:task`.
|
||||
|
||||
`./gradlew buildDesktopCpp` and `./gradlew buildDesktopJava` will compile `wpilibcExamples` and `wpilibjExamples` respectively. The results can't be ran, but they can compile.
|
||||
|
||||
@@ -119,7 +135,7 @@ Once a PR has been submitted, formatting can be run in CI by commenting `/format
|
||||
|
||||
#### wpiformat
|
||||
|
||||
wpiformat can be executed anywhere in the repository via `py -3 -m wpiformat -clang 14` on Windows or `python3 -m wpiformat -clang 14` on other platforms.
|
||||
wpiformat can be executed anywhere in the repository via `py -3 -m wpiformat` on Windows or `python3 -m wpiformat` on other platforms.
|
||||
|
||||
#### Java Code Quality Tools
|
||||
|
||||
@@ -131,6 +147,16 @@ If you only want to run the Java autoformatter, run `./gradlew spotlessApply`.
|
||||
|
||||
CMake is also supported for building. See [README-CMAKE.md](README-CMAKE.md).
|
||||
|
||||
## Running examples in simulation
|
||||
|
||||
Examples can be run in simulation with the following command:
|
||||
|
||||
```bash
|
||||
./gradlew wpilibcExamples:runExample
|
||||
./gradlew wpilibjExamples:runExample
|
||||
```
|
||||
where `Example` is the example's folder name.
|
||||
|
||||
## Publishing
|
||||
|
||||
If you are building to test with other dependencies or just want to export the build as a Maven-style dependency, simply run the `publish` task. This task will publish all available packages to ~/releases/maven/development. If you need to publish the project to a different repo, you can specify it with `-Prepo=repo_name`. Valid options are:
|
||||
@@ -153,7 +179,3 @@ The hal directory contains more C++ code meant to run on the roboRIO. HAL is an
|
||||
The upstream_utils directory contains scripts for updating copies of thirdparty code in the repository.
|
||||
|
||||
The [styleguide repository](https://github.com/wpilibsuite/styleguide) contains our style guides for C++ and Java code. Anything submitted to the WPILib project needs to follow the code style guides outlined in there. For details about the style, please see the contributors document [here](CONTRIBUTING.md#coding-guidelines).
|
||||
|
||||
# Contributing to WPILib
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
@@ -41,11 +41,9 @@ Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineP
|
||||
wpilibc/src/main/native/include/trajectory/TrajectoryParameterizer.h
|
||||
wpilibc/src/main/native/cpp/trajectory/TrajectoryParameterizer.cpp
|
||||
Portable File Dialogs wpigui/src/main/native/include/portable-file-dialogs.h
|
||||
Drake wpimath/src/main/native/thirdparty/drake/
|
||||
wpimath/src/test/native/cpp/drake/
|
||||
wpimath/src/test/native/include/drake/
|
||||
V8 export-template wpiutil/src/main/native/include/wpi/SymbolExports.h
|
||||
GCEM wpimath/src/main/native/thirdparty/gcem/include/
|
||||
Sleipnir wpimath/src/main/native/thirdparty/sleipnir
|
||||
|
||||
==============================================================================
|
||||
Google Test License
|
||||
@@ -1069,41 +1067,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
=============
|
||||
Drake Library
|
||||
=============
|
||||
All components of Drake are licensed under the BSD 3-Clause License
|
||||
shown below. Where noted in the source code, some portions may
|
||||
be subject to other permissive, non-viral licenses.
|
||||
|
||||
Copyright 2012-2016 Robot Locomotion Group @ CSAIL
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer. Redistributions
|
||||
in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution. Neither the name of
|
||||
the Massachusetts Institute of Technology nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
=====================
|
||||
Portable File Dialogs
|
||||
=====================
|
||||
@@ -1242,3 +1205,23 @@ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
================
|
||||
2024 Field Image
|
||||
================
|
||||
2024 Field Image from MikLast: https://www.chiefdelphi.com/t/2024-crescendo-top-down-field-renders/447764
|
||||
|
||||
================
|
||||
Sleipnir License
|
||||
================
|
||||
Copyright (c) Sleipnir contributors
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -4,114 +4,156 @@ include(CompileWarnings)
|
||||
include(GenResources)
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
fetchcontent_declare(
|
||||
apriltaglib
|
||||
GIT_REPOSITORY https://github.com/wpilibsuite/apriltag.git
|
||||
GIT_TAG ad31e33d20f9782b7239cb15cde57c56c91383ad
|
||||
GIT_REPOSITORY https://github.com/wpilibsuite/apriltag.git
|
||||
GIT_TAG da208cc38c1b78fe89861616d44c0692e76b6b8b
|
||||
)
|
||||
|
||||
# Don't use apriltag's CMakeLists.txt due to conflicting naming and JNI
|
||||
FetchContent_GetProperties(apriltaglib)
|
||||
fetchcontent_getproperties(apriltaglib)
|
||||
if(NOT apriltaglib_POPULATED)
|
||||
FetchContent_Populate(apriltaglib)
|
||||
fetchcontent_populate(apriltaglib)
|
||||
endif()
|
||||
|
||||
aux_source_directory(${apriltaglib_SOURCE_DIR}/common APRILTAGLIB_COMMON_SRC)
|
||||
file(GLOB TAG_FILES ${apriltaglib_SOURCE_DIR}/tag*.c)
|
||||
set(APRILTAGLIB_SRCS ${apriltaglib_SOURCE_DIR}/apriltag.c ${apriltaglib_SOURCE_DIR}/apriltag_pose.c ${apriltaglib_SOURCE_DIR}/apriltag_quad_thresh.c)
|
||||
set(APRILTAGLIB_SRCS
|
||||
${apriltaglib_SOURCE_DIR}/apriltag.c
|
||||
${apriltaglib_SOURCE_DIR}/apriltag_pose.c
|
||||
${apriltaglib_SOURCE_DIR}/apriltag_quad_thresh.c
|
||||
)
|
||||
|
||||
file(GLOB apriltag_jni_src src/main/native/cpp/jni/AprilTagJNI.cpp)
|
||||
|
||||
if (WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
if(WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
|
||||
set(CMAKE_JNI_TARGET true)
|
||||
set(CMAKE_JNI_TARGET true)
|
||||
|
||||
file(GLOB EJML_JARS "${WPILIB_BINARY_DIR}/wpimath/thirdparty/ejml/*.jar")
|
||||
file(GLOB JACKSON_JARS "${WPILIB_BINARY_DIR}/wpiutil/thirdparty/jackson/*.jar")
|
||||
find_file(OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/share/java
|
||||
NO_DEFAULT_PATH)
|
||||
file(GLOB EJML_JARS "${WPILIB_BINARY_DIR}/wpimath/thirdparty/ejml/*.jar")
|
||||
file(GLOB JACKSON_JARS "${WPILIB_BINARY_DIR}/wpiutil/thirdparty/jackson/*.jar")
|
||||
find_file(
|
||||
OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS
|
||||
${OPENCV_JAVA_INSTALL_DIR}
|
||||
${OpenCV_INSTALL_PATH}/bin
|
||||
${OpenCV_INSTALL_PATH}/share/java
|
||||
${OpenCV_INSTALL_PATH}/share/java/opencv4
|
||||
${OpenCV_INSTALL_PATH}/share/OpenCV/java
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
set(CMAKE_JAVA_INCLUDE_PATH apriltag.jar ${EJML_JARS} ${JACKSON_JARS})
|
||||
set(CMAKE_JAVA_INCLUDE_PATH apriltag.jar ${EJML_JARS} ${JACKSON_JARS})
|
||||
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
file(GLOB_RECURSE JAVA_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/main/native/resources/*.json)
|
||||
add_jar(apriltag_jar
|
||||
SOURCES ${JAVA_SOURCES}
|
||||
RESOURCES NAMESPACE "edu/wpi/first/apriltag" ${JAVA_RESOURCES}
|
||||
INCLUDE_JARS wpimath_jar ${EJML_JARS} wpiutil_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME apriltag
|
||||
GENERATE_NATIVE_HEADERS apriltag_jni_headers)
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
file(
|
||||
GLOB_RECURSE JAVA_RESOURCES
|
||||
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
src/main/native/resources/*.json
|
||||
)
|
||||
add_jar(
|
||||
apriltag_jar
|
||||
SOURCES ${JAVA_SOURCES}
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/apriltag" ${JAVA_RESOURCES}
|
||||
INCLUDE_JARS wpimath_jar wpiunits_jar ${EJML_JARS} wpiutil_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME apriltag
|
||||
GENERATE_NATIVE_HEADERS apriltag_jni_headers
|
||||
)
|
||||
set_property(TARGET apriltag_jar PROPERTY FOLDER "java")
|
||||
|
||||
get_property(APRILTAG_JAR_FILE TARGET apriltag_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${APRILTAG_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
install_jar(apriltag_jar DESTINATION ${java_lib_dest})
|
||||
install_jar_exports(TARGETS apriltag_jar FILE apriltag_jar.cmake DESTINATION share/apriltag)
|
||||
|
||||
set_property(TARGET apriltag_jar PROPERTY FOLDER "java")
|
||||
add_library(apriltagjni ${apriltag_jni_src})
|
||||
wpilib_target_warnings(apriltagjni)
|
||||
target_link_libraries(apriltagjni PUBLIC apriltag)
|
||||
|
||||
add_library(apriltagjni ${apriltag_jni_src})
|
||||
wpilib_target_warnings(apriltagjni)
|
||||
target_link_libraries(apriltagjni PUBLIC apriltag)
|
||||
set_property(TARGET apriltagjni PROPERTY FOLDER "libraries")
|
||||
|
||||
set_property(TARGET apriltagjni PROPERTY FOLDER "libraries")
|
||||
|
||||
target_link_libraries(apriltagjni PRIVATE apriltag_jni_headers)
|
||||
add_dependencies(apriltagjni apriltag_jar)
|
||||
|
||||
if (MSVC)
|
||||
install(TARGETS apriltagjni RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
install(TARGETS apriltagjni EXPORT apriltagjni DESTINATION "${main_lib_dest}")
|
||||
target_link_libraries(apriltagjni PRIVATE apriltag_jni_headers)
|
||||
add_dependencies(apriltagjni apriltag_jar)
|
||||
|
||||
install(TARGETS apriltagjni EXPORT apriltagjni)
|
||||
export(TARGETS apriltagjni FILE apriltagjni.cmake NAMESPACE apriltagjni::)
|
||||
endif()
|
||||
|
||||
GENERATE_RESOURCES(src/main/native/resources/edu/wpi/first/apriltag generated/main/cpp APRILTAG frc apriltag_resources_src)
|
||||
if(WITH_JAVA_SOURCE)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
file(GLOB APRILTAG_SOURCES src/main/java/edu/wpi/first/apriltag/*.java)
|
||||
add_jar(
|
||||
apriltag_src_jar
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/apriltag" ${APRILTAG_SOURCES}
|
||||
NAMESPACE
|
||||
"edu/wpi/first/apriltag/jni"
|
||||
src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java
|
||||
OUTPUT_NAME apriltag-sources
|
||||
)
|
||||
|
||||
get_property(APRILTAG_SRC_JAR_FILE TARGET apriltag_src_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${APRILTAG_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
|
||||
set_property(TARGET apriltag_src_jar PROPERTY FOLDER "java")
|
||||
endif()
|
||||
|
||||
generate_resources(
|
||||
src/main/native/resources/edu/wpi/first/apriltag
|
||||
generated/main/cpp
|
||||
APRILTAG
|
||||
frc
|
||||
apriltag_resources_src
|
||||
)
|
||||
|
||||
file(GLOB apriltag_native_src src/main/native/cpp/*.cpp)
|
||||
|
||||
add_library(apriltag ${apriltag_native_src} ${apriltag_resources_src} ${APRILTAGLIB_SRCS} ${APRILTAGLIB_COMMON_SRC} ${TAG_FILES})
|
||||
add_library(
|
||||
apriltag
|
||||
${apriltag_native_src}
|
||||
${apriltag_resources_src}
|
||||
${APRILTAGLIB_SRCS}
|
||||
${APRILTAGLIB_COMMON_SRC}
|
||||
${TAG_FILES}
|
||||
)
|
||||
set_target_properties(apriltag PROPERTIES DEBUG_POSTFIX "d")
|
||||
|
||||
set_property(TARGET apriltag PROPERTY FOLDER "libraries")
|
||||
target_compile_features(apriltag PUBLIC cxx_std_20)
|
||||
wpilib_target_warnings(apriltag)
|
||||
# disable warnings that apriltaglib can't handle
|
||||
if (MSVC)
|
||||
target_compile_options(apriltag PRIVATE /wd4018)
|
||||
if(MSVC)
|
||||
target_compile_options(apriltag PRIVATE /wd4018 /wd4005 /wd4996)
|
||||
else()
|
||||
target_compile_options(apriltag PRIVATE -Wno-sign-compare -Wno-gnu-zero-variadic-macro-arguments)
|
||||
target_compile_options(
|
||||
apriltag
|
||||
PRIVATE -Wno-sign-compare -Wno-gnu-zero-variadic-macro-arguments -Wno-type-limits
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(apriltag wpimath)
|
||||
|
||||
target_include_directories(apriltag PUBLIC
|
||||
$<BUILD_INTERFACE:${apriltaglib_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/apriltag>)
|
||||
target_include_directories(
|
||||
apriltag
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${apriltaglib_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/apriltag>
|
||||
)
|
||||
|
||||
install(TARGETS apriltag EXPORT apriltag DESTINATION "${main_lib_dest}")
|
||||
install(TARGETS apriltag EXPORT apriltag)
|
||||
export(TARGETS apriltag FILE apriltag.cmake NAMESPACE apriltag::)
|
||||
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/apriltag")
|
||||
|
||||
if (WITH_JAVA AND MSVC)
|
||||
install(TARGETS apriltag RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
|
||||
endif()
|
||||
configure_file(apriltag-config.cmake.in ${WPILIB_BINARY_DIR}/apriltag-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/apriltag-config.cmake DESTINATION share/apriltag)
|
||||
install(EXPORT apriltag DESTINATION share/apriltag)
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (apriltag_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (apriltag_config_dir share/apriltag)
|
||||
endif()
|
||||
|
||||
configure_file(apriltag-config.cmake.in ${WPILIB_BINARY_DIR}/apriltag-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/apriltag-config.cmake DESTINATION ${apriltag_config_dir})
|
||||
install(EXPORT apriltag DESTINATION ${apriltag_config_dir})
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
wpilib_add_test(apriltag src/test/native/cpp)
|
||||
target_include_directories(apriltag_test PRIVATE src/test/native/include)
|
||||
target_link_libraries(apriltag_test apriltag gmock_main)
|
||||
|
||||
28
apriltag/README.md
Normal file
28
apriltag/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# AprilTag
|
||||
|
||||
## Adding new field to AprilTagFields
|
||||
|
||||
### Adding field JSON
|
||||
|
||||
1. Add a field layout CSV file to `src/main/native/resources/edu/wpi/first/apriltag`
|
||||
1. See docstring in `convert_apriltag_layouts.py` for more
|
||||
2. Run `convert_apriltag_layouts.py` in the same directory as this readme to generate the JSON
|
||||
3. That script overwrites all generated JSONs, so undo undesired changes if necessary
|
||||
4. Update the field dimensions at the bottom of the JSON
|
||||
1. Length should be in meters from alliance wall to alliance wall
|
||||
2. Width should be in meters from inside guardrail plastic to plastic
|
||||
|
||||
### Java updates
|
||||
|
||||
1. Update `src/main/java/edu/wpi/first/apriltag/AprilTagFields.java`
|
||||
1. Add enum value for new field to `AprilTagFields`
|
||||
2. Update `AprilTagFields.kDefaultField` if necessary
|
||||
|
||||
### C++ updates
|
||||
|
||||
1. Update `src/main/native/include/frc/apriltag/AprilTagFields.h`
|
||||
1. Add enum value for new field to `AprilTagFields`
|
||||
2. Update `AprilTagFields::kDefaultField` if necessary
|
||||
2. Update `src/main/native/cpp/AprilTagFields.cpp`
|
||||
1. Add resource getter prototype like `std::string_view GetResource_2024_crescendo_json()`
|
||||
2. Add case for new field to switch in `LoadAprilTagLayoutField()`
|
||||
@@ -5,3 +5,6 @@ include(CMakeFindDependencyMacro)
|
||||
|
||||
@FILENAME_DEP_REPLACE@
|
||||
include(${SELF_DIR}/apriltag.cmake)
|
||||
if(@WITH_JAVA@)
|
||||
include(${SELF_DIR}/apriltag_jar.cmake)
|
||||
endif()
|
||||
|
||||
@@ -35,7 +35,6 @@ apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation project(':wpimath')
|
||||
devImplementation project(':wpimath')
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
||||
89
apriltag/convert_apriltag_layouts.py
Executable file
89
apriltag/convert_apriltag_layouts.py
Executable file
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
This script converts all AprilTag field layout CSV files in
|
||||
src/main/native/resources/edu/wpi/first/apriltag to the JSON format
|
||||
AprilTagFields expects.
|
||||
|
||||
The input CSV has the following format:
|
||||
|
||||
* Columns: ID, X, Y, Z, Rotation
|
||||
* ID is a positive integer
|
||||
* X, Y, and Z are decimal inches
|
||||
* Rotation is yaw in degrees
|
||||
|
||||
The values come from a table in the layout marking diagram (e.g.,
|
||||
https://firstfrc.blob.core.windows.net/frc2024/FieldAssets/2024LayoutMarkingDiagram.pdf).
|
||||
"""
|
||||
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
|
||||
from wpimath import geometry, units
|
||||
import numpy as np
|
||||
|
||||
|
||||
def main():
|
||||
# Find AprilTag field layout CSVs
|
||||
filenames = [
|
||||
os.path.join(dp, f)
|
||||
for dp, dn, fn in os.walk("src/main/native/resources/edu/wpi/first/apriltag")
|
||||
for f in fn
|
||||
if f.endswith(".csv")
|
||||
]
|
||||
|
||||
for filename in filenames:
|
||||
json_data = {"tags": [], "field": {"length": 0.0, "width": 0.0}}
|
||||
|
||||
# Read CSV and fill in JSON data
|
||||
with open(filename, newline="") as csvfile:
|
||||
reader = csv.reader(csvfile, delimiter=",")
|
||||
|
||||
# Skip header
|
||||
next(reader)
|
||||
|
||||
for row in reader:
|
||||
# Unpack row elements
|
||||
id = int(row[0])
|
||||
x = float(row[1])
|
||||
y = float(row[2])
|
||||
z = float(row[3])
|
||||
rotation = float(row[4])
|
||||
|
||||
# Turn yaw into quaternion
|
||||
q = geometry.Rotation3d(
|
||||
units.radians(0.0),
|
||||
units.radians(0.0),
|
||||
units.degreesToRadians(rotation),
|
||||
).getQuaternion()
|
||||
|
||||
json_data["tags"].append(
|
||||
{
|
||||
"ID": id,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": units.inchesToMeters(x),
|
||||
"y": units.inchesToMeters(y),
|
||||
"z": units.inchesToMeters(z),
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": q.W(),
|
||||
"X": q.X(),
|
||||
"Y": q.Y(),
|
||||
"Z": q.Z(),
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
# Write JSON
|
||||
with open(filename.replace(".csv", ".json"), "w") as f:
|
||||
json.dump(json_data, f, indent=2)
|
||||
f.write("\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -6,17 +6,28 @@ package edu.wpi.first.apriltag;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import edu.wpi.first.apriltag.jni.AprilTagJNI;
|
||||
import edu.wpi.first.math.geometry.Pose3d;
|
||||
import edu.wpi.first.util.RawFrame;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Represents an AprilTag's metadata. */
|
||||
@SuppressWarnings("MemberName")
|
||||
public class AprilTag {
|
||||
/** The tag's ID. */
|
||||
@JsonProperty(value = "ID")
|
||||
public int ID;
|
||||
|
||||
/** The tag's pose. */
|
||||
@JsonProperty(value = "pose")
|
||||
public Pose3d pose;
|
||||
|
||||
/**
|
||||
* Constructs an AprilTag.
|
||||
*
|
||||
* @param ID The tag's ID.
|
||||
* @param pose The tag's pose.
|
||||
*/
|
||||
@SuppressWarnings("ParameterName")
|
||||
@JsonCreator
|
||||
public AprilTag(
|
||||
@@ -28,11 +39,7 @@ public class AprilTag {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof AprilTag) {
|
||||
var other = (AprilTag) obj;
|
||||
return ID == other.ID && pose.equals(other.pose);
|
||||
}
|
||||
return false;
|
||||
return obj instanceof AprilTag tag && ID == tag.ID && pose.equals(tag.pose);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,4 +51,28 @@ public class AprilTag {
|
||||
public String toString() {
|
||||
return "AprilTag(ID: " + ID + ", pose: " + pose + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 16h5 passed in.
|
||||
*
|
||||
* @param id id
|
||||
* @return A RawFrame containing the AprilTag image
|
||||
*/
|
||||
public static RawFrame generate16h5AprilTagImage(int id) {
|
||||
RawFrame frame = new RawFrame();
|
||||
AprilTagJNI.generate16h5AprilTagImage(frame, frame.getNativeObj(), id);
|
||||
return frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 36h11 passed in.
|
||||
*
|
||||
* @param id id
|
||||
* @return A RawFrame containing the AprilTag image
|
||||
*/
|
||||
public static RawFrame generate36h11AprilTagImage(int id) {
|
||||
RawFrame frame = new RawFrame();
|
||||
AprilTagJNI.generate36h11AprilTagImage(frame, frame.getNativeObj(), id);
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class AprilTagDetection {
|
||||
* @return Homography matrix
|
||||
*/
|
||||
public Matrix<N3, N3> getHomographyMatrix() {
|
||||
return new MatBuilder<>(Nat.N3(), Nat.N3()).fill(m_homography);
|
||||
return MatBuilder.fill(Nat.N3(), Nat.N3(), m_homography);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +95,7 @@ public class AprilTagDetection {
|
||||
|
||||
/**
|
||||
* Gets a corner of the tag in image pixel coordinates. These always wrap counter-clock wise
|
||||
* around the tag.
|
||||
* around the tag. Index 0 is the bottom left corner.
|
||||
*
|
||||
* @param ndx Corner index (range is 0-3, inclusive)
|
||||
* @return Corner point X coordinate
|
||||
@@ -106,7 +106,7 @@ public class AprilTagDetection {
|
||||
|
||||
/**
|
||||
* Gets a corner of the tag in image pixel coordinates. These always wrap counter-clock wise
|
||||
* around the tag.
|
||||
* around the tag. Index 0 is the bottom left corner.
|
||||
*
|
||||
* @param ndx Corner index (range is 0-3, inclusive)
|
||||
* @return Corner point Y coordinate
|
||||
@@ -117,7 +117,8 @@ public class AprilTagDetection {
|
||||
|
||||
/**
|
||||
* Gets the corners of the tag in image pixel coordinates. These always wrap counter-clock wise
|
||||
* around the tag.
|
||||
* around the tag. The first set of corner coordinates are the coordinates for the bottom left
|
||||
* corner.
|
||||
*
|
||||
* @return Corner point array (X and Y for each corner in order)
|
||||
*/
|
||||
|
||||
@@ -57,8 +57,21 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
*/
|
||||
public boolean debug;
|
||||
|
||||
/** Default constructor. */
|
||||
public Config() {}
|
||||
|
||||
/**
|
||||
* Constructs a detector configuration.
|
||||
*
|
||||
* @param numThreads How many threads should be used for computation.
|
||||
* @param quadDecimate Quad decimation.
|
||||
* @param quadSigma What Gaussian blur should be applied to the segmented image (used for quad
|
||||
* detection).
|
||||
* @param refineEdges When true, the edges of the each quad are adjusted to "snap to" strong
|
||||
* gradients nearby.
|
||||
* @param decodeSharpening How much sharpening should be done to decoded images.
|
||||
* @param debug Debug mode.
|
||||
*/
|
||||
Config(
|
||||
int numThreads,
|
||||
float quadDecimate,
|
||||
@@ -86,12 +99,8 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Config other = (Config) obj;
|
||||
return numThreads == other.numThreads
|
||||
return obj instanceof Config other
|
||||
&& numThreads == other.numThreads
|
||||
&& quadDecimate == other.quadDecimate
|
||||
&& quadSigma == other.quadSigma
|
||||
&& refineEdges == other.refineEdges
|
||||
@@ -139,8 +148,21 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
*/
|
||||
public boolean deglitch;
|
||||
|
||||
/** Default constructor. */
|
||||
public QuadThresholdParameters() {}
|
||||
|
||||
/**
|
||||
* Constructs quad threshold parameters.
|
||||
*
|
||||
* @param minClusterPixels Threshold used to reject quads containing too few pixels.
|
||||
* @param maxNumMaxima How many corner candidates to consider when segmenting a group of pixels
|
||||
* into a quad.
|
||||
* @param criticalAngle Critical angle, in radians.
|
||||
* @param maxLineFitMSE When fitting lines to the contours, the maximum mean squared error
|
||||
* allowed.
|
||||
* @param minWhiteBlackDiff Minimum brightness offset.
|
||||
* @param deglitch Whether the thresholded image be should be deglitched.
|
||||
*/
|
||||
QuadThresholdParameters(
|
||||
int minClusterPixels,
|
||||
int maxNumMaxima,
|
||||
@@ -168,12 +190,8 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof QuadThresholdParameters)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QuadThresholdParameters other = (QuadThresholdParameters) obj;
|
||||
return minClusterPixels == other.minClusterPixels
|
||||
return obj instanceof QuadThresholdParameters other
|
||||
&& minClusterPixels == other.minClusterPixels
|
||||
&& maxNumMaxima == other.maxNumMaxima
|
||||
&& criticalAngle == other.criticalAngle
|
||||
&& maxLineFitMSE == other.maxLineFitMSE
|
||||
@@ -182,6 +200,7 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs an AprilTagDetector. */
|
||||
public AprilTagDetector() {
|
||||
m_native = AprilTagJNI.createDetector();
|
||||
}
|
||||
@@ -244,7 +263,7 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
* Adds a family of tags to be detected.
|
||||
*
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
* @param bitsCorrected maximum number of bits to correct
|
||||
* @param bitsCorrected Maximum number of bits to correct
|
||||
* @throws IllegalArgumentException if family name not recognized
|
||||
*/
|
||||
public void addFamily(String fam, int bitsCorrected) {
|
||||
@@ -270,6 +289,8 @@ public class AprilTagDetector implements AutoCloseable {
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
*
|
||||
* <p>The image must be grayscale.
|
||||
*
|
||||
* @param img 8-bit OpenCV Mat image
|
||||
* @return Results (array of AprilTagDetection)
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@ import edu.wpi.first.math.geometry.Translation3d;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -44,8 +45,11 @@ import java.util.Optional;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonAutoDetect(getterVisibility = JsonAutoDetect.Visibility.NONE)
|
||||
public class AprilTagFieldLayout {
|
||||
/** Common origin positions for the AprilTag coordinate system. */
|
||||
public enum OriginPosition {
|
||||
/** Blue alliance wall, right side. */
|
||||
kBlueAllianceWallRightSide,
|
||||
/** Red alliance wall, right side. */
|
||||
kRedAllianceWallRightSide,
|
||||
}
|
||||
|
||||
@@ -113,6 +117,26 @@ public class AprilTagFieldLayout {
|
||||
return new ArrayList<>(m_apriltags.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the field the layout is representing in meters.
|
||||
*
|
||||
* @return length, in meters
|
||||
*/
|
||||
@JsonIgnore
|
||||
public double getFieldLength() {
|
||||
return m_fieldDimensions.fieldLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the field the layout is representing in meters.
|
||||
*
|
||||
* @return width, in meters
|
||||
*/
|
||||
@JsonIgnore
|
||||
public double getFieldWidth() {
|
||||
return m_fieldDimensions.fieldWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the origin based on a predefined enumeration of coordinate frame origins. The origins are
|
||||
* calculated from the field dimensions.
|
||||
@@ -123,20 +147,15 @@ public class AprilTagFieldLayout {
|
||||
* @param origin The predefined origin
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setOrigin(OriginPosition origin) {
|
||||
switch (origin) {
|
||||
case kBlueAllianceWallRightSide:
|
||||
setOrigin(new Pose3d());
|
||||
break;
|
||||
case kRedAllianceWallRightSide:
|
||||
setOrigin(
|
||||
new Pose3d(
|
||||
new Translation3d(m_fieldDimensions.fieldLength, m_fieldDimensions.fieldWidth, 0),
|
||||
new Rotation3d(0, 0, Math.PI)));
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported enum value");
|
||||
}
|
||||
public final void setOrigin(OriginPosition origin) {
|
||||
var pose =
|
||||
switch (origin) {
|
||||
case kBlueAllianceWallRightSide -> Pose3d.kZero;
|
||||
case kRedAllianceWallRightSide -> new Pose3d(
|
||||
new Translation3d(m_fieldDimensions.fieldLength, m_fieldDimensions.fieldWidth, 0),
|
||||
new Rotation3d(0, 0, Math.PI));
|
||||
};
|
||||
setOrigin(pose);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,10 +167,20 @@ public class AprilTagFieldLayout {
|
||||
* @param origin The new origin for tag transformations
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setOrigin(Pose3d origin) {
|
||||
public final void setOrigin(Pose3d origin) {
|
||||
m_origin = origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the origin used for tag pose transformation.
|
||||
*
|
||||
* @return the origin
|
||||
*/
|
||||
@JsonIgnore
|
||||
public Pose3d getOrigin() {
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an AprilTag pose by its ID.
|
||||
*
|
||||
@@ -188,6 +217,29 @@ public class AprilTagFieldLayout {
|
||||
new ObjectMapper().writeValue(path.toFile(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an official {@link AprilTagFieldLayout}.
|
||||
*
|
||||
* @param field The loadable AprilTag field layout.
|
||||
* @return AprilTagFieldLayout of the field.
|
||||
* @throws UncheckedIOException If the layout does not exist.
|
||||
*/
|
||||
public static AprilTagFieldLayout loadField(AprilTagFields field) {
|
||||
if (field.m_fieldLayout == null) {
|
||||
try {
|
||||
field.m_fieldLayout = loadFromResource(field.m_resourceFile);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(
|
||||
"Could not load AprilTagFieldLayout from " + field.m_resourceFile, e);
|
||||
}
|
||||
}
|
||||
// Copy layout because the layout's origin is mutable
|
||||
return new AprilTagFieldLayout(
|
||||
field.m_fieldLayout.getTags(),
|
||||
field.m_fieldLayout.getFieldLength(),
|
||||
field.m_fieldLayout.getFieldWidth());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserializes a field layout from a resource within a internal jar file.
|
||||
*
|
||||
@@ -199,19 +251,24 @@ public class AprilTagFieldLayout {
|
||||
* @throws IOException If the resource could not be loaded
|
||||
*/
|
||||
public static AprilTagFieldLayout loadFromResource(String resourcePath) throws IOException {
|
||||
try (InputStream stream = AprilTagFieldLayout.class.getResourceAsStream(resourcePath);
|
||||
InputStreamReader reader = new InputStreamReader(stream)) {
|
||||
InputStream stream = AprilTagFieldLayout.class.getResourceAsStream(resourcePath);
|
||||
if (stream == null) {
|
||||
// Class.getResourceAsStream() returns null if the resource does not exist.
|
||||
throw new IOException("Could not locate resource: " + resourcePath);
|
||||
}
|
||||
InputStreamReader reader = new InputStreamReader(stream);
|
||||
try {
|
||||
return new ObjectMapper().readerFor(AprilTagFieldLayout.class).readValue(reader);
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Failed to load AprilTagFieldLayout: " + resourcePath);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof AprilTagFieldLayout) {
|
||||
var other = (AprilTagFieldLayout) obj;
|
||||
return m_apriltags.equals(other.m_apriltags) && m_origin.equals(other.m_origin);
|
||||
}
|
||||
return false;
|
||||
return obj instanceof AprilTagFieldLayout layout
|
||||
&& m_apriltags.equals(layout.m_apriltags)
|
||||
&& m_origin.equals(layout.m_origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -224,11 +281,11 @@ public class AprilTagFieldLayout {
|
||||
private static class FieldDimensions {
|
||||
@SuppressWarnings("MemberName")
|
||||
@JsonProperty(value = "length")
|
||||
public double fieldLength;
|
||||
public final double fieldLength;
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
@JsonProperty(value = "width")
|
||||
public double fieldWidth;
|
||||
public final double fieldWidth;
|
||||
|
||||
@JsonCreator()
|
||||
FieldDimensions(
|
||||
|
||||
@@ -4,19 +4,28 @@
|
||||
|
||||
package edu.wpi.first.apriltag;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
/** Loadable AprilTag field layouts. */
|
||||
public enum AprilTagFields {
|
||||
/** 2022 Rapid React. */
|
||||
k2022RapidReact("2022-rapidreact.json"),
|
||||
k2023ChargedUp("2023-chargedup.json");
|
||||
/** 2023 Charged Up. */
|
||||
k2023ChargedUp("2023-chargedup.json"),
|
||||
/** 2024 Crescendo. */
|
||||
k2024Crescendo("2024-crescendo.json");
|
||||
|
||||
/** Base resource directory. */
|
||||
public static final String kBaseResourceDir = "/edu/wpi/first/apriltag/";
|
||||
|
||||
/** Alias to the current game. */
|
||||
public static final AprilTagFields kDefaultField = k2023ChargedUp;
|
||||
public static final AprilTagFields kDefaultField = k2024Crescendo;
|
||||
|
||||
/** Resource filename. */
|
||||
public final String m_resourceFile;
|
||||
|
||||
AprilTagFieldLayout m_fieldLayout;
|
||||
|
||||
AprilTagFields(String resourceFile) {
|
||||
m_resourceFile = kBaseResourceDir + resourceFile;
|
||||
}
|
||||
@@ -25,9 +34,11 @@ public enum AprilTagFields {
|
||||
* Get a {@link AprilTagFieldLayout} from the resource JSON.
|
||||
*
|
||||
* @return AprilTagFieldLayout of the field
|
||||
* @throws IOException If the layout does not exist
|
||||
* @throws UncheckedIOException If the layout does not exist
|
||||
* @deprecated Use {@link AprilTagFieldLayout#loadField(AprilTagFields)} instead.
|
||||
*/
|
||||
public AprilTagFieldLayout loadAprilTagLayoutField() throws IOException {
|
||||
return AprilTagFieldLayout.loadFromResource(m_resourceFile);
|
||||
@Deprecated(forRemoval = true, since = "2025")
|
||||
public AprilTagFieldLayout loadAprilTagLayoutField() {
|
||||
return AprilTagFieldLayout.loadField(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,19 @@ public class AprilTagPoseEstimator {
|
||||
this.cy = cy;
|
||||
}
|
||||
|
||||
/** Tag size, in meters. */
|
||||
public double tagSize;
|
||||
|
||||
/** Camera horizontal focal length, in pixels. */
|
||||
public double fx;
|
||||
|
||||
/** Camera vertical focal length, in pixels. */
|
||||
public double fy;
|
||||
|
||||
/** Camera horizontal focal center, in pixels. */
|
||||
public double cx;
|
||||
|
||||
/** Camera vertical focal center, in pixels. */
|
||||
public double cy;
|
||||
|
||||
@Override
|
||||
@@ -46,12 +55,8 @@ public class AprilTagPoseEstimator {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof Config)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Config other = (Config) obj;
|
||||
return tagSize == other.tagSize
|
||||
return obj instanceof Config other
|
||||
&& tagSize == other.tagSize
|
||||
&& fx == other.fx
|
||||
&& fy == other.fy
|
||||
&& cx == other.cx
|
||||
|
||||
@@ -8,34 +8,45 @@ import edu.wpi.first.apriltag.AprilTagDetection;
|
||||
import edu.wpi.first.apriltag.AprilTagDetector;
|
||||
import edu.wpi.first.apriltag.AprilTagPoseEstimate;
|
||||
import edu.wpi.first.math.geometry.Transform3d;
|
||||
import edu.wpi.first.util.RawFrame;
|
||||
import edu.wpi.first.util.RuntimeLoader;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** AprilTag JNI. */
|
||||
public class AprilTagJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<AprilTagJNI> loader = null;
|
||||
|
||||
/** Sets whether JNI should be loaded in the static block. */
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
/**
|
||||
* Returns true if the JNI should be loaded in the static block.
|
||||
*
|
||||
* @return True if the JNI should be loaded in the static block.
|
||||
*/
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the JNI should be loaded in the static block.
|
||||
*
|
||||
* @param load Whether the JNI should be loaded in the static block.
|
||||
*/
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
|
||||
/** Utility class. */
|
||||
private Helper() {}
|
||||
}
|
||||
|
||||
static {
|
||||
if (Helper.getExtractOnStaticLoad()) {
|
||||
try {
|
||||
loader =
|
||||
new RuntimeLoader<>(
|
||||
"apriltagjni", RuntimeLoader.getDefaultExtractionRoot(), AprilTagJNI.class);
|
||||
loader.loadLibrary();
|
||||
RuntimeLoader.loadLibrary("apriltagjni");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
@@ -44,31 +55,119 @@ public class AprilTagJNI {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an AprilTag detector engine.
|
||||
*
|
||||
* @return The detector engine handle
|
||||
*/
|
||||
public static native long createDetector();
|
||||
|
||||
/**
|
||||
* Destroys an AprilTag detector engine.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
*/
|
||||
public static native void destroyDetector(long det);
|
||||
|
||||
/**
|
||||
* Sets the detector engine configuration.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param config A configuration
|
||||
*/
|
||||
public static native void setDetectorConfig(long det, AprilTagDetector.Config config);
|
||||
|
||||
/**
|
||||
* Gets the detector engine configuration.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @return The configuration
|
||||
*/
|
||||
public static native AprilTagDetector.Config getDetectorConfig(long det);
|
||||
|
||||
/**
|
||||
* Sets the detector engine quad threshold parameters.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param params Quad threshold parameters
|
||||
*/
|
||||
public static native void setDetectorQTP(
|
||||
long det, AprilTagDetector.QuadThresholdParameters params);
|
||||
|
||||
/**
|
||||
* Gets the detector engine quad threshold parameters.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @return Quad threshold parameters
|
||||
*/
|
||||
public static native AprilTagDetector.QuadThresholdParameters getDetectorQTP(long det);
|
||||
|
||||
/**
|
||||
* Adds a family of tags to be detected by the detector engine.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
* @param bitsCorrected Maximum number of bits to correct
|
||||
* @return False if family can't be found
|
||||
*/
|
||||
public static native boolean addFamily(long det, String fam, int bitsCorrected);
|
||||
|
||||
/**
|
||||
* Removes a family of tags from the detector.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
*/
|
||||
public static native void removeFamily(long det, String fam);
|
||||
|
||||
/**
|
||||
* Unregister all families.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
*/
|
||||
public static native void clearFamilies(long det);
|
||||
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
*
|
||||
* @param det The detector engine handle
|
||||
* @param width The width of the image
|
||||
* @param height The height of the image
|
||||
* @param stride The number of bytes between image rows (often the same as width)
|
||||
* @param bufAddr The address of the image buffer
|
||||
* @return The results (array of AprilTagDetection)
|
||||
*/
|
||||
public static native AprilTagDetection[] detect(
|
||||
long det, int width, int height, int stride, long bufAddr);
|
||||
|
||||
/**
|
||||
* Estimates the pose of the tag using the homography method described in [1].
|
||||
*
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @param tagSize The tag size, in meters
|
||||
* @param fx The camera horizontal focal length, in pixels
|
||||
* @param fy The camera vertical focal length, in pixels
|
||||
* @param cx The camera horizontal focal center, in pixels
|
||||
* @param cy The camera vertical focal center, in pixels
|
||||
* @return Pose estimate
|
||||
*/
|
||||
public static native Transform3d estimatePoseHomography(
|
||||
double[] homography, double tagSize, double fx, double fy, double cx, double cy);
|
||||
|
||||
/**
|
||||
* Estimates the pose of the tag. This returns one or two possible poses for the tag, along with
|
||||
* the object-space error of each.
|
||||
*
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @param corners Corner point array (X and Y for each corner in order)
|
||||
* @param tagSize The tag size, in meters
|
||||
* @param fx The camera horizontal focal length, in pixels
|
||||
* @param fy The camera vertical focal length, in pixels
|
||||
* @param cx The camera horizontal focal center, in pixels
|
||||
* @param cy The camera vertical focal center, in pixels
|
||||
* @param nIters Number of iterations
|
||||
* @return Initial and (possibly) second pose estimates
|
||||
*/
|
||||
public static native AprilTagPoseEstimate estimatePoseOrthogonalIteration(
|
||||
double[] homography,
|
||||
double[] corners,
|
||||
@@ -79,6 +178,20 @@ public class AprilTagJNI {
|
||||
double cy,
|
||||
int nIters);
|
||||
|
||||
/**
|
||||
* Estimates tag pose. This method is an easier to use interface to
|
||||
* EstimatePoseOrthogonalIteration(), running 50 iterations and returning the pose with the lower
|
||||
* object-space error.
|
||||
*
|
||||
* @param homography Homography 3x3 matrix data
|
||||
* @param corners Corner point array (X and Y for each corner in order)
|
||||
* @param tagSize The tag size, in meters
|
||||
* @param fx The camera horizontal focal length, in pixels
|
||||
* @param fy The camera vertical focal length, in pixels
|
||||
* @param cx The camera horizontal focal center, in pixels
|
||||
* @param cy The camera vertical focal center, in pixels
|
||||
* @return Pose estimate
|
||||
*/
|
||||
public static native Transform3d estimatePose(
|
||||
double[] homography,
|
||||
double[] corners,
|
||||
@@ -87,4 +200,25 @@ public class AprilTagJNI {
|
||||
double fy,
|
||||
double cx,
|
||||
double cy);
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 16h5 passed in.
|
||||
*
|
||||
* @param frameObj generated frame (output parameter).
|
||||
* @param frame raw frame handle
|
||||
* @param id id
|
||||
*/
|
||||
public static native void generate16h5AprilTagImage(RawFrame frameObj, long frame, int id);
|
||||
|
||||
/**
|
||||
* Generates a RawFrame containing the apriltag with the id with family 36h11 passed in.
|
||||
*
|
||||
* @param frameObj generated frame (output parameter).
|
||||
* @param frame raw frame handle
|
||||
* @param id id
|
||||
*/
|
||||
public static native void generate36h11AprilTagImage(RawFrame frameObj, long frame, int id);
|
||||
|
||||
/** Utility class. */
|
||||
private AprilTagJNI() {}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,53 @@
|
||||
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <wpi/json.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4200)
|
||||
#elif defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wc99-extensions"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
|
||||
#include "apriltag.h"
|
||||
#include "tag16h5.h"
|
||||
#include "tag36h11.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
static bool FamilyToImage(wpi::RawFrame* frame, apriltag_family_t* family,
|
||||
int id) {
|
||||
image_u8_t* image = apriltag_to_image(family, id);
|
||||
size_t totalDataSize = image->height * image->stride;
|
||||
bool rv = frame->Reserve(totalDataSize);
|
||||
std::memcpy(frame->data, image->buf, totalDataSize);
|
||||
frame->size = totalDataSize;
|
||||
frame->width = image->width;
|
||||
frame->height = image->height;
|
||||
frame->stride = image->stride;
|
||||
frame->pixelFormat = WPI_PIXFMT_GRAY;
|
||||
image_u8_destroy(image);
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool AprilTag::Generate36h11AprilTagImage(wpi::RawFrame* frame, int id) {
|
||||
apriltag_family_t* tagFamily = tag36h11_create();
|
||||
bool rv = FamilyToImage(frame, tagFamily, id);
|
||||
tag36h11_destroy(tagFamily);
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool AprilTag::Generate16h5AprilTagImage(wpi::RawFrame* frame, int id) {
|
||||
apriltag_family_t* tagFamily = tag16h5_create();
|
||||
bool rv = FamilyToImage(frame, tagFamily, id);
|
||||
tag16h5_destroy(tagFamily);
|
||||
return rv;
|
||||
}
|
||||
|
||||
void frc::to_json(wpi::json& json, const AprilTag& apriltag) {
|
||||
json = wpi::json{{"ID", apriltag.ID}, {"pose", apriltag.pose}};
|
||||
}
|
||||
|
||||
@@ -8,22 +8,21 @@
|
||||
|
||||
#include <units/angle.h>
|
||||
#include <units/length.h>
|
||||
#include <wpi/MemoryBuffer.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
using namespace frc;
|
||||
|
||||
AprilTagFieldLayout::AprilTagFieldLayout(std::string_view path) {
|
||||
std::error_code error_code;
|
||||
|
||||
wpi::raw_fd_istream input{path, error_code};
|
||||
if (error_code) {
|
||||
std::error_code ec;
|
||||
std::unique_ptr<wpi::MemoryBuffer> fileBuffer =
|
||||
wpi::MemoryBuffer::GetFile(path, ec);
|
||||
if (fileBuffer == nullptr || ec) {
|
||||
throw std::runtime_error(fmt::format("Cannot open file: {}", path));
|
||||
}
|
||||
|
||||
wpi::json json;
|
||||
input >> json;
|
||||
wpi::json json = wpi::json::parse(fileBuffer->GetCharBuffer());
|
||||
|
||||
for (const auto& tag : json.at("tags").get<std::vector<AprilTag>>()) {
|
||||
m_apriltags[tag.ID] = tag;
|
||||
@@ -42,6 +41,23 @@ AprilTagFieldLayout::AprilTagFieldLayout(std::vector<AprilTag> apriltags,
|
||||
}
|
||||
}
|
||||
|
||||
units::meter_t AprilTagFieldLayout::GetFieldLength() const {
|
||||
return m_fieldLength;
|
||||
}
|
||||
|
||||
units::meter_t AprilTagFieldLayout::GetFieldWidth() const {
|
||||
return m_fieldWidth;
|
||||
}
|
||||
|
||||
std::vector<AprilTag> AprilTagFieldLayout::GetTags() const {
|
||||
std::vector<AprilTag> tags;
|
||||
tags.reserve(m_apriltags.size());
|
||||
for (const auto& tag : m_apriltags) {
|
||||
tags.emplace_back(tag.second);
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
void AprilTagFieldLayout::SetOrigin(OriginPosition origin) {
|
||||
switch (origin) {
|
||||
case OriginPosition::kBlueAllianceWallRightSide:
|
||||
@@ -60,6 +76,10 @@ void AprilTagFieldLayout::SetOrigin(const Pose3d& origin) {
|
||||
m_origin = origin;
|
||||
}
|
||||
|
||||
Pose3d AprilTagFieldLayout::GetOrigin() const {
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
std::optional<frc::Pose3d> AprilTagFieldLayout::GetTagPose(int ID) const {
|
||||
const auto& it = m_apriltags.find(ID);
|
||||
if (it == m_apriltags.end()) {
|
||||
@@ -105,3 +125,37 @@ void frc::from_json(const wpi::json& json, AprilTagFieldLayout& layout) {
|
||||
layout.m_fieldWidth =
|
||||
units::meter_t{json.at("field").at("width").get<double>()};
|
||||
}
|
||||
|
||||
// Use namespace declaration for forward declaration
|
||||
namespace frc {
|
||||
|
||||
// C++ generated from resource files
|
||||
std::string_view GetResource_2022_rapidreact_json();
|
||||
std::string_view GetResource_2023_chargedup_json();
|
||||
std::string_view GetResource_2024_crescendo_json();
|
||||
|
||||
} // namespace frc
|
||||
|
||||
AprilTagFieldLayout AprilTagFieldLayout::LoadField(AprilTagField field) {
|
||||
std::string_view fieldString;
|
||||
switch (field) {
|
||||
case AprilTagField::k2022RapidReact:
|
||||
fieldString = GetResource_2022_rapidreact_json();
|
||||
break;
|
||||
case AprilTagField::k2023ChargedUp:
|
||||
fieldString = GetResource_2023_chargedup_json();
|
||||
break;
|
||||
case AprilTagField::k2024Crescendo:
|
||||
fieldString = GetResource_2024_crescendo_json();
|
||||
break;
|
||||
case AprilTagField::kNumFields:
|
||||
throw std::invalid_argument("Invalid Field");
|
||||
}
|
||||
|
||||
wpi::json json = wpi::json::parse(fieldString);
|
||||
return json.get<AprilTagFieldLayout>();
|
||||
}
|
||||
|
||||
AprilTagFieldLayout frc::LoadAprilTagLayoutField(AprilTagField field) {
|
||||
return AprilTagFieldLayout::LoadField(field);
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "frc/apriltag/AprilTagFields.h"
|
||||
|
||||
#include <wpi/json.h>
|
||||
|
||||
namespace frc {
|
||||
|
||||
// C++ generated from resource files
|
||||
std::string_view GetResource_2022_rapidreact_json();
|
||||
std::string_view GetResource_2023_chargedup_json();
|
||||
|
||||
AprilTagFieldLayout LoadAprilTagLayoutField(AprilTagField field) {
|
||||
std::string_view fieldString;
|
||||
switch (field) {
|
||||
case AprilTagField::k2022RapidReact:
|
||||
fieldString = GetResource_2022_rapidreact_json();
|
||||
break;
|
||||
case AprilTagField::k2023ChargedUp:
|
||||
fieldString = GetResource_2023_chargedup_json();
|
||||
break;
|
||||
case AprilTagField::kNumFields:
|
||||
throw std::invalid_argument("Invalid Field");
|
||||
}
|
||||
|
||||
wpi::json json = wpi::json::parse(fieldString);
|
||||
return json.get<AprilTagFieldLayout>();
|
||||
}
|
||||
|
||||
} // namespace frc
|
||||
@@ -110,7 +110,7 @@ static AprilTagPoseEstimate DoEstimateOrthogonalIteration(
|
||||
apriltag_pose_t pose1, pose2;
|
||||
double err1, err2;
|
||||
estimate_tag_pose_orthogonal_iteration(&info, &err1, &pose1, &err2, &pose2,
|
||||
nIters);
|
||||
nIters, 1e-7);
|
||||
return {MakePose(pose1), MakePose(pose2), err1, err2};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#define WPI_RAWFRAME_JNI
|
||||
#include <wpi/RawFrame.h>
|
||||
#include <wpi/jni_util.h>
|
||||
|
||||
#include "edu_wpi_first_apriltag_jni_AprilTagJNI.h"
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
#include "frc/apriltag/AprilTagDetector.h"
|
||||
#include "frc/apriltag/AprilTagPoseEstimator.h"
|
||||
|
||||
@@ -24,6 +29,7 @@ static JClass quaternionCls;
|
||||
static JClass rotation3dCls;
|
||||
static JClass transform3dCls;
|
||||
static JClass translation3dCls;
|
||||
static JClass rawFrameCls;
|
||||
static JException illegalArgEx;
|
||||
static JException nullPointerEx;
|
||||
|
||||
@@ -36,7 +42,8 @@ static const JClassInit classes[] = {
|
||||
{"edu/wpi/first/math/geometry/Quaternion", &quaternionCls},
|
||||
{"edu/wpi/first/math/geometry/Rotation3d", &rotation3dCls},
|
||||
{"edu/wpi/first/math/geometry/Transform3d", &transform3dCls},
|
||||
{"edu/wpi/first/math/geometry/Translation3d", &translation3dCls}};
|
||||
{"edu/wpi/first/math/geometry/Translation3d", &translation3dCls},
|
||||
{"edu/wpi/first/util/RawFrame", &rawFrameCls}};
|
||||
|
||||
static const JExceptionInit exceptions[] = {
|
||||
{"java/lang/IllegalArgumentException", &illegalArgEx},
|
||||
@@ -504,15 +511,14 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseHomography
|
||||
nullPointerEx.Throw(env, "homography cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef harr{env, homography};
|
||||
JSpan<const jdouble, 9> harr{env, homography};
|
||||
if (harr.size() != 9) {
|
||||
illegalArgEx.Throw(env, "homography array must be size 9");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env, estimator.EstimateHomography(
|
||||
std::span<const double, 9>{harr.array()}));
|
||||
return MakeJObject(env, estimator.EstimateHomography(harr));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -530,7 +536,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
nullPointerEx.Throw(env, "homography cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef harr{env, homography};
|
||||
JSpan<const jdouble, 9> harr{env, homography};
|
||||
if (harr.size() != 9) {
|
||||
illegalArgEx.Throw(env, "homography array must be size 9");
|
||||
return nullptr;
|
||||
@@ -541,7 +547,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
nullPointerEx.Throw(env, "corners cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef carr{env, corners};
|
||||
JSpan<const jdouble, 8> carr{env, corners};
|
||||
if (carr.size() != 8) {
|
||||
illegalArgEx.Throw(env, "corners array must be size 8");
|
||||
return nullptr;
|
||||
@@ -549,9 +555,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
|
||||
AprilTagPoseEstimator estimator({units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env,
|
||||
estimator.EstimateOrthogonalIteration(
|
||||
std::span<const double, 9>{harr.array()},
|
||||
std::span<const double, 8>{carr.array()}, nIters));
|
||||
estimator.EstimateOrthogonalIteration(harr, carr, nIters));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -569,7 +573,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePose
|
||||
nullPointerEx.Throw(env, "homography cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef harr{env, homography};
|
||||
JSpan<const jdouble, 9> harr{env, homography};
|
||||
if (harr.size() != 9) {
|
||||
illegalArgEx.Throw(env, "homography array must be size 9");
|
||||
return nullptr;
|
||||
@@ -580,16 +584,51 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePose
|
||||
nullPointerEx.Throw(env, "corners cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef carr{env, corners};
|
||||
JSpan<const jdouble, 8> carr{env, corners};
|
||||
if (carr.size() != 8) {
|
||||
illegalArgEx.Throw(env, "corners array must be size 8");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(
|
||||
env, estimator.Estimate(std::span<const double, 9>{harr.array()},
|
||||
std::span<const double, 8>{carr.array()}));
|
||||
return MakeJObject(env, estimator.Estimate(harr, carr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_apriltag_jni_AprilTagJNI
|
||||
* Method: generate16h5AprilTagImage
|
||||
* Signature: (Ljava/lang/Object;JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_apriltag_jni_AprilTagJNI_generate16h5AprilTagImage
|
||||
(JNIEnv* env, jclass, jobject frameObj, jlong framePtr, jint id)
|
||||
{
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
if (!frame) {
|
||||
nullPointerEx.Throw(env, "frame is null");
|
||||
return;
|
||||
}
|
||||
bool newData = AprilTag::Generate16h5AprilTagImage(frame, id);
|
||||
wpi::SetFrameData(env, rawFrameCls, frameObj, *frame, newData);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: edu_wpi_first_apriltag_jni_AprilTagJNI
|
||||
* Method: generate36h11AprilTagImage
|
||||
* Signature: (Ljava/lang/Object;JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_apriltag_jni_AprilTagJNI_generate36h11AprilTagImage
|
||||
(JNIEnv* env, jclass, jobject frameObj, jlong framePtr, jint id)
|
||||
{
|
||||
auto* frame = reinterpret_cast<wpi::RawFrame*>(framePtr);
|
||||
if (!frame) {
|
||||
nullPointerEx.Throw(env, "frame is null");
|
||||
return;
|
||||
}
|
||||
// function might reallocate
|
||||
bool newData = AprilTag::Generate36h11AprilTagImage(frame, id);
|
||||
wpi::SetFrameData(env, rawFrameCls, frameObj, *frame, newData);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -4,25 +4,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wpi/RawFrame.h>
|
||||
#include <wpi/SymbolExports.h>
|
||||
#include <wpi/json_fwd.h>
|
||||
|
||||
#include "frc/geometry/Pose3d.h"
|
||||
|
||||
namespace wpi {
|
||||
class json;
|
||||
} // namespace wpi
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Represents an AprilTag's metadata.
|
||||
*/
|
||||
struct WPILIB_DLLEXPORT AprilTag {
|
||||
/// The tag's ID.
|
||||
int ID;
|
||||
|
||||
/// The tag's pose.
|
||||
Pose3d pose;
|
||||
|
||||
/**
|
||||
* Checks equality between this AprilTag and another object.
|
||||
*/
|
||||
bool operator==(const AprilTag&) const = default;
|
||||
|
||||
static bool Generate36h11AprilTagImage(wpi::RawFrame* frame, int id);
|
||||
static bool Generate16h5AprilTagImage(wpi::RawFrame* frame, int id);
|
||||
};
|
||||
|
||||
WPILIB_DLLEXPORT
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <wpi/SymbolExports.h>
|
||||
|
||||
#include "frc/EigenCore.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
@@ -94,7 +93,7 @@ class WPILIB_DLLEXPORT AprilTagDetection final {
|
||||
|
||||
/**
|
||||
* Gets a corner of the tag in image pixel coordinates. These always
|
||||
* wrap counter-clock wise around the tag.
|
||||
* wrap counter-clock wise around the tag. Index 0 is the bottom left corner.
|
||||
*
|
||||
* @param ndx Corner index (range is 0-3, inclusive)
|
||||
* @return Corner point
|
||||
@@ -105,7 +104,8 @@ class WPILIB_DLLEXPORT AprilTagDetection final {
|
||||
|
||||
/**
|
||||
* Gets the corners of the tag in image pixel coordinates. These always
|
||||
* wrap counter-clock wise around the tag.
|
||||
* wrap counter-clock wise around the tag. The first set of corner coordinates
|
||||
* are the coordinates for the bottom left corner.
|
||||
*
|
||||
* @param cornersBuf Corner point array (X and Y for each corner in order)
|
||||
* @return Corner point array (copy of cornersBuf span)
|
||||
|
||||
@@ -205,7 +205,7 @@ class WPILIB_DLLEXPORT AprilTagDetector {
|
||||
* Adds a family of tags to be detected.
|
||||
*
|
||||
* @param fam Family name, e.g. "tag16h5"
|
||||
* @param bitsCorrected
|
||||
* @param bitsCorrected Maximum number of bits to correct
|
||||
* @return False if family can't be found
|
||||
*/
|
||||
bool AddFamily(std::string_view fam, int bitsCorrected = 2);
|
||||
@@ -226,6 +226,7 @@ class WPILIB_DLLEXPORT AprilTagDetector {
|
||||
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
* The image must be grayscale.
|
||||
*
|
||||
* @param width width of the image
|
||||
* @param height height of the image
|
||||
@@ -237,6 +238,7 @@ class WPILIB_DLLEXPORT AprilTagDetector {
|
||||
|
||||
/**
|
||||
* Detect tags from an 8-bit image.
|
||||
* The image must be grayscale.
|
||||
*
|
||||
* @param width width of the image
|
||||
* @param height height of the image
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
|
||||
#include <units/length.h>
|
||||
#include <wpi/SymbolExports.h>
|
||||
#include <wpi/json_fwd.h>
|
||||
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
#include "frc/apriltag/AprilTagFields.h"
|
||||
#include "frc/geometry/Pose3d.h"
|
||||
|
||||
namespace wpi {
|
||||
class json;
|
||||
} // namespace wpi
|
||||
|
||||
namespace frc {
|
||||
/**
|
||||
* Class for representing a layout of AprilTags on a field and reading them from
|
||||
@@ -41,11 +39,24 @@ namespace frc {
|
||||
* towards the opposing alliance). */
|
||||
class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
public:
|
||||
/**
|
||||
* Common origin positions for the AprilTag coordinate system.
|
||||
*/
|
||||
enum class OriginPosition {
|
||||
/// Blue alliance wall, right side.
|
||||
kBlueAllianceWallRightSide,
|
||||
/// Red alliance wall, right side.
|
||||
kRedAllianceWallRightSide,
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an AprilTagFieldLayout from a predefined field
|
||||
*
|
||||
* @param field The predefined field
|
||||
* @return AprilTagFieldLayout of the field
|
||||
*/
|
||||
static AprilTagFieldLayout LoadField(AprilTagField field);
|
||||
|
||||
AprilTagFieldLayout() = default;
|
||||
|
||||
/**
|
||||
@@ -65,6 +76,24 @@ class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
AprilTagFieldLayout(std::vector<AprilTag> apriltags,
|
||||
units::meter_t fieldLength, units::meter_t fieldWidth);
|
||||
|
||||
/**
|
||||
* Returns the length of the field the layout is representing.
|
||||
* @return length
|
||||
*/
|
||||
units::meter_t GetFieldLength() const;
|
||||
|
||||
/**
|
||||
* Returns the length of the field the layout is representing.
|
||||
* @return width
|
||||
*/
|
||||
units::meter_t GetFieldWidth() const;
|
||||
|
||||
/**
|
||||
* Returns a vector of all the april tags used in this layout.
|
||||
* @return list of tags
|
||||
*/
|
||||
std::vector<AprilTag> GetTags() const;
|
||||
|
||||
/**
|
||||
* Sets the origin based on a predefined enumeration of coordinate frame
|
||||
* origins. The origins are calculated from the field dimensions.
|
||||
@@ -79,13 +108,19 @@ class WPILIB_DLLEXPORT AprilTagFieldLayout {
|
||||
/**
|
||||
* Sets the origin for tag pose transformation.
|
||||
*
|
||||
* This tranforms the Pose3ds returned by GetTagPose(int) to return the
|
||||
* This transforms the Pose3ds returned by GetTagPose(int) to return the
|
||||
* correct pose relative to the provided origin.
|
||||
*
|
||||
* @param origin The new origin for tag transformations
|
||||
*/
|
||||
void SetOrigin(const Pose3d& origin);
|
||||
|
||||
/**
|
||||
* Returns the origin used for tag pose transformation.
|
||||
* @return the origin
|
||||
*/
|
||||
Pose3d GetOrigin() const;
|
||||
|
||||
/**
|
||||
* Gets an AprilTag pose by its ID.
|
||||
*
|
||||
@@ -126,4 +161,15 @@ void to_json(wpi::json& json, const AprilTagFieldLayout& layout);
|
||||
WPILIB_DLLEXPORT
|
||||
void from_json(const wpi::json& json, AprilTagFieldLayout& layout);
|
||||
|
||||
/**
|
||||
* Loads an AprilTagFieldLayout from a predefined field
|
||||
*
|
||||
* @param field The predefined field
|
||||
* @return AprilTagFieldLayout of the field
|
||||
* @deprecated Use AprilTagFieldLayout::LoadField() instead
|
||||
*/
|
||||
[[deprecated("Use AprilTagFieldLayout::LoadField() instead")]]
|
||||
WPILIB_DLLEXPORT AprilTagFieldLayout
|
||||
LoadAprilTagLayoutField(AprilTagField field);
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -8,25 +8,22 @@
|
||||
|
||||
#include <wpi/SymbolExports.h>
|
||||
|
||||
#include "frc/apriltag/AprilTagFieldLayout.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
* Loadable AprilTag field layouts.
|
||||
*/
|
||||
enum class AprilTagField {
|
||||
/// 2022 Rapid React.
|
||||
k2022RapidReact,
|
||||
/// 2023 Charged Up.
|
||||
k2023ChargedUp,
|
||||
/// 2024 Crescendo.
|
||||
k2024Crescendo,
|
||||
|
||||
// This is a placeholder for denoting the last supported field. This should
|
||||
// always be the last entry in the enum and should not be used by users
|
||||
kNumFields,
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads an AprilTagFieldLayout from a predefined field
|
||||
*
|
||||
* @param field The predefined field
|
||||
*/
|
||||
WPILIB_DLLEXPORT AprilTagFieldLayout
|
||||
LoadAprilTagLayoutField(AprilTagField field);
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
ID,X,Y,Z,Rotation
|
||||
1,593.68,9.68,53.38,120
|
||||
2,637.21,34.79,53.38,120
|
||||
3,652.73,196.17,57.13,180
|
||||
4,652.73,218.42,57.13,180
|
||||
5,578.77,323.00,53.38,270
|
||||
6,72.5,323.00,53.38,270
|
||||
7,-1.50,218.42,57.13,0
|
||||
8,-1.50,196.17,57.13,0
|
||||
9,14.02,34.79,53.38,60
|
||||
10,57.54,9.68,53.38,60
|
||||
11,468.69,146.19,52.00,300
|
||||
12,468.69,177.10,52.00,60
|
||||
13,441.74,161.62,52.00,180
|
||||
14,209.48,161.62,52.00,0
|
||||
15,182.73,177.10,52.00,120
|
||||
16,182.73,146.19,52.00,240
|
||||
|
@@ -0,0 +1,296 @@
|
||||
{
|
||||
"tags": [
|
||||
{
|
||||
"ID": 1,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 15.079471999999997,
|
||||
"y": 0.24587199999999998,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.5000000000000001,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844386
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 2,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 16.185134,
|
||||
"y": 0.883666,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.5000000000000001,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844386
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 3,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 16.579342,
|
||||
"y": 4.982717999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 6.123233995736766e-17,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 4,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 16.579342,
|
||||
"y": 5.547867999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 6.123233995736766e-17,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 5,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 14.700757999999999,
|
||||
"y": 8.2042,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.7071067811865475,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.7071067811865476
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 6,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 1.8415,
|
||||
"y": 8.2042,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.7071067811865475,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.7071067811865476
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 7,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": -0.038099999999999995,
|
||||
"y": 5.547867999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 1.0,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 8,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": -0.038099999999999995,
|
||||
"y": 4.982717999999999,
|
||||
"z": 1.4511020000000001
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 1.0,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 9,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 0.356108,
|
||||
"y": 0.883666,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.8660254037844387,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 10,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 1.4615159999999998,
|
||||
"y": 0.24587199999999998,
|
||||
"z": 1.355852
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.8660254037844387,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 11,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 11.904726,
|
||||
"y": 3.7132259999999997,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.8660254037844387,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 12,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 11.904726,
|
||||
"y": 4.49834,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.8660254037844387,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.49999999999999994
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 13,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 11.220196,
|
||||
"y": 4.105148,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 6.123233995736766e-17,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 14,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 5.320792,
|
||||
"y": 4.105148,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 1.0,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 15,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 4.641342,
|
||||
"y": 4.49834,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": 0.5000000000000001,
|
||||
"X": 0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844386
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": 16,
|
||||
"pose": {
|
||||
"translation": {
|
||||
"x": 4.641342,
|
||||
"y": 3.7132259999999997,
|
||||
"z": 1.3208
|
||||
},
|
||||
"rotation": {
|
||||
"quaternion": {
|
||||
"W": -0.4999999999999998,
|
||||
"X": -0.0,
|
||||
"Y": 0.0,
|
||||
"Z": 0.8660254037844387
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"field": {
|
||||
"length": 16.541,
|
||||
"width": 8.211
|
||||
}
|
||||
}
|
||||
@@ -29,15 +29,10 @@ class AprilTagDetectorTest {
|
||||
@SuppressWarnings("MemberName")
|
||||
AprilTagDetector detector;
|
||||
|
||||
static RuntimeLoader<Core> loader;
|
||||
|
||||
@BeforeAll
|
||||
static void beforeAll() {
|
||||
try {
|
||||
loader =
|
||||
new RuntimeLoader<>(
|
||||
Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
|
||||
loader.loadLibrary();
|
||||
RuntimeLoader.loadLibrary(Core.NATIVE_LIBRARY_NAME);
|
||||
} catch (IOException ex) {
|
||||
fail(ex);
|
||||
}
|
||||
@@ -157,8 +152,8 @@ class AprilTagDetectorTest {
|
||||
|
||||
var estimator =
|
||||
new AprilTagPoseEstimator(new AprilTagPoseEstimator.Config(0.2, 500, 500, 320, 240));
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 50);
|
||||
assertEquals(new Transform3d(), est.pose2);
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 200);
|
||||
assertEquals(Transform3d.kZero, est.pose2);
|
||||
Transform3d pose = estimator.estimate(results[0]);
|
||||
assertEquals(est.pose1, pose);
|
||||
} finally {
|
||||
@@ -189,7 +184,7 @@ class AprilTagDetectorTest {
|
||||
new AprilTagPoseEstimator(
|
||||
new AprilTagPoseEstimator.Config(
|
||||
0.2, 500, 500, image.cols() / 2.0, image.rows() / 2.0));
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 50);
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 200);
|
||||
|
||||
assertEquals(Units.degreesToRadians(45), est.pose1.getRotation().getX(), 0.1);
|
||||
assertEquals(Units.degreesToRadians(0), est.pose1.getRotation().getY(), 0.1);
|
||||
@@ -222,7 +217,7 @@ class AprilTagDetectorTest {
|
||||
new AprilTagPoseEstimator(
|
||||
new AprilTagPoseEstimator.Config(
|
||||
0.2, 500, 500, image.cols() / 2.0, image.rows() / 2.0));
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 50);
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 200);
|
||||
|
||||
assertEquals(Units.degreesToRadians(0), est.pose1.getRotation().getX(), 0.1);
|
||||
assertEquals(Units.degreesToRadians(45), est.pose1.getRotation().getY(), 0.1);
|
||||
@@ -252,7 +247,7 @@ class AprilTagDetectorTest {
|
||||
new AprilTagPoseEstimator(
|
||||
new AprilTagPoseEstimator.Config(
|
||||
0.2, 500, 500, image.cols() / 2.0, image.rows() / 2.0));
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 50);
|
||||
AprilTagPoseEstimate est = estimator.estimateOrthogonalIteration(results[0], 200);
|
||||
|
||||
assertEquals(Units.degreesToRadians(0), est.pose1.getRotation().getX(), 0.1);
|
||||
assertEquals(Units.degreesToRadians(0), est.pose1.getRotation().getY(), 0.1);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.apriltag;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AprilTagGenerationTest {
|
||||
@Test
|
||||
void test36h11() {
|
||||
var frame = AprilTag.generate36h11AprilTagImage(1);
|
||||
assertEquals(PixelFormat.kGray, frame.getPixelFormat());
|
||||
assertEquals(10, frame.getWidth());
|
||||
assertEquals(10, frame.getHeight());
|
||||
int stride = frame.getStride();
|
||||
assertEquals(stride * 10, frame.getSize());
|
||||
// check the diagonal values
|
||||
var data = frame.getData();
|
||||
assertEquals(-1, data.get(stride * 0 + 0)); // outer border is white
|
||||
assertEquals(0, data.get(stride * 1 + 1)); // inner border is black
|
||||
assertEquals(-1, data.get(stride * 2 + 2));
|
||||
assertEquals(-1, data.get(stride * 3 + 3));
|
||||
assertEquals(-1, data.get(stride * 4 + 4));
|
||||
assertEquals(0, data.get(stride * 5 + 5));
|
||||
assertEquals(0, data.get(stride * 6 + 6));
|
||||
assertEquals(-1, data.get(stride * 7 + 7));
|
||||
assertEquals(0, data.get(stride * 8 + 8)); // inner border
|
||||
assertEquals(-1, data.get(stride * 9 + 9)); // outer border
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class AprilTagPoseSetOriginTest {
|
||||
var layout =
|
||||
new AprilTagFieldLayout(
|
||||
List.of(
|
||||
new AprilTag(1, new Pose3d(new Translation3d(0, 0, 0), new Rotation3d(0, 0, 0))),
|
||||
new AprilTag(1, Pose3d.kZero),
|
||||
new AprilTag(
|
||||
2,
|
||||
new Pose3d(
|
||||
@@ -40,7 +40,7 @@ class AprilTagPoseSetOriginTest {
|
||||
new Pose3d(
|
||||
new Translation3d(
|
||||
Units.feetToMeters(50.0), Units.feetToMeters(23.0), Units.feetToMeters(4)),
|
||||
new Rotation3d(0.0, 0.0, 0)),
|
||||
Rotation3d.kZero),
|
||||
layout.getTagPose(2).orElse(null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ class AprilTagSerializationTest {
|
||||
var layout =
|
||||
new AprilTagFieldLayout(
|
||||
List.of(
|
||||
new AprilTag(1, new Pose3d(0, 0, 0, new Rotation3d(0, 0, 0))),
|
||||
new AprilTag(3, new Pose3d(0, 1, 0, new Rotation3d(0, 0, 0)))),
|
||||
new AprilTag(1, Pose3d.kZero),
|
||||
new AprilTag(3, new Pose3d(0, 1, 0, Rotation3d.kZero))),
|
||||
Units.feetToMeters(54.0),
|
||||
Units.feetToMeters(27.0));
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import edu.wpi.first.math.geometry.Pose3d;
|
||||
import edu.wpi.first.math.geometry.Rotation3d;
|
||||
import edu.wpi.first.math.util.Units;
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -23,13 +22,14 @@ class LoadConfigTest {
|
||||
@ParameterizedTest
|
||||
@EnumSource(AprilTagFields.class)
|
||||
void testLoad(AprilTagFields field) {
|
||||
AprilTagFieldLayout layout = Assertions.assertDoesNotThrow(field::loadAprilTagLayoutField);
|
||||
AprilTagFieldLayout layout =
|
||||
Assertions.assertDoesNotThrow(() -> AprilTagFieldLayout.loadField(field));
|
||||
assertNotNull(layout);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test2022RapidReact() throws IOException {
|
||||
AprilTagFieldLayout layout = AprilTagFields.k2022RapidReact.loadAprilTagLayoutField();
|
||||
void test2022RapidReact() {
|
||||
AprilTagFieldLayout layout = AprilTagFieldLayout.loadField(AprilTagFields.k2022RapidReact);
|
||||
|
||||
// Blue Hangar Truss - Hub
|
||||
Pose3d expectedPose =
|
||||
@@ -37,7 +37,7 @@ class LoadConfigTest {
|
||||
Units.inchesToMeters(127.272),
|
||||
Units.inchesToMeters(216.01),
|
||||
Units.inchesToMeters(67.932),
|
||||
new Rotation3d(0, 0, 0));
|
||||
Rotation3d.kZero);
|
||||
Optional<Pose3d> maybePose = layout.getTagPose(1);
|
||||
assertTrue(maybePose.isPresent());
|
||||
assertEquals(expectedPose, maybePose.get());
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "frc/apriltag/AprilTagDetector.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <wpi/json.h>
|
||||
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
#include "frc/apriltag/AprilTagFieldLayout.h"
|
||||
#include "frc/geometry/Pose3d.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <wpi/json.h>
|
||||
|
||||
#include "frc/apriltag/AprilTag.h"
|
||||
#include "frc/apriltag/AprilTagFieldLayout.h"
|
||||
#include "frc/geometry/Pose3d.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace frc;
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "frc/apriltag/AprilTagFieldLayout.h"
|
||||
#include "frc/apriltag/AprilTagFields.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
@@ -19,7 +21,7 @@ std::vector<AprilTagField> GetAllFields() {
|
||||
|
||||
TEST(AprilTagFieldsTest, TestLoad2022RapidReact) {
|
||||
AprilTagFieldLayout layout =
|
||||
LoadAprilTagLayoutField(AprilTagField::k2022RapidReact);
|
||||
AprilTagFieldLayout::LoadField(AprilTagField::k2022RapidReact);
|
||||
|
||||
// Blue Hangar Truss - Hub
|
||||
auto expectedPose =
|
||||
@@ -52,7 +54,7 @@ class AllFieldsFixtureTest : public ::testing::TestWithParam<AprilTagField> {};
|
||||
|
||||
TEST_P(AllFieldsFixtureTest, CheckEntireEnum) {
|
||||
AprilTagField field = GetParam();
|
||||
EXPECT_NO_THROW(LoadAprilTagLayoutField(field));
|
||||
EXPECT_NO_THROW(AprilTagFieldLayout::LoadField(field));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ValuesEnumTestInstTests, AllFieldsFixtureTest,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
27
build.gradle
27
build.gradle
@@ -7,7 +7,7 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.hubspot.jinjava:jinjava:2.6.0'
|
||||
classpath 'com.hubspot.jinjava:jinjava:2.7.1'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,11 @@ plugins {
|
||||
id 'edu.wpi.first.GradleVsCode'
|
||||
id 'idea'
|
||||
id 'visual-studio'
|
||||
id 'net.ltgt.errorprone' version '2.0.2' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '7.1.2' apply false
|
||||
id 'com.diffplug.spotless' version '6.12.0' apply false
|
||||
id 'com.github.spotbugs' version '5.0.8' apply false
|
||||
id 'net.ltgt.errorprone' version '3.1.0' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
|
||||
id 'com.diffplug.spotless' version '6.20.0' apply false
|
||||
id 'com.github.spotbugs' version '6.0.2' apply false
|
||||
id 'com.google.protobuf' version '0.9.3' apply false
|
||||
}
|
||||
|
||||
wpilibVersioning.buildServerMode = project.hasProperty('buildServer')
|
||||
@@ -49,6 +50,9 @@ buildScan {
|
||||
publishAlways()
|
||||
}
|
||||
|
||||
import com.github.spotbugs.snom.Effort
|
||||
ext.spotbugsEffort = Effort.MAX
|
||||
|
||||
ext.licenseFile = files("$rootDir/LICENSE.md", "$rootDir/ThirdPartyNotices.txt")
|
||||
|
||||
if (project.hasProperty("publishVersion")) {
|
||||
@@ -94,8 +98,8 @@ ext.addTaskToCopyAllOutputs = { task ->
|
||||
return
|
||||
}
|
||||
copyAllOutputs.dependsOn task
|
||||
copyAllOutputs.inputs.file task.archivePath
|
||||
copyAllOutputs.from task.archivePath
|
||||
copyAllOutputs.inputs.file task.archiveFile
|
||||
copyAllOutputs.from task.archiveFile
|
||||
}
|
||||
|
||||
subprojects {
|
||||
@@ -109,8 +113,10 @@ subprojects {
|
||||
}
|
||||
|
||||
plugins.withType(JavaPlugin) {
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
java {
|
||||
sourceCompatibility = 17
|
||||
targetCompatibility = 17
|
||||
}
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/shared/java/javastyle.gradle"
|
||||
@@ -126,6 +132,7 @@ subprojects {
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs.add '-XDstringConcat=inline'
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
// Enables UTF-8 support in Javadoc
|
||||
@@ -167,5 +174,5 @@ ext.getCurrentArch = {
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '7.5.1'
|
||||
gradleVersion = '8.5'
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ repositories {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation "edu.wpi.first:native-utils:2023.11.1"
|
||||
implementation "edu.wpi.first:native-utils:2025.1.0"
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.gradle.language.base.internal.ProjectLayout;
|
||||
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
|
||||
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
|
||||
import org.gradle.model.ModelMap;
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
import edu.wpi.first.toolchain.ToolchainExtension
|
||||
import org.gradle.model.Mutate;
|
||||
import org.gradle.api.plugins.ExtensionContainer;
|
||||
@@ -60,12 +61,16 @@ class MultiBuilds implements Plugin<Project> {
|
||||
@CompileStatic
|
||||
void disableReleaseGoogleTest(BinaryContainer binaries, ProjectLayout projectLayout) {
|
||||
def project = (Project) projectLayout.projectIdentifier
|
||||
if (project.hasProperty('testRelease')) {
|
||||
if (project.hasProperty('testOther')) {
|
||||
return
|
||||
}
|
||||
def check_string = 'release'
|
||||
if (project.hasProperty('buildServer') && !OperatingSystem.current().isWindows()) {
|
||||
check_string = 'debug'
|
||||
}
|
||||
binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
|
||||
GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
|
||||
if (spec.buildType.name == 'release') {
|
||||
if (spec.buildType.name == check_string) {
|
||||
Rules.setBuildableFalseDynamically(spec)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class WPIJREArtifact extends MavenArtifact {
|
||||
|
||||
private boolean checkJreVersion = true;
|
||||
|
||||
private final String artifactLocation = "edu.wpi.first.jdk:roborio-2023:17.0.5u7-1"
|
||||
private final String artifactLocation = "edu.wpi.first.jdk:roborio-2024:17.0.9u7-1"
|
||||
|
||||
@Inject
|
||||
public WPIJREArtifact(String name, RemoteTarget target) {
|
||||
|
||||
@@ -13,6 +13,7 @@ repoRootNameOverride {
|
||||
|
||||
includeOtherLibs {
|
||||
^fmt/
|
||||
^gtest/
|
||||
^hal/
|
||||
^networktables/
|
||||
^opencv2/
|
||||
|
||||
@@ -3,59 +3,86 @@ project(cameraserver)
|
||||
include(CompileWarnings)
|
||||
include(AddTest)
|
||||
|
||||
find_package( OpenCV REQUIRED )
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
# Java bindings
|
||||
if (WITH_JAVA)
|
||||
if(WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
|
||||
#find java files, copy them locally
|
||||
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/java/opencv4)
|
||||
|
||||
find_file(OPENCV_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin NO_DEFAULT_PATH)
|
||||
find_file(
|
||||
OPENCV_JAR_FILE
|
||||
NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar
|
||||
PATHS
|
||||
${OPENCV_JAVA_INSTALL_DIR}
|
||||
${OpenCV_INSTALL_PATH}/bin
|
||||
${OpenCV_INSTALL_PATH}/share/java
|
||||
${OpenCV_INSTALL_PATH}/share/OpenCV/java
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java)
|
||||
|
||||
add_jar(cameraserver_jar ${JAVA_SOURCES} INCLUDE_JARS wpiutil_jar cscore_jar ntcore_jar ${OPENCV_JAR_FILE} OUTPUT_NAME cameraserver)
|
||||
|
||||
get_property(CAMERASERVER_JAR_FILE TARGET cameraserver_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${CAMERASERVER_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
|
||||
add_jar(
|
||||
cameraserver_jar
|
||||
${JAVA_SOURCES}
|
||||
INCLUDE_JARS wpiutil_jar cscore_jar ntcore_jar ${OPENCV_JAR_FILE}
|
||||
OUTPUT_NAME cameraserver
|
||||
)
|
||||
set_property(TARGET cameraserver_jar PROPERTY FOLDER "java")
|
||||
|
||||
install_jar(cameraserver_jar DESTINATION ${java_lib_dest})
|
||||
install_jar_exports(
|
||||
TARGETS cameraserver_jar
|
||||
FILE cameraserver_jar.cmake
|
||||
DESTINATION share/cameraserver
|
||||
)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE
|
||||
cameraserver_native_src src/main/native/cpp/*.cpp)
|
||||
if(WITH_JAVA_SOURCE)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
file(GLOB CAMERASERVER_SOURCES src/main/java/edu/wpi/first/cameraserver/*.java)
|
||||
file(GLOB VISION_SOURCES src/main/java/edu/wpi/first/vision/*.java)
|
||||
add_jar(
|
||||
cameraserver_src_jar
|
||||
RESOURCES
|
||||
NAMESPACE "edu/wpi/first/cameraserver" ${CAMERASERVER_SOURCES}
|
||||
NAMESPACE "edu/wpi/first/vision" ${VISION_SOURCES}
|
||||
OUTPUT_NAME cameraserver-sources
|
||||
)
|
||||
|
||||
get_property(CAMERASERVER_SRC_JAR_FILE TARGET cameraserver_src_jar PROPERTY JAR_FILE)
|
||||
install(FILES ${CAMERASERVER_SRC_JAR_FILE} DESTINATION "${java_lib_dest}")
|
||||
|
||||
set_property(TARGET cameraserver_src_jar PROPERTY FOLDER "java")
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE cameraserver_native_src src/main/native/cpp/*.cpp)
|
||||
add_library(cameraserver ${cameraserver_native_src})
|
||||
set_target_properties(cameraserver PROPERTIES DEBUG_POSTFIX "d")
|
||||
target_include_directories(cameraserver PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cameraserver>)
|
||||
target_include_directories(
|
||||
cameraserver
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
|
||||
$<INSTALL_INTERFACE:${include_dest}/cameraserver>
|
||||
)
|
||||
wpilib_target_warnings(cameraserver)
|
||||
target_link_libraries(cameraserver PUBLIC ntcore cscore wpiutil ${OpenCV_LIBS})
|
||||
|
||||
set_property(TARGET cameraserver PROPERTY FOLDER "libraries")
|
||||
|
||||
install(TARGETS cameraserver EXPORT cameraserver DESTINATION "${main_lib_dest}")
|
||||
install(TARGETS cameraserver EXPORT cameraserver)
|
||||
export(TARGETS cameraserver FILE cameraserver.cmake NAMESPACE cameraserver::)
|
||||
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/cameraserver")
|
||||
|
||||
if (WITH_JAVA AND MSVC)
|
||||
install(TARGETS cameraserver RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
|
||||
endif()
|
||||
|
||||
if (WITH_FLAT_INSTALL)
|
||||
set (cameraserver_config_dir ${wpilib_dest})
|
||||
else()
|
||||
set (cameraserver_config_dir share/cameraserver)
|
||||
endif()
|
||||
|
||||
configure_file(cameraserver-config.cmake.in ${WPILIB_BINARY_DIR}/cameraserver-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
|
||||
install(EXPORT cameraserver DESTINATION ${cameraserver_config_dir})
|
||||
configure_file(cameraserver-config.cmake.in ${WPILIB_BINARY_DIR}/cameraserver-config.cmake)
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cameraserver-config.cmake DESTINATION share/cameraserver)
|
||||
install(EXPORT cameraserver DESTINATION share/cameraserver)
|
||||
|
||||
file(GLOB multiCameraServer_src multiCameraServer/src/main/native/cpp/*.cpp)
|
||||
add_executable(multiCameraServer ${multiCameraServer_src})
|
||||
@@ -64,7 +91,7 @@ target_link_libraries(multiCameraServer cameraserver)
|
||||
|
||||
set_property(TARGET multiCameraServer PROPERTY FOLDER "examples")
|
||||
|
||||
if (WITH_TESTS)
|
||||
if(WITH_TESTS)
|
||||
wpilib_add_test(cameraserver src/test/native/cpp)
|
||||
target_link_libraries(cameraserver_test cameraserver gtest)
|
||||
endif()
|
||||
|
||||
@@ -14,10 +14,6 @@ dependencies {
|
||||
implementation project(':wpinet')
|
||||
implementation project(':ntcore')
|
||||
implementation project(':cscore')
|
||||
devImplementation project(':wpiutil')
|
||||
devImplementation project(':wpinet')
|
||||
devImplementation project(':ntcore')
|
||||
devImplementation project(':cscore')
|
||||
}
|
||||
|
||||
ext {
|
||||
|
||||
@@ -7,3 +7,6 @@ find_dependency(OpenCV)
|
||||
|
||||
@FILENAME_DEP_REPLACE@
|
||||
include(${SELF_DIR}/cameraserver.cmake)
|
||||
if(@WITH_JAVA@)
|
||||
include(${SELF_DIR}/cameraserver_jar.cmake)
|
||||
endif()
|
||||
|
||||
@@ -18,7 +18,9 @@ ext {
|
||||
|
||||
apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
mainClassName = 'edu.wpi.Main'
|
||||
application {
|
||||
mainClass = 'edu.wpi.Main'
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
@@ -29,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
|
||||
implementation project(':wpiutil')
|
||||
implementation project(':wpinet')
|
||||
@@ -59,6 +61,9 @@ model {
|
||||
lib project: ':cscore', library: 'cscore', linkage: 'static'
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'static'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
|
||||
if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
|
||||
nativeUtils.useRequiredLibrary(binary, 'ni_link_libraries', 'ni_runtime_libraries')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public final class Main {
|
||||
// parse file
|
||||
JsonElement top;
|
||||
try {
|
||||
top = new JsonParser().parse(Files.newBufferedReader(Paths.get(configFile)));
|
||||
top = JsonParser.parseReader(Files.newBufferedReader(Paths.get(configFile)));
|
||||
} catch (IOException ex) {
|
||||
System.err.println("could not open '" + configFile + "': " + ex);
|
||||
return false;
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <wpi/MemoryBuffer.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/fmt/raw_ostream.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/print.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "cameraserver/CameraServer.h"
|
||||
@@ -63,10 +65,6 @@ struct CameraConfig {
|
||||
|
||||
std::vector<CameraConfig> cameras;
|
||||
|
||||
wpi::raw_ostream& ParseError() {
|
||||
return wpi::errs() << "config error in '" << configFile << "': ";
|
||||
}
|
||||
|
||||
bool ReadCameraConfig(const wpi::json& config) {
|
||||
CameraConfig c;
|
||||
|
||||
@@ -74,7 +72,8 @@ bool ReadCameraConfig(const wpi::json& config) {
|
||||
try {
|
||||
c.name = config.at("name").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
ParseError() << "could not read camera name: " << e.what() << '\n';
|
||||
wpi::print(stderr, "config error in '{}': could not read camera name: {}\n",
|
||||
configFile, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -82,8 +81,9 @@ bool ReadCameraConfig(const wpi::json& config) {
|
||||
try {
|
||||
c.path = config.at("path").get<std::string>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
ParseError() << "camera '" << c.name
|
||||
<< "': could not read path: " << e.what() << '\n';
|
||||
wpi::print(stderr,
|
||||
"config error in '{}': camera '{}': could not read path: {}\n",
|
||||
configFile, c.name, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -96,25 +96,27 @@ bool ReadCameraConfig(const wpi::json& config) {
|
||||
bool ReadConfig() {
|
||||
// open config file
|
||||
std::error_code ec;
|
||||
wpi::raw_fd_istream is(configFile, ec);
|
||||
if (ec) {
|
||||
wpi::errs() << "could not open '" << configFile << "': " << ec.message()
|
||||
<< '\n';
|
||||
std::unique_ptr<wpi::MemoryBuffer> fileBuffer =
|
||||
wpi::MemoryBuffer::GetFile(configFile, ec);
|
||||
if (fileBuffer == nullptr || ec) {
|
||||
wpi::print(stderr, "could not open '{}': {}\n", configFile, ec.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
// parse file
|
||||
wpi::json j;
|
||||
try {
|
||||
j = wpi::json::parse(is);
|
||||
j = wpi::json::parse(fileBuffer->GetCharBuffer());
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
fmt::print(ParseError(), "byte {}: {}\n", e.byte, e.what());
|
||||
wpi::print(stderr, "config error in '{}': byte {}: {}\n", configFile,
|
||||
e.byte, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
// top level must be an object
|
||||
if (!j.is_object()) {
|
||||
ParseError() << "must be JSON object\n";
|
||||
wpi::print(stderr, "config error in '{}': must be JSON object\n",
|
||||
configFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,7 +124,8 @@ bool ReadConfig() {
|
||||
try {
|
||||
team = j.at("team").get<unsigned int>();
|
||||
} catch (const wpi::json::exception& e) {
|
||||
ParseError() << "could not read team number: " << e.what() << '\n';
|
||||
wpi::print(stderr, "config error in '{}': could not read team number: {}\n",
|
||||
configFile, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,10 +138,14 @@ bool ReadConfig() {
|
||||
} else if (wpi::equals_lower(str, "server")) {
|
||||
server = true;
|
||||
} else {
|
||||
ParseError() << "could not understand ntmode value '" << str << "'\n";
|
||||
wpi::print(
|
||||
stderr,
|
||||
"config error in '{}': could not understand ntmode value '{}'\n",
|
||||
configFile, str);
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
ParseError() << "could not read ntmode: " << e.what() << '\n';
|
||||
wpi::print(stderr, "config error in '{}': could not read ntmode: {}\n",
|
||||
configFile, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +157,8 @@ bool ReadConfig() {
|
||||
}
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
ParseError() << "could not read cameras: " << e.what() << '\n';
|
||||
wpi::print(stderr, "config error in '{}': could not read cameras: {}\n",
|
||||
configFile, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -158,7 +166,7 @@ bool ReadConfig() {
|
||||
}
|
||||
|
||||
void StartCamera(const CameraConfig& config) {
|
||||
fmt::print("Starting camera '{}' on {}\n", config.name, config.path);
|
||||
wpi::print("Starting camera '{}' on {}\n", config.name, config.path);
|
||||
auto camera =
|
||||
frc::CameraServer::StartAutomaticCapture(config.name, config.path);
|
||||
|
||||
@@ -182,7 +190,7 @@ int main(int argc, char* argv[]) {
|
||||
std::puts("Setting up NetworkTables server");
|
||||
ntinst.StartServer();
|
||||
} else {
|
||||
fmt::print("Setting up NetworkTables client for team {}\n", team);
|
||||
wpi::print("Setting up NetworkTables client for team {}\n", team);
|
||||
ntinst.StartClient4("multicameraserver");
|
||||
ntinst.SetServerTeam(team);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import edu.wpi.first.cscore.VideoEvent;
|
||||
import edu.wpi.first.cscore.VideoException;
|
||||
import edu.wpi.first.cscore.VideoListener;
|
||||
import edu.wpi.first.cscore.VideoMode;
|
||||
import edu.wpi.first.cscore.VideoMode.PixelFormat;
|
||||
import edu.wpi.first.cscore.VideoSink;
|
||||
import edu.wpi.first.cscore.VideoSource;
|
||||
import edu.wpi.first.networktables.BooleanEntry;
|
||||
@@ -27,6 +26,8 @@ import edu.wpi.first.networktables.StringArrayPublisher;
|
||||
import edu.wpi.first.networktables.StringArrayTopic;
|
||||
import edu.wpi.first.networktables.StringEntry;
|
||||
import edu.wpi.first.networktables.StringPublisher;
|
||||
import edu.wpi.first.util.PixelFormat;
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -39,6 +40,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* NetworkTables.
|
||||
*/
|
||||
public final class CameraServer {
|
||||
/** CameraServer base port. */
|
||||
public static final int kBasePort = 1181;
|
||||
|
||||
private static final String kPublishName = "/CameraPublisher";
|
||||
@@ -92,29 +94,29 @@ public final class CameraServer {
|
||||
|
||||
void update(VideoEvent event) {
|
||||
switch (event.propertyKind) {
|
||||
case kBoolean:
|
||||
case kBoolean -> {
|
||||
if (m_booleanValueEntry != null) {
|
||||
m_booleanValueEntry.set(event.value != 0);
|
||||
}
|
||||
break;
|
||||
case kInteger:
|
||||
case kEnum:
|
||||
}
|
||||
case kInteger, kEnum -> {
|
||||
if (m_integerValueEntry != null) {
|
||||
m_integerValueEntry.set(event.value);
|
||||
}
|
||||
break;
|
||||
case kString:
|
||||
}
|
||||
case kString -> {
|
||||
if (m_stringValueEntry != null) {
|
||||
m_stringValueEntry.set(event.valueStr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default -> {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
public void close() {
|
||||
if (m_booleanValueEntry != null) {
|
||||
m_booleanValueEntry.close();
|
||||
}
|
||||
@@ -139,6 +141,7 @@ public final class CameraServer {
|
||||
if (m_choicesPublisher != null) {
|
||||
m_choicesPublisher.close();
|
||||
}
|
||||
Reference.reachabilityFence(m_videoListener);
|
||||
}
|
||||
|
||||
BooleanEntry m_booleanValueEntry;
|
||||
@@ -222,118 +225,99 @@ public final class CameraServer {
|
||||
// - "PropertyInfo/{Property}" - Property supporting information
|
||||
|
||||
// Listener for video events
|
||||
@SuppressWarnings({"PMD.UnusedPrivateField", "PMD.AvoidCatchingGenericException"})
|
||||
@SuppressWarnings("PMD.AvoidCatchingGenericException")
|
||||
private static final VideoListener m_videoListener =
|
||||
new VideoListener(
|
||||
event -> {
|
||||
synchronized (CameraServer.class) {
|
||||
switch (event.kind) {
|
||||
case kSourceCreated:
|
||||
{
|
||||
// Create subtable for the camera
|
||||
NetworkTable table = m_publishTable.getSubTable(event.name);
|
||||
m_publishers.put(
|
||||
event.sourceHandle, new SourcePublisher(table, event.sourceHandle));
|
||||
break;
|
||||
case kSourceCreated -> {
|
||||
// Create subtable for the camera
|
||||
NetworkTable table = m_publishTable.getSubTable(event.name);
|
||||
m_publishers.put(
|
||||
event.sourceHandle, new SourcePublisher(table, event.sourceHandle));
|
||||
}
|
||||
case kSourceDestroyed -> {
|
||||
SourcePublisher publisher = m_publishers.remove(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
try {
|
||||
publisher.close();
|
||||
} catch (Exception e) {
|
||||
// ignore (nothing we can do about it)
|
||||
}
|
||||
}
|
||||
case kSourceDestroyed:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.remove(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
}
|
||||
case kSourceConnected -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
// update the description too (as it may have changed)
|
||||
publisher.m_descriptionPublisher.set(
|
||||
CameraServerJNI.getSourceDescription(event.sourceHandle));
|
||||
publisher.m_connectedPublisher.set(true);
|
||||
}
|
||||
}
|
||||
case kSourceDisconnected -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_connectedPublisher.set(false);
|
||||
}
|
||||
}
|
||||
case kSourceVideoModesUpdated -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_modesPublisher.set(getSourceModeValues(event.sourceHandle));
|
||||
}
|
||||
}
|
||||
case kSourceVideoModeChanged -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_modeEntry.set(videoModeToString(event.mode));
|
||||
}
|
||||
}
|
||||
case kSourcePropertyCreated -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_properties.put(
|
||||
event.propertyHandle, new PropertyPublisher(publisher.m_table, event));
|
||||
}
|
||||
}
|
||||
case kSourcePropertyValueUpdated -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
PropertyPublisher pp = publisher.m_properties.get(event.propertyHandle);
|
||||
if (pp != null) {
|
||||
pp.update(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
case kSourcePropertyChoicesUpdated -> {
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
PropertyPublisher pp = publisher.m_properties.get(event.propertyHandle);
|
||||
if (pp != null && pp.m_choicesTopic != null) {
|
||||
try {
|
||||
publisher.close();
|
||||
} catch (Exception e) {
|
||||
// ignore (nothing we can do about it)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceConnected:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
// update the description too (as it may have changed)
|
||||
publisher.m_descriptionPublisher.set(
|
||||
CameraServerJNI.getSourceDescription(event.sourceHandle));
|
||||
publisher.m_connectedPublisher.set(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceDisconnected:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_connectedPublisher.set(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceVideoModesUpdated:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_modesPublisher.set(getSourceModeValues(event.sourceHandle));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourceVideoModeChanged:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_modeEntry.set(videoModeToString(event.mode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourcePropertyCreated:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
publisher.m_properties.put(
|
||||
event.propertyHandle, new PropertyPublisher(publisher.m_table, event));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourcePropertyValueUpdated:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
PropertyPublisher pp = publisher.m_properties.get(event.propertyHandle);
|
||||
if (pp != null) {
|
||||
pp.update(event);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSourcePropertyChoicesUpdated:
|
||||
{
|
||||
SourcePublisher publisher = m_publishers.get(event.sourceHandle);
|
||||
if (publisher != null) {
|
||||
PropertyPublisher pp = publisher.m_properties.get(event.propertyHandle);
|
||||
if (pp != null && pp.m_choicesTopic != null) {
|
||||
try {
|
||||
String[] choices =
|
||||
CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
|
||||
if (pp.m_choicesPublisher == null) {
|
||||
pp.m_choicesPublisher = pp.m_choicesTopic.publish();
|
||||
}
|
||||
pp.m_choicesPublisher.set(choices);
|
||||
} catch (VideoException ignored) {
|
||||
// ignore (just don't publish choices if we can't get them)
|
||||
String[] choices =
|
||||
CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
|
||||
if (pp.m_choicesPublisher == null) {
|
||||
pp.m_choicesPublisher = pp.m_choicesTopic.publish();
|
||||
}
|
||||
pp.m_choicesPublisher.set(choices);
|
||||
} catch (VideoException ignored) {
|
||||
// ignore (just don't publish choices if we can't get them)
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kSinkSourceChanged:
|
||||
case kSinkCreated:
|
||||
case kSinkDestroyed:
|
||||
case kNetworkInterfacesChanged:
|
||||
{
|
||||
m_addresses = CameraServerJNI.getNetworkInterfaces();
|
||||
updateStreamValues();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case kSinkSourceChanged,
|
||||
kSinkCreated,
|
||||
kSinkDestroyed,
|
||||
kNetworkInterfacesChanged -> {
|
||||
m_addresses = CameraServerJNI.getNetworkInterfaces();
|
||||
updateStreamValues();
|
||||
}
|
||||
default -> {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -349,23 +333,20 @@ public final class CameraServer {
|
||||
* @param source Source index.
|
||||
*/
|
||||
private static String makeSourceValue(int source) {
|
||||
switch (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))) {
|
||||
case kUsb:
|
||||
return "usb:" + CameraServerJNI.getUsbCameraPath(source);
|
||||
case kHttp:
|
||||
{
|
||||
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
|
||||
if (urls.length > 0) {
|
||||
return "ip:" + urls[0];
|
||||
} else {
|
||||
return "ip:";
|
||||
}
|
||||
return switch (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))) {
|
||||
case kUsb -> "usb:" + CameraServerJNI.getUsbCameraPath(source);
|
||||
case kHttp -> {
|
||||
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
|
||||
if (urls.length > 0) {
|
||||
yield "ip:" + urls[0];
|
||||
} else {
|
||||
yield "ip:";
|
||||
}
|
||||
case kCv:
|
||||
return "cv:";
|
||||
default:
|
||||
return "unknown:";
|
||||
}
|
||||
}
|
||||
case kCv -> "cv:";
|
||||
case kRaw -> "raw:";
|
||||
case kUnknown -> "unknown:";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,20 +480,17 @@ public final class CameraServer {
|
||||
|
||||
/** Provide string description of pixel format. */
|
||||
private static String pixelFormatToString(PixelFormat pixelFormat) {
|
||||
switch (pixelFormat) {
|
||||
case kMJPEG:
|
||||
return "MJPEG";
|
||||
case kYUYV:
|
||||
return "YUYV";
|
||||
case kRGB565:
|
||||
return "RGB565";
|
||||
case kBGR:
|
||||
return "BGR";
|
||||
case kGray:
|
||||
return "Gray";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
return switch (pixelFormat) {
|
||||
case kMJPEG -> "MJPEG";
|
||||
case kYUYV -> "YUYV";
|
||||
case kRGB565 -> "RGB565";
|
||||
case kBGR -> "BGR";
|
||||
case kBGRA -> "BGRA";
|
||||
case kGray -> "Gray";
|
||||
case kY16 -> "Y16";
|
||||
case kUYVY -> "UYVY";
|
||||
case kUnknown -> "Unknown";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +607,10 @@ public final class CameraServer {
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @return The Axis camera capturing images.
|
||||
* @deprecated Call startAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2025")
|
||||
@SuppressWarnings("removal")
|
||||
public static AxisCamera addAxisCamera(String host) {
|
||||
return addAxisCamera("Axis Camera", host);
|
||||
}
|
||||
@@ -641,7 +622,10 @@ public final class CameraServer {
|
||||
*
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @return The Axis camera capturing images.
|
||||
* @deprecated Call startAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2025")
|
||||
@SuppressWarnings("removal")
|
||||
public static AxisCamera addAxisCamera(String[] hosts) {
|
||||
return addAxisCamera("Axis Camera", hosts);
|
||||
}
|
||||
@@ -652,7 +636,10 @@ public final class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @return The Axis camera capturing images.
|
||||
* @deprecated Call startAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2025")
|
||||
@SuppressWarnings("removal")
|
||||
public static AxisCamera addAxisCamera(String name, String host) {
|
||||
AxisCamera camera = new AxisCamera(name, host);
|
||||
// Create a passthrough MJPEG server for USB access
|
||||
@@ -667,7 +654,10 @@ public final class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @return The Axis camera capturing images.
|
||||
* @deprecated Call startAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "2025")
|
||||
@SuppressWarnings("removal")
|
||||
public static AxisCamera addAxisCamera(String name, String[] hosts) {
|
||||
AxisCamera camera = new AxisCamera(name, hosts);
|
||||
// Create a passthrough MJPEG server for USB access
|
||||
@@ -686,7 +676,7 @@ public final class CameraServer {
|
||||
*/
|
||||
public static MjpegServer addSwitchedCamera(String name) {
|
||||
// create a dummy CvSource
|
||||
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, 160, 120, 30);
|
||||
CvSource source = new CvSource(name, PixelFormat.kMJPEG, 160, 120, 30);
|
||||
MjpegServer server = startAutomaticCapture(source);
|
||||
synchronized (CameraServer.class) {
|
||||
m_fixedSources.put(server.getHandle(), source.getHandle());
|
||||
@@ -745,6 +735,34 @@ public final class CameraServer {
|
||||
return newsink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
|
||||
* image processing on the roboRIO.
|
||||
*
|
||||
* @param camera Camera (e.g. as returned by startAutomaticCapture).
|
||||
* @param pixelFormat Desired pixelFormat of the camera
|
||||
* @return OpenCV sink for the specified camera
|
||||
*/
|
||||
public static CvSink getVideo(VideoSource camera, PixelFormat pixelFormat) {
|
||||
String name = "opencv_" + camera.getName();
|
||||
|
||||
synchronized (CameraServer.class) {
|
||||
VideoSink sink = m_sinks.get(name);
|
||||
if (sink != null) {
|
||||
VideoSink.Kind kind = sink.getKind();
|
||||
if (kind != VideoSink.Kind.kCv) {
|
||||
throw new VideoException("expected OpenCV sink, but got " + kind);
|
||||
}
|
||||
return (CvSink) sink;
|
||||
}
|
||||
}
|
||||
|
||||
CvSink newsink = new CvSink(name, pixelFormat);
|
||||
newsink.setSource(camera);
|
||||
addServer(newsink);
|
||||
return newsink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
|
||||
* image processing on the roboRIO.
|
||||
@@ -773,7 +791,7 @@ public final class CameraServer {
|
||||
* @return OpenCV source for the MJPEG stream
|
||||
*/
|
||||
public static CvSource putVideo(String name, int width, int height) {
|
||||
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, width, height, 30);
|
||||
CvSource source = new CvSource(name, PixelFormat.kMJPEG, width, height, 30);
|
||||
startAutomaticCapture(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.cameraserver;
|
||||
|
||||
/** CameraServer shared functions. */
|
||||
public interface CameraServerShared {
|
||||
/**
|
||||
* get the main thread id func.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
package edu.wpi.first.cameraserver;
|
||||
|
||||
/** Storage for CameraServerShared instance. */
|
||||
public final class CameraServerSharedStore {
|
||||
private static CameraServerShared cameraServerShared;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.opencv.core.Mat;
|
||||
* code. The easiest way to use this is to run it in a {@link VisionThread} and use the listener to
|
||||
* take snapshots of the pipeline's outputs.
|
||||
*
|
||||
* @param <P> Vision pipeline type.
|
||||
* @see VisionPipeline
|
||||
* @see VisionThread
|
||||
* @see <a href="package-summary.html">vision</a>
|
||||
|
||||
@@ -21,6 +21,7 @@ public class VisionThread extends Thread {
|
||||
*
|
||||
* @param visionRunner the runner for a vision pipeline
|
||||
*/
|
||||
@SuppressWarnings("this-escape")
|
||||
public VisionThread(VisionRunner<?> visionRunner) {
|
||||
super(visionRunner::runForever, "WPILib Vision Thread");
|
||||
setDaemon(true);
|
||||
|
||||
@@ -113,6 +113,8 @@ static std::string_view MakeSourceValue(CS_Source source,
|
||||
}
|
||||
case CS_SOURCE_CV:
|
||||
return "cv:";
|
||||
case CS_SOURCE_RAW:
|
||||
return "raw:";
|
||||
default:
|
||||
return "unknown:";
|
||||
}
|
||||
@@ -502,6 +504,7 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
WPI_IGNORE_DEPRECATED
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view host) {
|
||||
return AddAxisCamera("Axis Camera", host);
|
||||
}
|
||||
@@ -557,7 +560,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
csShared->ReportAxisCamera(camera.GetHandle());
|
||||
return camera;
|
||||
}
|
||||
|
||||
WPI_UNIGNORE_DEPRECATED
|
||||
cs::MjpegServer CameraServer::AddSwitchedCamera(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
// create a dummy CvSource
|
||||
@@ -622,6 +625,33 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
|
||||
return newsink;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera,
|
||||
cs::VideoMode::PixelFormat pixelFormat) {
|
||||
auto& inst = ::GetInstance();
|
||||
wpi::SmallString<64> name{"opencv_"};
|
||||
name += camera.GetName();
|
||||
|
||||
{
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
auto it = inst.m_sinks.find(name);
|
||||
if (it != inst.m_sinks.end()) {
|
||||
auto kind = it->second.GetKind();
|
||||
if (kind != cs::VideoSink::kCv) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("expected OpenCV sink, but got {}",
|
||||
static_cast<int>(kind));
|
||||
return cs::CvSink{};
|
||||
}
|
||||
return *static_cast<cs::CvSink*>(&it->second);
|
||||
}
|
||||
}
|
||||
|
||||
cs::CvSink newsink{name.str(), pixelFormat};
|
||||
newsink.SetSource(camera);
|
||||
AddServer(newsink);
|
||||
return newsink;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
cs::VideoSource source;
|
||||
@@ -638,6 +668,23 @@ cs::CvSink CameraServer::GetVideo(std::string_view name) {
|
||||
return GetVideo(source);
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(std::string_view name,
|
||||
cs::VideoMode::PixelFormat pixelFormat) {
|
||||
auto& inst = ::GetInstance();
|
||||
cs::VideoSource source;
|
||||
{
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
auto it = inst.m_sources.find(name);
|
||||
if (it == inst.m_sources.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("could not find camera {}", name);
|
||||
return cs::CvSink{};
|
||||
}
|
||||
source = it->second;
|
||||
}
|
||||
return GetVideo(source, pixelFormat);
|
||||
}
|
||||
|
||||
cs::CvSource CameraServer::PutVideo(std::string_view name, int width,
|
||||
int height) {
|
||||
::GetInstance();
|
||||
@@ -717,22 +764,3 @@ void CameraServer::RemoveCamera(std::string_view name) {
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
inst.m_sources.erase(name);
|
||||
}
|
||||
|
||||
void CameraServer::SetSize(int size) {
|
||||
auto& inst = ::GetInstance();
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
if (inst.m_primarySourceName.empty()) {
|
||||
return;
|
||||
}
|
||||
auto it = inst.m_sources.find(inst.m_primarySourceName);
|
||||
if (it == inst.m_sources.end()) {
|
||||
return;
|
||||
}
|
||||
if (size == kSize160x120) {
|
||||
it->second.SetResolution(160, 120);
|
||||
} else if (size == kSize320x240) {
|
||||
it->second.SetResolution(320, 240);
|
||||
} else if (size == kSize640x480) {
|
||||
it->second.SetResolution(640, 480);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/deprecated.h>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
|
||||
@@ -22,10 +24,8 @@ namespace frc {
|
||||
*/
|
||||
class CameraServer {
|
||||
public:
|
||||
/// CameraServer base port.
|
||||
static constexpr uint16_t kBasePort = 1181;
|
||||
static constexpr int kSize640x480 = 0;
|
||||
static constexpr int kSize320x240 = 1;
|
||||
static constexpr int kSize160x120 = 2;
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
@@ -75,13 +75,16 @@ class CameraServer {
|
||||
*/
|
||||
static cs::MjpegServer StartAutomaticCapture(const cs::VideoSource& camera);
|
||||
|
||||
WPI_IGNORE_DEPRECATED
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
*
|
||||
* This overload calls AddAxisCamera() with name "Axis Camera".
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view host);
|
||||
|
||||
/**
|
||||
@@ -90,7 +93,9 @@ class CameraServer {
|
||||
* This overload calls AddAxisCamera() with name "Axis Camera".
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(const char* host);
|
||||
|
||||
/**
|
||||
@@ -99,7 +104,9 @@ class CameraServer {
|
||||
* This overload calls AddAxisCamera() with name "Axis Camera".
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(const std::string& host);
|
||||
|
||||
/**
|
||||
@@ -108,7 +115,9 @@ class CameraServer {
|
||||
* This overload calls AddAxisCamera() with name "Axis Camera".
|
||||
*
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::span<const std::string> hosts);
|
||||
|
||||
/**
|
||||
@@ -117,8 +126,10 @@ class CameraServer {
|
||||
* This overload calls AddAxisCamera() with name "Axis Camera".
|
||||
*
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
template <typename T>
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
|
||||
|
||||
/**
|
||||
@@ -126,7 +137,9 @@ class CameraServer {
|
||||
*
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
std::string_view host);
|
||||
|
||||
@@ -135,7 +148,9 @@ class CameraServer {
|
||||
*
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name, const char* host);
|
||||
|
||||
/**
|
||||
@@ -143,7 +158,9 @@ class CameraServer {
|
||||
*
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
const std::string& host);
|
||||
|
||||
@@ -152,7 +169,9 @@ class CameraServer {
|
||||
*
|
||||
* @param name The name to give the camera
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
std::span<const std::string> hosts);
|
||||
|
||||
@@ -161,10 +180,13 @@ class CameraServer {
|
||||
*
|
||||
* @param name The name to give the camera
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
* @deprecated Call StartAutomaticCapture with a HttpCamera instead.
|
||||
*/
|
||||
template <typename T>
|
||||
[[deprecated("Call StartAutomaticCapture with a HttpCamera instead.")]]
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
std::initializer_list<T> hosts);
|
||||
WPI_UNIGNORE_DEPRECATED
|
||||
|
||||
/**
|
||||
* Adds a virtual camera for switching between two streams. Unlike the
|
||||
@@ -191,6 +213,17 @@ class CameraServer {
|
||||
*/
|
||||
static cs::CvSink GetVideo(const cs::VideoSource& camera);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
* images from the camera for image processing on the roboRIO.
|
||||
*
|
||||
* @param camera Camera (e.g. as returned by startAutomaticCapture).
|
||||
* @param pixelFormat The desired pixelFormat of captured frames from the
|
||||
* camera
|
||||
*/
|
||||
static cs::CvSink GetVideo(const cs::VideoSource& camera,
|
||||
cs::VideoMode::PixelFormat pixelFormat);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
* images from the camera for image processing on the roboRIO.
|
||||
@@ -199,6 +232,17 @@ class CameraServer {
|
||||
*/
|
||||
static cs::CvSink GetVideo(std::string_view name);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
* images from the camera for image processing on the roboRIO.
|
||||
*
|
||||
* @param name Camera name
|
||||
* @param pixelFormat The desired pixelFormat of captured frames from the
|
||||
* camera
|
||||
*/
|
||||
static cs::CvSink GetVideo(std::string_view name,
|
||||
cs::VideoMode::PixelFormat pixelFormat);
|
||||
|
||||
/**
|
||||
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
|
||||
* annotated images to the dashboard.
|
||||
@@ -267,17 +311,6 @@ class CameraServer {
|
||||
*/
|
||||
static void RemoveCamera(std::string_view name);
|
||||
|
||||
/**
|
||||
* Sets the size of the image to use. Use the public kSize constants to set
|
||||
* the correct mode, or set it directly on a camera and call the appropriate
|
||||
* StartAutomaticCapture method.
|
||||
*
|
||||
* @deprecated Use SetResolution on the UsbCamera returned by
|
||||
* StartAutomaticCapture() instead.
|
||||
* @param size The size to use
|
||||
*/
|
||||
static void SetSize(int size);
|
||||
|
||||
private:
|
||||
CameraServer() = default;
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace frc {
|
||||
|
||||
WPI_IGNORE_DEPRECATED
|
||||
template <typename T>
|
||||
inline cs::AxisCamera CameraServer::AddAxisCamera(
|
||||
std::initializer_list<T> hosts) {
|
||||
@@ -27,5 +28,6 @@ inline cs::AxisCamera CameraServer::AddAxisCamera(
|
||||
}
|
||||
return AddAxisCamera(name, vec);
|
||||
}
|
||||
WPI_UNIGNORE_DEPRECATED
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "vision/VisionRunner.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
@@ -3,11 +3,12 @@ include(CompileWarnings)
|
||||
macro(wpilib_add_test name srcdir)
|
||||
file(GLOB_RECURSE test_src ${srcdir}/*.cpp)
|
||||
add_executable(${name}_test ${test_src})
|
||||
set_property(TARGET ${name}_test PROPERTY FOLDER "tests")
|
||||
wpilib_target_warnings(${name}_test)
|
||||
if (BUILD_SHARED_LIBS)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
|
||||
endif()
|
||||
if (MSVC)
|
||||
if(MSVC)
|
||||
target_compile_options(${name}_test PRIVATE /wd4101 /wd4251)
|
||||
endif()
|
||||
add_test(NAME ${name} COMMAND ${name}_test)
|
||||
|
||||
@@ -1,15 +1,56 @@
|
||||
macro(wpilib_target_warnings target)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter ${WPILIB_TARGET_WARNINGS})
|
||||
set(WARNING_FLAGS
|
||||
-Wall
|
||||
-pedantic
|
||||
-Wextra
|
||||
-Wno-unused-parameter
|
||||
${WPILIB_TARGET_WARNINGS}
|
||||
)
|
||||
if(NOT NO_WERROR)
|
||||
set(WARNING_FLAGS ${WARNING_FLAGS} -Werror)
|
||||
endif()
|
||||
|
||||
target_compile_options(${target} PRIVATE ${WARNING_FLAGS})
|
||||
else()
|
||||
target_compile_options(${target} PRIVATE /wd4146 /wd4244 /wd4251 /wd4267 /WX /D_CRT_SECURE_NO_WARNINGS ${WPILIB_TARGET_WARNINGS})
|
||||
target_compile_options(
|
||||
${target}
|
||||
PRIVATE
|
||||
/wd4146
|
||||
/wd4244
|
||||
/wd4251
|
||||
/wd4267
|
||||
/WX
|
||||
/D_CRT_SECURE_NO_WARNINGS
|
||||
${WPILIB_TARGET_WARNINGS}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Suppress C++-specific OpenCV warning; C compiler rejects it with an error
|
||||
# https://github.com/opencv/opencv/issues/20269
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>)
|
||||
target_compile_options(
|
||||
${target}
|
||||
PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
|
||||
)
|
||||
elseif(UNIX AND APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-anon-enum-enum-conversion>)
|
||||
target_compile_options(
|
||||
${target}
|
||||
PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-anon-enum-enum-conversion>
|
||||
)
|
||||
endif()
|
||||
|
||||
# Suppress warning "enumeration types with a fixed underlying type are a
|
||||
# Clang extension"
|
||||
if(APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:C>:-Wno-fixed-enum-extension>)
|
||||
endif()
|
||||
|
||||
# Compress debug info with GCC
|
||||
if(
|
||||
(${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
|
||||
AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"
|
||||
)
|
||||
target_compile_options(${target} PRIVATE -gz=zlib)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
11
cmake/modules/DownloadAndCheck.cmake
Normal file
11
cmake/modules/DownloadAndCheck.cmake
Normal file
@@ -0,0 +1,11 @@
|
||||
macro(download_and_check source destination)
|
||||
file(DOWNLOAD ${source} ${destination} STATUS download_status)
|
||||
list(GET download_status 0 status_code)
|
||||
list(GET download_status 1 status_message)
|
||||
|
||||
if(${status_code} EQUAL 0)
|
||||
message(VERBOSE "Download of \"${source}\" successful.")
|
||||
else()
|
||||
message(FATAL_ERROR "Download of \"${source}\" failed: ${status_message}")
|
||||
endif()
|
||||
endmacro()
|
||||
@@ -38,30 +38,28 @@ if(LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LIBSSH_FOUND TRUE)
|
||||
else()
|
||||
find_path(LIBSSH_INCLUDE_DIR
|
||||
NAMES
|
||||
libssh/libssh.h
|
||||
find_path(
|
||||
LIBSSH_INCLUDE_DIR
|
||||
NAMES libssh/libssh.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
${CMAKE_INCLUDE_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
)
|
||||
|
||||
find_library(LIBSSH_LIBRARY
|
||||
NAMES
|
||||
ssh.so
|
||||
libssh.so
|
||||
libssh.dylib
|
||||
find_library(
|
||||
LIBSSH_LIBRARY
|
||||
NAMES ssh.so libssh.so libssh.dylib
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
${CMAKE_LIBRARY_PATH}
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
)
|
||||
|
||||
if(LIBSSH_INCLUDE_DIR AND LIBSSH_LIBRARY)
|
||||
@@ -71,34 +69,60 @@ else()
|
||||
else()
|
||||
set(LIBSSH_HEADER_PATH ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h)
|
||||
endif()
|
||||
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_MAJOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+")
|
||||
file(
|
||||
STRINGS
|
||||
${LIBSSH_HEADER_PATH}
|
||||
LIBSSH_VERSION_MAJOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+"
|
||||
)
|
||||
if(NOT LIBSSH_VERSION_MAJOR)
|
||||
message(STATUS "LIBSSH_VERSION_MAJOR not found, assuming libssh is too old and cannot be used!")
|
||||
message(
|
||||
STATUS
|
||||
"LIBSSH_VERSION_MAJOR not found, assuming libssh is too old and cannot be used!"
|
||||
)
|
||||
set(LIBSSH_INCLUDE_DIR "LIBSSH_INCLUDE_DIR-NOTFOUND")
|
||||
set(LIBSSH_LIBRARY "LIBSSH_LIBRARY-NOTFOUND")
|
||||
else()
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MAJOR ${LIBSSH_VERSION_MAJOR})
|
||||
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_MINOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+")
|
||||
file(
|
||||
STRINGS
|
||||
${LIBSSH_HEADER_PATH}
|
||||
LIBSSH_VERSION_MINOR
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MINOR ${LIBSSH_VERSION_MINOR})
|
||||
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_PATCH
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+")
|
||||
file(
|
||||
STRINGS
|
||||
${LIBSSH_HEADER_PATH}
|
||||
LIBSSH_VERSION_PATCH
|
||||
REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${LIBSSH_VERSION_PATCH})
|
||||
|
||||
set(LIBSSH_VERSION ${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH})
|
||||
set(LIBSSH_VERSION
|
||||
${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH}
|
||||
)
|
||||
|
||||
if(LIBSSH_VERSION VERSION_LESS 0.8.0)
|
||||
# libssh_threads also needs to be linked for these versions
|
||||
string(REPLACE "libssh.so" "libssh_threads.so"
|
||||
string(
|
||||
REPLACE
|
||||
"libssh.so"
|
||||
"libssh_threads.so"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_LIBRARY}
|
||||
)
|
||||
string(REPLACE "libssh.dylib" "libssh_threads.dylib"
|
||||
string(
|
||||
REPLACE
|
||||
"libssh.dylib"
|
||||
"libssh_threads.dylib"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_THREADS_LIBRARY}
|
||||
)
|
||||
string(REPLACE "ssh.so" "ssh_threads.so"
|
||||
string(
|
||||
REPLACE
|
||||
"ssh.so"
|
||||
"ssh_threads.so"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_THREADS_LIBRARY}
|
||||
)
|
||||
@@ -110,7 +134,10 @@ else()
|
||||
set(LIBSSH_LIBRARIES ${LIBSSH_LIBRARY} ${LIBSSH_THREADS_LIBRARY})
|
||||
mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES)
|
||||
|
||||
find_package_handle_standard_args(LIBSSH FOUND_VAR LIBSSH_FOUND
|
||||
find_package_handle_standard_args(
|
||||
LIBSSH
|
||||
FOUND_VAR LIBSSH_FOUND
|
||||
REQUIRED_VARS LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES
|
||||
VERSION_VAR LIBSSH_VERSION)
|
||||
VERSION_VAR LIBSSH_VERSION
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
set(SCRIPTS_DIR "${CMAKE_CURRENT_LIST_DIR}/../scripts")
|
||||
MACRO(GENERATE_RESOURCES inputDir outputDir prefix namespace outputFiles)
|
||||
FILE(GLOB inputFiles ${inputDir}/*)
|
||||
SET(${outputFiles})
|
||||
FOREACH(input ${inputFiles})
|
||||
GET_FILENAME_COMPONENT(inputBase ${input} NAME)
|
||||
IF("${inputBase}" MATCHES "^\\.")
|
||||
CONTINUE()
|
||||
ENDIF()
|
||||
SET(output "${outputDir}/${inputBase}.cpp")
|
||||
LIST(APPEND ${outputFiles} "${output}")
|
||||
set(scripts_dir "${CMAKE_CURRENT_LIST_DIR}/../scripts")
|
||||
macro(
|
||||
generate_resources
|
||||
inputDir
|
||||
outputDir
|
||||
prefix
|
||||
namespace
|
||||
outputFiles
|
||||
)
|
||||
file(GLOB inputFiles ${inputDir}/*)
|
||||
set(${outputFiles})
|
||||
foreach(input ${inputFiles})
|
||||
get_filename_component(inputBase ${input} NAME)
|
||||
if("${inputBase}" MATCHES "^\\.")
|
||||
continue()
|
||||
endif()
|
||||
set(output "${outputDir}/${inputBase}.cpp")
|
||||
list(APPEND ${outputFiles} "${output}")
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${output}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
"-Dinput=${input}"
|
||||
"-Doutput=${output}"
|
||||
"-Dprefix=${prefix}"
|
||||
"-Dnamespace=${namespace}"
|
||||
-P "${SCRIPTS_DIR}/GenResource.cmake"
|
||||
MAIN_DEPENDENCY ${input}
|
||||
DEPENDS ${SCRIPTS_DIR}/GenResource.cmake
|
||||
VERBATIM
|
||||
)
|
||||
ENDFOREACH()
|
||||
ENDMACRO()
|
||||
add_custom_command(
|
||||
OUTPUT ${output}
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} "-Dinput=${input}" "-Doutput=${output}" "-Dprefix=${prefix}"
|
||||
"-Dnamespace=${namespace}" -P "${scripts_dir}/GenResource.cmake"
|
||||
MAIN_DEPENDENCY ${input}
|
||||
DEPENDS ${scripts_dir}/GenResource.cmake
|
||||
VERBATIM
|
||||
)
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
macro(wpilib_link_macos_gui target)
|
||||
if (APPLE)
|
||||
set_target_properties(${target} PROPERTIES LINK_FLAGS "-framework Metal -framework QuartzCore")
|
||||
if(APPLE)
|
||||
set_target_properties(
|
||||
${target}
|
||||
PROPERTIES LINK_FLAGS "-framework Metal -framework QuartzCore"
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
MACRO(SUBDIR_LIST result curdir)
|
||||
FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
SET(dirlist "")
|
||||
FOREACH(child ${children})
|
||||
IF(IS_DIRECTORY ${curdir}/${child})
|
||||
LIST(APPEND dirlist ${child})
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
SET(${result} ${dirlist})
|
||||
ENDMACRO()
|
||||
macro(subdir_list result curdir)
|
||||
file(GLOB children RELATIVE ${curdir} ${curdir}/*)
|
||||
set(dirlist "")
|
||||
foreach(child ${children})
|
||||
if(IS_DIRECTORY ${curdir}/${child})
|
||||
list(APPEND dirlist ${child})
|
||||
endif()
|
||||
endforeach()
|
||||
set(${result} ${dirlist})
|
||||
endmacro()
|
||||
|
||||
MACRO(ADD_ALL_SUBDIRECTORIES curdir)
|
||||
SUBDIR_LIST (_SUBPROJECTS ${curdir})
|
||||
FOREACH (dir ${_SUBPROJECTS})
|
||||
ADD_SUBDIRECTORY (${dir})
|
||||
ENDFOREACH ()
|
||||
ENDMACRO()
|
||||
macro(add_all_subdirectories curdir)
|
||||
subdir_list(_SUBPROJECTS ${curdir})
|
||||
foreach(dir ${_SUBPROJECTS})
|
||||
add_subdirectory(${dir})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
@@ -1,23 +1,35 @@
|
||||
# Parameters: input output prefix namespace
|
||||
FILE(READ ${input} fileHex HEX)
|
||||
STRING(LENGTH "${fileHex}" fileHexSize)
|
||||
MATH(EXPR fileSize "${fileHexSize} / 2")
|
||||
file(READ ${input} fileHex HEX)
|
||||
string(LENGTH "${fileHex}" fileHexSize)
|
||||
math(EXPR fileSize "${fileHexSize} / 2")
|
||||
|
||||
GET_FILENAME_COMPONENT(inputBase ${input} NAME)
|
||||
STRING(REGEX REPLACE "[^a-zA-Z0-9]" "_" funcName "${inputBase}")
|
||||
SET(funcName "GetResource_${funcName}")
|
||||
get_filename_component(inputBase ${input} NAME)
|
||||
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" funcName "${inputBase}")
|
||||
set(funcName "GetResource_${funcName}")
|
||||
|
||||
FILE(WRITE "${output}" "#include <stddef.h>\n#include <string_view>\nextern \"C\" {\nstatic const unsigned char contents[] = {")
|
||||
file(
|
||||
WRITE
|
||||
"${output}"
|
||||
"#include <stddef.h>\n#include <string_view>\nextern \"C\" {\nstatic const unsigned char contents[] = {"
|
||||
)
|
||||
|
||||
STRING(REGEX MATCHALL ".." outputData "${fileHex}")
|
||||
STRING(REGEX REPLACE ";" ", 0x" outputData "${outputData}")
|
||||
FILE(APPEND "${output}" " 0x${outputData} };\n")
|
||||
FILE(APPEND "${output}" "const unsigned char* ${prefix}${funcName}(size_t* len) {\n *len = ${fileSize};\n return contents;\n}\n}\n")
|
||||
string(REGEX MATCHALL ".." outputData "${fileHex}")
|
||||
string(REGEX REPLACE ";" ", 0x" outputData "${outputData}")
|
||||
file(APPEND "${output}" " 0x${outputData} };\n")
|
||||
file(
|
||||
APPEND
|
||||
"${output}"
|
||||
"const unsigned char* ${prefix}${funcName}(size_t* len) {\n *len = ${fileSize};\n return contents;\n}\n}\n"
|
||||
)
|
||||
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "namespace ${namespace} {\n")
|
||||
ENDIF()
|
||||
FILE(APPEND "${output}" "std::string_view ${funcName}() {\n return std::string_view(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "}\n")
|
||||
ENDIF()
|
||||
if(NOT namespace STREQUAL "")
|
||||
file(APPEND "${output}" "namespace ${namespace} {\n")
|
||||
endif()
|
||||
file(
|
||||
APPEND
|
||||
"${output}"
|
||||
"std::string_view ${funcName}() {\n return std::string_view(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n"
|
||||
)
|
||||
if(NOT namespace STREQUAL "")
|
||||
file(APPEND "${output}" "}\n")
|
||||
endif()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
|
||||
# load settings in case of "try compile"
|
||||
set(TOOLCHAIN_CONFIG_FILE "${WPILIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/AnalogInput.h>
|
||||
#include <hal/AnalogOutput.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/DIO.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/HAL.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
@@ -21,10 +21,10 @@ TEST_P(DutyCycleTest, DutyCycle) {
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
// Ensure our PWM is disabled, and set up properly
|
||||
HAL_SetPWMRaw(pwmHandle, 0, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmHandle, 0, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetPWMConfig(pwmHandle, 2.0, 1.0, 1.0, 0, 0, &status);
|
||||
HAL_SetPWMConfig(pwmHandle, 5.05, 2.525, 2.525, 2.525, 0, &status);
|
||||
HAL_SetPWMConfigMicroseconds(pwmHandle, 2000, 1000, 1000, 0, 0, &status);
|
||||
HAL_SetPWMConfigMicroseconds(pwmHandle, 5050, 2525, 2525, 2525, 0, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetPWMPeriodScale(pwmHandle, 0, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
@@ -41,8 +41,9 @@ TEST_P(DutyCycleTest, DutyCycle) {
|
||||
// Sleep enough time for the frequency to converge
|
||||
usleep(3500000);
|
||||
|
||||
ASSERT_NEAR(1000 / 5.05,
|
||||
(double)HAL_GetDutyCycleFrequency(dutyCycle, &status), 1);
|
||||
ASSERT_NEAR(
|
||||
1000 / 5.05,
|
||||
static_cast<double>(HAL_GetDutyCycleFrequency(dutyCycle, &status)), 1);
|
||||
|
||||
// TODO measure output
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/DMA.h>
|
||||
#include <hal/HAL.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
@@ -13,7 +14,6 @@
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
@@ -32,8 +32,8 @@ void TestTimingDMA(int squelch, std::pair<int, int> param) {
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
// Ensure our PWM is disabled, and set up properly
|
||||
HAL_SetPWMRaw(pwmHandle, 0, &status);
|
||||
HAL_SetPWMConfig(pwmHandle, 2.0, 1.0, 1.0, 0, 0, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmHandle, 0, &status);
|
||||
HAL_SetPWMConfigMicroseconds(pwmHandle, 2000, 1000, 1000, 0, 0, &status);
|
||||
HAL_SetPWMPeriodScale(pwmHandle, squelch, &status);
|
||||
|
||||
unsigned int checkPeriod = 0;
|
||||
@@ -163,8 +163,8 @@ void TestTiming(int squelch, std::pair<int, int> param) {
|
||||
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
|
||||
|
||||
// Ensure our PWM is disabled, and set up properly
|
||||
HAL_SetPWMRaw(pwmHandle, 0, &status);
|
||||
HAL_SetPWMConfig(pwmHandle, 2.0, 1.0, 1.0, 0, 0, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmHandle, 0, &status);
|
||||
HAL_SetPWMConfigMicroseconds(pwmHandle, 2000, 1000, 1000, 0, 0, &status);
|
||||
HAL_SetPWMPeriodScale(pwmHandle, squelch, &status);
|
||||
|
||||
unsigned int checkPeriod = 0;
|
||||
@@ -251,7 +251,7 @@ void TestTiming(int squelch, std::pair<int, int> param) {
|
||||
}
|
||||
}
|
||||
|
||||
HAL_SetPWMRaw(pwmHandle, 0, &status);
|
||||
HAL_SetPWMPulseTimeMicroseconds(pwmHandle, 0, &status);
|
||||
|
||||
// Ensure our interrupts have the proper counts
|
||||
ASSERT_EQ(interruptData.risingStamps.size(),
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/AnalogInput.h>
|
||||
#include <hal/Relay.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/Relay.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include <thread>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <hal/HAL.h>
|
||||
#include <wpi/print.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mockds/MockDS.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
@@ -27,7 +28,7 @@ class TestEnvironment : public testing::Environment {
|
||||
m_alreadySetUp = true;
|
||||
|
||||
if (!HAL_Initialize(500, 0)) {
|
||||
fmt::print(stderr, "FATAL ERROR: HAL could not be initialized\n");
|
||||
wpi::print(stderr, "FATAL ERROR: HAL could not be initialized\n");
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
@@ -39,7 +40,7 @@ class TestEnvironment : public testing::Environment {
|
||||
// able to run on the hardware.
|
||||
HAL_ObserveUserProgramStarting();
|
||||
|
||||
fmt::print("Started coms\n");
|
||||
wpi::print("Started coms\n");
|
||||
|
||||
int enableCounter = 0;
|
||||
|
||||
@@ -54,13 +55,13 @@ class TestEnvironment : public testing::Environment {
|
||||
if (enableCounter > 50) {
|
||||
// Robot did not enable properly after 5 seconds.
|
||||
// Force exit
|
||||
fmt::print(stderr, " Failed to enable. Aborting\n");
|
||||
wpi::print(stderr, " Failed to enable. Aborting\n");
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
|
||||
fmt::print("Waiting for enable: {}\n", enableCounter++);
|
||||
wpi::print("Waiting for enable: {}\n", enableCounter++);
|
||||
HAL_RefreshDSData();
|
||||
}
|
||||
std::this_thread::sleep_for(500ms);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user