mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-29 02:21:44 +00:00
Compare commits
1067 Commits
v2021.1.1-
...
v2023.0.0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90cfa00115 | ||
|
|
5cf961edb9 | ||
|
|
b2276e47de | ||
|
|
893b46139a | ||
|
|
60e29627c0 | ||
|
|
3b81cf6c35 | ||
|
|
5c067d30a0 | ||
|
|
ceaf493811 | ||
|
|
10e04e2b13 | ||
|
|
726f67c64b | ||
|
|
c7b7624c1c | ||
|
|
d600529ec0 | ||
|
|
b53b3526a2 | ||
|
|
38bb23eb18 | ||
|
|
3937ff8221 | ||
|
|
abbfe244b5 | ||
|
|
4ddb8aa0dd | ||
|
|
a791470de7 | ||
|
|
17f504f548 | ||
|
|
773198537c | ||
|
|
5ac658c8f0 | ||
|
|
8767e4a941 | ||
|
|
8c4af073f4 | ||
|
|
c79f38584a | ||
|
|
36c08dd97c | ||
|
|
69b7b3dd7d | ||
|
|
738c75fed8 | ||
|
|
4eb1d03fb3 | ||
|
|
ba4ec6c967 | ||
|
|
97836f0e55 | ||
|
|
fdfb85f695 | ||
|
|
ab1baf4832 | ||
|
|
9730032866 | ||
|
|
5b656eecf6 | ||
|
|
9ae38eaa7c | ||
|
|
cb33bd71df | ||
|
|
d9b4e7b8bf | ||
|
|
0389bf5214 | ||
|
|
4267fa08d1 | ||
|
|
65c8fbd452 | ||
|
|
f36162fddc | ||
|
|
5149f7d894 | ||
|
|
20b5bed1cb | ||
|
|
f18dd1905d | ||
|
|
aa9d7f1cdc | ||
|
|
2742662254 | ||
|
|
a5df391166 | ||
|
|
59e6706b75 | ||
|
|
8461bb1e03 | ||
|
|
b873e208b4 | ||
|
|
873e72df8c | ||
|
|
c8bd6fc5b4 | ||
|
|
fed68b83b4 | ||
|
|
0ef8a4e1df | ||
|
|
c393b3b367 | ||
|
|
b5a17f762c | ||
|
|
fafc81ed1a | ||
|
|
cc56bdc787 | ||
|
|
4254438d8d | ||
|
|
97c15af238 | ||
|
|
d22ff8a158 | ||
|
|
fdb5a2791f | ||
|
|
c3a93fb995 | ||
|
|
f2a8d38d2a | ||
|
|
9e24c6eac0 | ||
|
|
fe4d12ce22 | ||
|
|
eb08486039 | ||
|
|
ccf83c634a | ||
|
|
3fd69749e7 | ||
|
|
594df5fc08 | ||
|
|
539070820d | ||
|
|
564a56d99b | ||
|
|
5adf50d93c | ||
|
|
d80e8039d7 | ||
|
|
0e6d67b23b | ||
|
|
be5270697a | ||
|
|
8d28851263 | ||
|
|
3d2115c93e | ||
|
|
91002ae3cc | ||
|
|
148c18e658 | ||
|
|
a2a5c926b6 | ||
|
|
ea6b1d8449 | ||
|
|
ac9be78e27 | ||
|
|
151dabb2af | ||
|
|
340465c929 | ||
|
|
d45bcddd15 | ||
|
|
0e0786331a | ||
|
|
c5db23f296 | ||
|
|
44abc8dfa6 | ||
|
|
3fdb2f767d | ||
|
|
0485f05da9 | ||
|
|
0a5eb65231 | ||
|
|
19ffebaf3e | ||
|
|
ce1a90d639 | ||
|
|
d25af48797 | ||
|
|
ebb836dacb | ||
|
|
d83e202f00 | ||
|
|
3ccf806064 | ||
|
|
6f1e01f8bd | ||
|
|
1023c34b1c | ||
|
|
faa29d596c | ||
|
|
add00a96ed | ||
|
|
82fac41244 | ||
|
|
5eb44e22a9 | ||
|
|
2e09fa7325 | ||
|
|
fe3c24b1ee | ||
|
|
aa221597bc | ||
|
|
579a8ee229 | ||
|
|
5105c5eab6 | ||
|
|
787fe6e7a5 | ||
|
|
6671f8d099 | ||
|
|
9ac9b69aa2 | ||
|
|
e61028cb18 | ||
|
|
661d23eaf5 | ||
|
|
666040e3e5 | ||
|
|
aebc272449 | ||
|
|
fd884581e4 | ||
|
|
9b1bf5c7f1 | ||
|
|
c9e620a920 | ||
|
|
41d40dd62f | ||
|
|
30f5b68264 | ||
|
|
f7b3f4b90e | ||
|
|
a99c11c14c | ||
|
|
45b7fc445b | ||
|
|
16a4888c52 | ||
|
|
17752f1337 | ||
|
|
abb45a68db | ||
|
|
1280a54ef3 | ||
|
|
f2d243fa68 | ||
|
|
a4787130f4 | ||
|
|
af7985e46c | ||
|
|
e9d1b5c2d0 | ||
|
|
45b598d236 | ||
|
|
fc37265da5 | ||
|
|
a4ec13eb0e | ||
|
|
2fa52007af | ||
|
|
d9f9cd1140 | ||
|
|
8b6df88783 | ||
|
|
345cff08c0 | ||
|
|
57428112ac | ||
|
|
a18d4ff154 | ||
|
|
d1cd07b9f3 | ||
|
|
e67f8e917a | ||
|
|
be2fedfe50 | ||
|
|
7ad2be172e | ||
|
|
abc605c9c9 | ||
|
|
3e94805220 | ||
|
|
db2e1d170e | ||
|
|
96ebdcaf16 | ||
|
|
553b2a3b12 | ||
|
|
3e13ef42eb | ||
|
|
d651a1fcec | ||
|
|
b193b318c1 | ||
|
|
ef3714223b | ||
|
|
3d8dbbbac3 | ||
|
|
013efdde25 | ||
|
|
816aa4e465 | ||
|
|
046c2c8972 | ||
|
|
d80e9cdf64 | ||
|
|
7576136b4a | ||
|
|
c3b223ce60 | ||
|
|
5aa67f56e6 | ||
|
|
fff4d1f44e | ||
|
|
0d9956273c | ||
|
|
3fada4e0b4 | ||
|
|
65b23ac45e | ||
|
|
4ac34c0141 | ||
|
|
8bd614bb1e | ||
|
|
4253d6d5f0 | ||
|
|
6a4752dcdc | ||
|
|
5876b40f08 | ||
|
|
5983434a70 | ||
|
|
a3d44a1e69 | ||
|
|
d364bbd5a7 | ||
|
|
f341e1b2be | ||
|
|
9af389b200 | ||
|
|
2ae4adf2d7 | ||
|
|
178b2a1e88 | ||
|
|
18db343cdc | ||
|
|
f0c821282a | ||
|
|
d673ead481 | ||
|
|
b33715db15 | ||
|
|
99424ad562 | ||
|
|
dc6f641fd2 | ||
|
|
f20a20f3f1 | ||
|
|
708a4bc3bc | ||
|
|
ef7ed21a9d | ||
|
|
b1abf455c1 | ||
|
|
d5456cf278 | ||
|
|
99343d40ba | ||
|
|
ee03a7ad3b | ||
|
|
ce1a7d698a | ||
|
|
87bf70fa8e | ||
|
|
ebd2a303bf | ||
|
|
e28776d361 | ||
|
|
dac1429aa9 | ||
|
|
e767605e94 | ||
|
|
97c493241f | ||
|
|
8ea90d8bc9 | ||
|
|
ae7b1851ec | ||
|
|
e3d62c22d3 | ||
|
|
7200c4951d | ||
|
|
84056c9347 | ||
|
|
09cf6eeecb | ||
|
|
03230fc842 | ||
|
|
63cf3aaa3f | ||
|
|
18ff694f02 | ||
|
|
4f79ceedd9 | ||
|
|
f7ca72fb41 | ||
|
|
a06b3f0307 | ||
|
|
d926dd1610 | ||
|
|
51bc893bc5 | ||
|
|
fbe761f7f6 | ||
|
|
5ebe911933 | ||
|
|
3919250da2 | ||
|
|
b3aee28388 | ||
|
|
9d20ab3024 | ||
|
|
aaa69f6717 | ||
|
|
355a11a414 | ||
|
|
ffc69d406c | ||
|
|
922d50079a | ||
|
|
dd163b62ae | ||
|
|
bd80e220b9 | ||
|
|
aef4b16d4c | ||
|
|
975171609e | ||
|
|
5bf46a9093 | ||
|
|
f27a1f9bfb | ||
|
|
1b26e2d5da | ||
|
|
88222daa3d | ||
|
|
81c5b41ce1 | ||
|
|
9650e6733e | ||
|
|
c8905ec29a | ||
|
|
b4620f01f9 | ||
|
|
2e462a19d3 | ||
|
|
069f932e59 | ||
|
|
126e3de91a | ||
|
|
ba0dccaae4 | ||
|
|
e1b6e5f212 | ||
|
|
8d79dc8738 | ||
|
|
78108c2aba | ||
|
|
cdafc723fb | ||
|
|
0d70884dce | ||
|
|
765efa325e | ||
|
|
89ffcbbe41 | ||
|
|
95ae23b0e7 | ||
|
|
d5cb6fed67 | ||
|
|
d0fef18378 | ||
|
|
d640c0f41f | ||
|
|
a2fa5e3ff7 | ||
|
|
a3eea9958e | ||
|
|
db27331d7b | ||
|
|
fdfb31f164 | ||
|
|
f93c3331b3 | ||
|
|
ab7ac4fbb9 | ||
|
|
bc39a1a293 | ||
|
|
2668130e70 | ||
|
|
d27ed3722b | ||
|
|
dae18308c9 | ||
|
|
d66555e42f | ||
|
|
9f52d8a3b1 | ||
|
|
757ea91932 | ||
|
|
02a804f1c5 | ||
|
|
9b500df0d9 | ||
|
|
5a89575b3a | ||
|
|
b8c4d7527b | ||
|
|
ac5d46cfa7 | ||
|
|
bc9e96e86f | ||
|
|
f88c435dd0 | ||
|
|
e4b91005cf | ||
|
|
a260bfd83b | ||
|
|
18e262a100 | ||
|
|
4bd1f526ab | ||
|
|
27847d7eb2 | ||
|
|
b2a8d3f0f3 | ||
|
|
49adac9564 | ||
|
|
a19d1133b1 | ||
|
|
dde91717e4 | ||
|
|
e9050afd67 | ||
|
|
165d2837cf | ||
|
|
ac7549edca | ||
|
|
4d96bc72e0 | ||
|
|
3411eee20f | ||
|
|
74de97eeca | ||
|
|
4e3cc25012 | ||
|
|
90c1db393e | ||
|
|
2f43274aa4 | ||
|
|
aeca09db09 | ||
|
|
c107f22c67 | ||
|
|
68fe51e8da | ||
|
|
8d08d67cf1 | ||
|
|
4f1782f66e | ||
|
|
3f77725cd3 | ||
|
|
5635f33a32 | ||
|
|
bca4b7111b | ||
|
|
6a6366b0d6 | ||
|
|
16bf2c70c5 | ||
|
|
4b3edb742c | ||
|
|
fcf23fc9e9 | ||
|
|
af5ef510c5 | ||
|
|
05401e2b81 | ||
|
|
9fde0110b6 | ||
|
|
b03f8ddb2e | ||
|
|
a26df2a022 | ||
|
|
d68d6674e8 | ||
|
|
a8f0f6bb90 | ||
|
|
dd9c92d5bf | ||
|
|
84df14dd70 | ||
|
|
560094ad92 | ||
|
|
7ea1be9c01 | ||
|
|
700f13bffd | ||
|
|
b6aa7c1aa9 | ||
|
|
eb4d183e48 | ||
|
|
77e4e81e1e | ||
|
|
88f5cb6eb0 | ||
|
|
efae552f3e | ||
|
|
46b277421a | ||
|
|
42908126b9 | ||
|
|
a467392cbd | ||
|
|
78d0bcf49d | ||
|
|
02a0ced9b0 | ||
|
|
4ccfe1c9f2 | ||
|
|
830c0c5c2f | ||
|
|
5548a37465 | ||
|
|
2f9a600de2 | ||
|
|
559db11a20 | ||
|
|
76c78e295b | ||
|
|
debbd5ff4b | ||
|
|
841174f302 | ||
|
|
8c55844f91 | ||
|
|
0b990bf0f5 | ||
|
|
104d7e2abc | ||
|
|
5ba69e1af1 | ||
|
|
f3a0b5c7d7 | ||
|
|
7f4265facc | ||
|
|
63d1fb3bed | ||
|
|
36af6d25a5 | ||
|
|
8f387f7255 | ||
|
|
792e735e08 | ||
|
|
3b76de83eb | ||
|
|
ad9f738cfa | ||
|
|
49455199e5 | ||
|
|
64426502ea | ||
|
|
8cc112d196 | ||
|
|
e78cd49861 | ||
|
|
cfb4f756d6 | ||
|
|
ba0908216c | ||
|
|
a3a0334fad | ||
|
|
cf7460c3a8 | ||
|
|
db0fbb6448 | ||
|
|
8ac45f20bb | ||
|
|
b3707cca0b | ||
|
|
a69ee3ece9 | ||
|
|
750d9a30c9 | ||
|
|
41c5b2b5ac | ||
|
|
6cf3f9b28e | ||
|
|
269cf03472 | ||
|
|
5ccfc4adbd | ||
|
|
b6f44f98be | ||
|
|
0dca57e9ec | ||
|
|
22c4da152e | ||
|
|
05d66f862d | ||
|
|
b09f5b2cf2 | ||
|
|
a2510aaa0e | ||
|
|
947f589916 | ||
|
|
bbd8980a20 | ||
|
|
831052f118 | ||
|
|
c137569f91 | ||
|
|
dae61226fa | ||
|
|
3ad4594a88 | ||
|
|
112acb9a62 | ||
|
|
ecee224e81 | ||
|
|
a3645dea34 | ||
|
|
7c09f44898 | ||
|
|
f401ea9aae | ||
|
|
bf8517f1e6 | ||
|
|
528087e308 | ||
|
|
1f59ff72f9 | ||
|
|
315be873c4 | ||
|
|
b8d019cdb4 | ||
|
|
102f23bbdb | ||
|
|
b85c24a79c | ||
|
|
eee29daaf9 | ||
|
|
aa9dfabde2 | ||
|
|
5999a26fba | ||
|
|
1e82595ffb | ||
|
|
e373fa476b | ||
|
|
dceb5364f4 | ||
|
|
baacbc8e24 | ||
|
|
84b15f0883 | ||
|
|
c0da9d2d35 | ||
|
|
0fe0be2733 | ||
|
|
eafa947338 | ||
|
|
9d13ae8d01 | ||
|
|
2a64e4bae5 | ||
|
|
c3fd20db59 | ||
|
|
6f91f37cd0 | ||
|
|
5158730b81 | ||
|
|
2ad2d2ca96 | ||
|
|
b5fd29774f | ||
|
|
9f8f330e96 | ||
|
|
1ad3b1b333 | ||
|
|
dfc24425c3 | ||
|
|
c02577bb51 | ||
|
|
c9e6a96a61 | ||
|
|
9778626f34 | ||
|
|
34b2d0dae1 | ||
|
|
59a7528fd6 | ||
|
|
11d9859ef1 | ||
|
|
e44ed752ad | ||
|
|
52b2dd5b89 | ||
|
|
c46636f218 | ||
|
|
dc531462e1 | ||
|
|
92ba98621c | ||
|
|
d41d051f1b | ||
|
|
c5ae0effac | ||
|
|
b3974c6ed3 | ||
|
|
589a00e379 | ||
|
|
8d9836ca02 | ||
|
|
8b5bf8632e | ||
|
|
1846114491 | ||
|
|
2c461c794e | ||
|
|
109363daa4 | ||
|
|
41d26bee8d | ||
|
|
7269a170fb | ||
|
|
441f2ed9b0 | ||
|
|
15275433d4 | ||
|
|
1ac02d2f58 | ||
|
|
8ee6257e92 | ||
|
|
d81ef2bc5c | ||
|
|
acb64dff97 | ||
|
|
3f6cf76a8c | ||
|
|
3ef2dab465 | ||
|
|
a5a56dd067 | ||
|
|
04957a6d30 | ||
|
|
5da54888f8 | ||
|
|
6c93365b0f | ||
|
|
1c4a8bfb66 | ||
|
|
d51a1d3b3d | ||
|
|
aced2e7da6 | ||
|
|
fa1ceca83a | ||
|
|
0ea05d34e6 | ||
|
|
09db4f672b | ||
|
|
4ba80a3a8c | ||
|
|
ae208d2b17 | ||
|
|
6f51cb3b98 | ||
|
|
f6159ee1a2 | ||
|
|
7f401ae895 | ||
|
|
0587b7043a | ||
|
|
0bbf51d566 | ||
|
|
92c6eae6b0 | ||
|
|
141354cd79 | ||
|
|
f6e9fc7d71 | ||
|
|
d8418be7d1 | ||
|
|
82066946e5 | ||
|
|
4b1defc8d8 | ||
|
|
da90c1cd2c | ||
|
|
3aa54fa027 | ||
|
|
b156db400d | ||
|
|
9aba2b7583 | ||
|
|
a9931223f0 | ||
|
|
aacf9442e4 | ||
|
|
7db10ecf00 | ||
|
|
a0a5b2aea5 | ||
|
|
eb835598a4 | ||
|
|
f0ab6df5b6 | ||
|
|
075144faa3 | ||
|
|
32468a40cb | ||
|
|
38611e9dd7 | ||
|
|
4d78def31e | ||
|
|
3be0c1217a | ||
|
|
42d3a50aa2 | ||
|
|
52f1464029 | ||
|
|
68ce62e2e9 | ||
|
|
3dd41c0d37 | ||
|
|
7699a1f827 | ||
|
|
e473a00f97 | ||
|
|
52f2d580eb | ||
|
|
d7b1e3576f | ||
|
|
93799fbe9d | ||
|
|
b84644740d | ||
|
|
2dc35c1399 | ||
|
|
2cb171f6f5 | ||
|
|
a939cd9c89 | ||
|
|
d5270d113b | ||
|
|
b20903960b | ||
|
|
c0cb545b41 | ||
|
|
35c9f66a75 | ||
|
|
796d03d105 | ||
|
|
8723caf78d | ||
|
|
187f50a344 | ||
|
|
8d04606c4d | ||
|
|
b82d4f6e58 | ||
|
|
87e34967ef | ||
|
|
e32499c546 | ||
|
|
aa0b49228d | ||
|
|
57301a7f9c | ||
|
|
d1842ea8fb | ||
|
|
558151061e | ||
|
|
181723e573 | ||
|
|
6bc1db44bc | ||
|
|
737b57ed5f | ||
|
|
4d287d1ae2 | ||
|
|
f26eb5ada4 | ||
|
|
94ed275ba6 | ||
|
|
ac2f44da33 | ||
|
|
75fa1fbfbf | ||
|
|
5e689faea8 | ||
|
|
649a50b401 | ||
|
|
e94397a97d | ||
|
|
4ec58724d7 | ||
|
|
8cb294aa4a | ||
|
|
2b3a9a52b3 | ||
|
|
138cbb94b2 | ||
|
|
e56d6dea81 | ||
|
|
43f30e44e4 | ||
|
|
9e6db17ef4 | ||
|
|
0e631ad2f2 | ||
|
|
6229d8d2ff | ||
|
|
4647d09b50 | ||
|
|
4ad3a54026 | ||
|
|
05e5feac41 | ||
|
|
67df469c58 | ||
|
|
689e9ccfb5 | ||
|
|
9cd4bc407a | ||
|
|
61996c2bbf | ||
|
|
6d3dd99eb2 | ||
|
|
f0b484892c | ||
|
|
8352cbb7a3 | ||
|
|
6da08b71dc | ||
|
|
5d99059bf9 | ||
|
|
fa41b106ab | ||
|
|
4e3fd7d420 | ||
|
|
791d8354da | ||
|
|
10f19e6fc3 | ||
|
|
4c61a13057 | ||
|
|
7b3f62244f | ||
|
|
d347928e4d | ||
|
|
cc31079a11 | ||
|
|
4676648b78 | ||
|
|
c7594c9111 | ||
|
|
173cb7359d | ||
|
|
af295879fb | ||
|
|
95dd20a151 | ||
|
|
b65fce86bf | ||
|
|
3b8d3bbcbf | ||
|
|
f9e976467f | ||
|
|
118a27be2f | ||
|
|
59c89428e5 | ||
|
|
202ca5e782 | ||
|
|
d6f185d8e5 | ||
|
|
54ca474dba | ||
|
|
1ca383b23b | ||
|
|
179fde3a7b | ||
|
|
50198ffcf1 | ||
|
|
a446c25598 | ||
|
|
a7fb831035 | ||
|
|
4f5e0c9f85 | ||
|
|
8164b91dc4 | ||
|
|
4d5fca27ef | ||
|
|
fe59e4b9fe | ||
|
|
5c88685495 | ||
|
|
9359431bad | ||
|
|
72716f51ce | ||
|
|
382deef750 | ||
|
|
161e211734 | ||
|
|
263a248119 | ||
|
|
725251d294 | ||
|
|
4dff873013 | ||
|
|
60ede67abd | ||
|
|
906bfc8464 | ||
|
|
0d4f08ad9c | ||
|
|
a52bf87b7d | ||
|
|
40c7645d6e | ||
|
|
5b886a23fd | ||
|
|
65797caa7b | ||
|
|
66abb39880 | ||
|
|
95a12e0ee8 | ||
|
|
27951442b8 | ||
|
|
c42e053ae9 | ||
|
|
e7048c8c8b | ||
|
|
d8e0b6c977 | ||
|
|
5e6c34c61c | ||
|
|
828f073ebd | ||
|
|
2dd5701ac0 | ||
|
|
531439198e | ||
|
|
3d9a4d585e | ||
|
|
54eda59286 | ||
|
|
5a4f75c9f8 | ||
|
|
7810f665f1 | ||
|
|
697e2dd330 | ||
|
|
936c64ff51 | ||
|
|
1ea6549548 | ||
|
|
32d9949e4d | ||
|
|
01ba56a8a6 | ||
|
|
e109c42515 | ||
|
|
e4c7091647 | ||
|
|
960b6e5897 | ||
|
|
82eef8d5ee | ||
|
|
aa3848b2c8 | ||
|
|
3b5d0d141a | ||
|
|
c8fc715fe2 | ||
|
|
e5fe3a8e16 | ||
|
|
e0c6cd3dcc | ||
|
|
2edd510ab7 | ||
|
|
2b3e2ebc11 | ||
|
|
ab4cb59326 | ||
|
|
57c8615af3 | ||
|
|
b903173211 | ||
|
|
10cc8b89c4 | ||
|
|
5d9ae3cdb4 | ||
|
|
192d251ee8 | ||
|
|
031962608b | ||
|
|
25f6f478a5 | ||
|
|
e80f09f849 | ||
|
|
c159f91f06 | ||
|
|
eb790a74d2 | ||
|
|
e47451f5a0 | ||
|
|
252b8c83bf | ||
|
|
09666ff294 | ||
|
|
baf2e501dc | ||
|
|
5ac60f0a20 | ||
|
|
fb2ee8ec34 | ||
|
|
94e0db7963 | ||
|
|
b253246959 | ||
|
|
1ac73a247e | ||
|
|
2014115bca | ||
|
|
4a944dc397 | ||
|
|
3838cc4ec4 | ||
|
|
85748f2e6f | ||
|
|
d7b8aa56dc | ||
|
|
16e096cf86 | ||
|
|
50af74c38f | ||
|
|
bfc209b120 | ||
|
|
e7f9331e4b | ||
|
|
ab8e8aa2a1 | ||
|
|
1ef826d1da | ||
|
|
52bddaa97b | ||
|
|
e4dc3908bb | ||
|
|
1daadb812f | ||
|
|
9c2723391b | ||
|
|
7a8796414c | ||
|
|
f8f13c536f | ||
|
|
1adb69c0fd | ||
|
|
5f5830b960 | ||
|
|
9fb4f35bb6 | ||
|
|
c002e6f926 | ||
|
|
c154e5262e | ||
|
|
6ddef1cca6 | ||
|
|
9d68d95825 | ||
|
|
a4233e1a16 | ||
|
|
39373c6d2d | ||
|
|
d29acc90a2 | ||
|
|
a371235b0d | ||
|
|
53b4891a5e | ||
|
|
646ded9123 | ||
|
|
ea0b8f48e6 | ||
|
|
2067d7e300 | ||
|
|
866571ab41 | ||
|
|
4e1fa03087 | ||
|
|
b45572167d | ||
|
|
57a160f1b3 | ||
|
|
29ae8640d9 | ||
|
|
ee6377e54b | ||
|
|
b0f1ae7ea3 | ||
|
|
7aae2b72dc | ||
|
|
73fcbbd748 | ||
|
|
e7bedde835 | ||
|
|
7253edb1e1 | ||
|
|
efa28125c6 | ||
|
|
9832fcfe14 | ||
|
|
49c71f9f2d | ||
|
|
791770cf6e | ||
|
|
9ce9188ff6 | ||
|
|
362066a9b7 | ||
|
|
26ff9371d9 | ||
|
|
4a36f86c81 | ||
|
|
85144e47ff | ||
|
|
b417d961ec | ||
|
|
ef4ea84cb5 | ||
|
|
b422665a3c | ||
|
|
186dadf14d | ||
|
|
04e64db945 | ||
|
|
f60994ad24 | ||
|
|
cfa1ca96f2 | ||
|
|
4d9ff76433 | ||
|
|
9e1b7e0464 | ||
|
|
a77c6ff3a2 | ||
|
|
099fde97d5 | ||
|
|
f8fc2463ee | ||
|
|
e246b78846 | ||
|
|
c1e128bd5a | ||
|
|
8284075ee4 | ||
|
|
f7db09a128 | ||
|
|
f9c3d54bd1 | ||
|
|
0773f4033e | ||
|
|
d068fb321f | ||
|
|
8d054c940c | ||
|
|
80f1d79218 | ||
|
|
64f5413253 | ||
|
|
2abbbd9e70 | ||
|
|
a5c471af7e | ||
|
|
edd2f0232c | ||
|
|
b2c3b2dd8e | ||
|
|
4f1cecb8e7 | ||
|
|
b336eac343 | ||
|
|
2a09f6fa45 | ||
|
|
0e702eb799 | ||
|
|
dea841103d | ||
|
|
82856cf816 | ||
|
|
8aecda03ed | ||
|
|
5c817082a0 | ||
|
|
15c521a7fe | ||
|
|
989de4a1bf | ||
|
|
d9eeb45b03 | ||
|
|
fe570e000c | ||
|
|
01dc0249de | ||
|
|
93523d572e | ||
|
|
4f7a4464df | ||
|
|
e09293a15e | ||
|
|
827b17a52b | ||
|
|
a610379965 | ||
|
|
4e2c3051be | ||
|
|
50915cb7ed | ||
|
|
f4e2d26d58 | ||
|
|
cb0051ae60 | ||
|
|
a238cec12b | ||
|
|
393bf23c0c | ||
|
|
e7d9ba135c | ||
|
|
0a0003c110 | ||
|
|
7e1b27554c | ||
|
|
fb2a56e2d6 | ||
|
|
84218bfb45 | ||
|
|
dd78243406 | ||
|
|
484cf9c0e8 | ||
|
|
a04d1b4f97 | ||
|
|
831c10bdfc | ||
|
|
87603e400d | ||
|
|
4426216725 | ||
|
|
bc15b953b4 | ||
|
|
6d20b12043 | ||
|
|
2385c2a430 | ||
|
|
87384ea684 | ||
|
|
04dae799a2 | ||
|
|
0768c39036 | ||
|
|
8dd8d4d2d4 | ||
|
|
49b06beedf | ||
|
|
4c562a4457 | ||
|
|
fdbbf11887 | ||
|
|
f1e64b349a | ||
|
|
224f3a05cf | ||
|
|
ff56d6861d | ||
|
|
1873fbefba | ||
|
|
80b479e502 | ||
|
|
1f7c9adeeb | ||
|
|
9ebc3b058d | ||
|
|
e21b443a45 | ||
|
|
da590120c4 | ||
|
|
561d53885e | ||
|
|
44ad67ca8c | ||
|
|
3fe8fc75aa | ||
|
|
3cc2da3328 | ||
|
|
a3cd90dd71 | ||
|
|
d6cfdd3bae | ||
|
|
ba08baabb9 | ||
|
|
497b712f67 | ||
|
|
f00dfed7ac | ||
|
|
3c08461685 | ||
|
|
5ef2b4fdc0 | ||
|
|
23d2326d1d | ||
|
|
e338f9f190 | ||
|
|
c8ff626fe2 | ||
|
|
4e424d51f4 | ||
|
|
6b50323b07 | ||
|
|
65c148536d | ||
|
|
f99f62bee4 | ||
|
|
365f5449ca | ||
|
|
ff52f207cc | ||
|
|
ee0eed143a | ||
|
|
5127380727 | ||
|
|
ced654880c | ||
|
|
936d3b9f83 | ||
|
|
6e31230adc | ||
|
|
05ebe93180 | ||
|
|
aaf24e2552 | ||
|
|
8d961dfd25 | ||
|
|
659b37ef9d | ||
|
|
0abf6c9045 | ||
|
|
4630191fa4 | ||
|
|
b7b178f49c | ||
|
|
687066af3d | ||
|
|
6b168ab0c8 | ||
|
|
948625de9d | ||
|
|
3848eb8b16 | ||
|
|
3abe0b9d49 | ||
|
|
d7fabe81fe | ||
|
|
1dc81669c2 | ||
|
|
01d0e12603 | ||
|
|
397e569aaf | ||
|
|
79267f9e60 | ||
|
|
48ebe5736a | ||
|
|
c2064c78b2 | ||
|
|
36608a283b | ||
|
|
a1c87e1e15 | ||
|
|
fa7240a501 | ||
|
|
ffb4d38e24 | ||
|
|
f57c188f2e | ||
|
|
8471c4fb26 | ||
|
|
c97acd18e7 | ||
|
|
ffb590bfcc | ||
|
|
6137f98eb5 | ||
|
|
a6f6539691 | ||
|
|
10c038d9bf | ||
|
|
2d2eaa3eff | ||
|
|
4d28b1f0cd | ||
|
|
3de800a607 | ||
|
|
eff5923778 | ||
|
|
a79faace1b | ||
|
|
9550777b9d | ||
|
|
c8521a3c33 | ||
|
|
d71eb2cf39 | ||
|
|
160fb740f4 | ||
|
|
48e9f39513 | ||
|
|
8afa596fdf | ||
|
|
d3e45c297c | ||
|
|
2c98939c18 | ||
|
|
a18a7409fb | ||
|
|
2f19cf4524 | ||
|
|
da96707dca | ||
|
|
c3a8bdc240 | ||
|
|
21624ef273 | ||
|
|
1032c9b917 | ||
|
|
2e07902d76 | ||
|
|
6e23e1840a | ||
|
|
3e22e45066 | ||
|
|
79d1bd6c8f | ||
|
|
fe341a16f5 | ||
|
|
62abf46b3f | ||
|
|
a95a5e0d9b | ||
|
|
d6f6ceaba5 | ||
|
|
0922f8af59 | ||
|
|
6812302ff9 | ||
|
|
f3f86b8e78 | ||
|
|
1a2680b9e5 | ||
|
|
435bbb6a8c | ||
|
|
3cf44e0a53 | ||
|
|
40b367513f | ||
|
|
9f563d584a | ||
|
|
af4adf5379 | ||
|
|
2560146da3 | ||
|
|
eae3a6397a | ||
|
|
959611420b | ||
|
|
9522f2e8c7 | ||
|
|
e42a0b6cf0 | ||
|
|
d1c7032dec | ||
|
|
d241bc81ae | ||
|
|
cb7f39afa1 | ||
|
|
99b5ad9ebb | ||
|
|
c14b237757 | ||
|
|
d447c7dc32 | ||
|
|
247420c9c1 | ||
|
|
04b112e004 | ||
|
|
be0ce99007 | ||
|
|
69e8d0b65d | ||
|
|
94e685e1bd | ||
|
|
5899f3dd28 | ||
|
|
f82aa1d564 | ||
|
|
fe5c2cf4b7 | ||
|
|
43d40c6e9e | ||
|
|
3d44d8f79c | ||
|
|
ba6fe8ff2e | ||
|
|
5337258888 | ||
|
|
29bf9d6ef1 | ||
|
|
483beb6361 | ||
|
|
fdaec77594 | ||
|
|
8494a5761b | ||
|
|
45590eea22 | ||
|
|
834a64920b | ||
|
|
2c2ccb3618 | ||
|
|
fb5c8c39ae | ||
|
|
f7d39193a4 | ||
|
|
aec796b212 | ||
|
|
fb13bb2393 | ||
|
|
c517ec6779 | ||
|
|
e8cbf2a717 | ||
|
|
e9c86df468 | ||
|
|
6ba8c289c5 | ||
|
|
3f1672e89f | ||
|
|
15be5cbf1f | ||
|
|
4cf0e5e6db | ||
|
|
6b1898f12e | ||
|
|
b3426e9c0d | ||
|
|
38c1a1f3e0 | ||
|
|
4488e25f16 | ||
|
|
cfdb3058ee | ||
|
|
64adff5fea | ||
|
|
6efc58e3db | ||
|
|
f393989a5b | ||
|
|
d6ed20c1e4 | ||
|
|
7c524014c8 | ||
|
|
406d055f07 | ||
|
|
04a90b5dd1 | ||
|
|
8c5bfa0132 | ||
|
|
bc80c55353 | ||
|
|
9c3b51ca0f | ||
|
|
26584ff145 | ||
|
|
42c3d52863 | ||
|
|
64e72f7103 | ||
|
|
e955037980 | ||
|
|
fb99910c23 | ||
|
|
e620bd4d3f | ||
|
|
a44e761d9e | ||
|
|
ea1974d576 | ||
|
|
85a0bd43c2 | ||
|
|
278e0f126e | ||
|
|
d8652cfd4f | ||
|
|
377b7065aa | ||
|
|
1e9c79c587 | ||
|
|
78147aa342 | ||
|
|
cd4a2265b9 | ||
|
|
767ac1de10 | ||
|
|
d762215d13 | ||
|
|
1fd09593cf | ||
|
|
e45a0f6ce2 | ||
|
|
94f8525721 | ||
|
|
d73cf64e54 | ||
|
|
f945462bab | ||
|
|
b05946175b | ||
|
|
62f0f8190d | ||
|
|
bf8c0da4be | ||
|
|
dfdd6b3891 | ||
|
|
f5e0fc3e9a | ||
|
|
d741101fe3 | ||
|
|
e1620799c7 | ||
|
|
749c7adb13 | ||
|
|
921a733911 | ||
|
|
26d0004fe1 | ||
|
|
948af6d5b5 | ||
|
|
670a187a3c | ||
|
|
be9f725023 | ||
|
|
daf3f4cb1a | ||
|
|
5acda4cc71 | ||
|
|
8452af606b | ||
|
|
630d449520 | ||
|
|
7372cf7d99 | ||
|
|
b7e46c558f | ||
|
|
bf8f8710ea | ||
|
|
6ffe5b775d | ||
|
|
be0805b85b | ||
|
|
65b2359b27 | ||
|
|
8651aa73e8 | ||
|
|
78b542737a | ||
|
|
fccf86532f | ||
|
|
1857417601 | ||
|
|
ee7114a58c | ||
|
|
00fa91d0d6 | ||
|
|
b7a25bfc33 | ||
|
|
a2e46b9a1b | ||
|
|
a751fa22d2 | ||
|
|
e563a0b7db | ||
|
|
49085ca943 | ||
|
|
560a850a2b | ||
|
|
66782e2317 | ||
|
|
b60eb1544b | ||
|
|
cbe59fa3bf | ||
|
|
c97c6dc065 | ||
|
|
32fa97d68d | ||
|
|
aee4603269 | ||
|
|
29c7da5f1a | ||
|
|
6131f4e32b | ||
|
|
67e03e625d | ||
|
|
b124f9101b | ||
|
|
d11a3a6380 | ||
|
|
4cc0706b06 | ||
|
|
885f5a9781 | ||
|
|
60b5964577 | ||
|
|
6e1919414e | ||
|
|
8c8ec5e63e | ||
|
|
b8413ddd5b | ||
|
|
5d976b6e18 | ||
|
|
2b4317452b | ||
|
|
1c3011ba4b | ||
|
|
574a42f3b4 | ||
|
|
9005cd59e5 | ||
|
|
dd494d4ab7 | ||
|
|
7cca469a12 | ||
|
|
2aed432b4b | ||
|
|
0291a3ff56 | ||
|
|
5d7315280a | ||
|
|
254931b9a8 | ||
|
|
aa89744c95 | ||
|
|
1cda3f5ad7 | ||
|
|
8f1f64ffb6 | ||
|
|
2bc0a7795c | ||
|
|
4204da6ad4 | ||
|
|
7ac39b10f7 | ||
|
|
6b567e0066 | ||
|
|
df299d6edd | ||
|
|
4e34f05238 | ||
|
|
9962f6fd79 | ||
|
|
f9d492f4b1 | ||
|
|
a8bb2ef1c3 | ||
|
|
240c629cda | ||
|
|
952567dd3c | ||
|
|
10b396b4c2 | ||
|
|
699bbe21a4 | ||
|
|
27b67deca6 | ||
|
|
581b7ec553 | ||
|
|
acfbb1a44a | ||
|
|
d85a6d8fe4 | ||
|
|
20fbb5c63b | ||
|
|
1051a06a76 | ||
|
|
98dfc26208 | ||
|
|
1ba0a2cedd | ||
|
|
4afb13f98b | ||
|
|
b27d33675d | ||
|
|
00b9ae77f9 | ||
|
|
65219f3093 | ||
|
|
f78d1d4340 | ||
|
|
941edca597 | ||
|
|
a699435ede | ||
|
|
66d6417189 | ||
|
|
558e37c412 | ||
|
|
4f40d991ea | ||
|
|
549af99007 | ||
|
|
b336930093 | ||
|
|
c9a0edfb8b | ||
|
|
2c5668af46 | ||
|
|
751dea32ae | ||
|
|
cd8f4bfb1f | ||
|
|
a6cfcc6866 | ||
|
|
b8c4f603db | ||
|
|
0075e4b391 | ||
|
|
125af556ce | ||
|
|
963ad5c255 | ||
|
|
387f56cb7b | ||
|
|
b3deda38c9 | ||
|
|
2a5ca77454 | ||
|
|
727940d847 | ||
|
|
8cd42478e1 | ||
|
|
c11d34b26c | ||
|
|
339d7445b3 | ||
|
|
d16f05f2c8 | ||
|
|
5427b32a40 | ||
|
|
f73701239d | ||
|
|
f5a6fc0703 | ||
|
|
bdf5ba91a4 | ||
|
|
bc8f338771 | ||
|
|
3413bfc06a | ||
|
|
2056f0ce09 | ||
|
|
5eb8cfd691 | ||
|
|
e6a4254488 | ||
|
|
d478ad00d0 | ||
|
|
53eda861de | ||
|
|
cc1d86ba63 | ||
|
|
f0528f00e7 | ||
|
|
5cd2ad124d | ||
|
|
6c00e7a902 | ||
|
|
53170bbb58 | ||
|
|
467258e050 | ||
|
|
129be23c9e | ||
|
|
8e9290e86e | ||
|
|
7cf5bebf8e | ||
|
|
f7f9087fb5 | ||
|
|
256e7904fd | ||
|
|
c8ea1b6c38 | ||
|
|
2816b06c05 | ||
|
|
4c695ea088 |
@@ -14,10 +14,10 @@ AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
@@ -157,7 +157,7 @@ SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
Standard: Auto
|
||||
Standard: c++17
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
|
||||
71
.clang-tidy
Normal file
71
.clang-tidy
Normal file
@@ -0,0 +1,71 @@
|
||||
Checks:
|
||||
'bugprone-assert-side-effect,
|
||||
bugprone-bool-pointer-implicit-conversion,
|
||||
bugprone-copy-constructor-init,
|
||||
bugprone-dangling-handle,
|
||||
bugprone-dynamic-static-initializers,
|
||||
bugprone-forward-declaration-namespace,
|
||||
bugprone-forwarding-reference-overload,
|
||||
bugprone-inaccurate-erase,
|
||||
bugprone-incorrect-roundings,
|
||||
bugprone-integer-division,
|
||||
bugprone-lambda-function-name,
|
||||
bugprone-misplaced-operator-in-strlen-in-alloc,
|
||||
bugprone-misplaced-widening-cast,
|
||||
bugprone-move-forwarding-reference,
|
||||
bugprone-multiple-statement-macro,
|
||||
bugprone-parent-virtual-call,
|
||||
bugprone-posix-return,
|
||||
bugprone-sizeof-container,
|
||||
bugprone-sizeof-expression,
|
||||
bugprone-spuriously-wake-up-functions,
|
||||
bugprone-string-constructor,
|
||||
bugprone-string-integer-assignment,
|
||||
bugprone-string-literal-with-embedded-nul,
|
||||
bugprone-suspicious-enum-usage,
|
||||
bugprone-suspicious-include,
|
||||
bugprone-suspicious-memset-usage,
|
||||
bugprone-suspicious-missing-comma,
|
||||
bugprone-suspicious-semicolon,
|
||||
bugprone-suspicious-string-compare,
|
||||
bugprone-throw-keyword-missing,
|
||||
bugprone-too-small-loop-variable,
|
||||
bugprone-undefined-memory-manipulation,
|
||||
bugprone-undelegated-constructor,
|
||||
bugprone-unhandled-self-assignment,
|
||||
bugprone-unused-raii,
|
||||
bugprone-virtual-near-miss,
|
||||
cert-dcl58-cpp,
|
||||
cert-err52-cpp,
|
||||
cert-err60-cpp,
|
||||
cert-mem57-cpp,
|
||||
cert-oop57-cpp,
|
||||
cert-oop58-cpp,
|
||||
clang-diagnostic-*,
|
||||
-clang-diagnostic-deprecated-declarations,
|
||||
-clang-diagnostic-#warnings,
|
||||
-clang-diagnostic-pedantic,
|
||||
clang-analyzer-*,
|
||||
cppcoreguidelines-slicing,
|
||||
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,
|
||||
misc-misplaced-const,
|
||||
misc-new-delete-overloads,
|
||||
misc-non-copyable-objects,
|
||||
modernize-avoid-bind,
|
||||
modernize-concat-nested-namespaces,
|
||||
modernize-make-shared,
|
||||
modernize-make-unique,
|
||||
modernize-pass-by-value,
|
||||
modernize-use-default-member-init,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-override,
|
||||
modernize-use-using,
|
||||
readability-braces-around-statements'
|
||||
FormatStyle: file
|
||||
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
*.gradle text eol=lf
|
||||
*.java text eol=lf
|
||||
*.md text eol=lf
|
||||
*.xml text eol=lf
|
||||
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
3
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -22,7 +22,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):**
|
||||
- OS: [e.g. Windows]
|
||||
- WPILib Version: [e.g. 2021.3.1]
|
||||
- OS: [e.g. Windows 11]
|
||||
- Java version [e.g. 1.10.2]
|
||||
- C++ version [e.g. 17]
|
||||
|
||||
|
||||
238
.github/workflows/ci.yml
vendored
238
.github/workflows/ci.yml
vendored
@@ -1,238 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- container: wpilib/roborio-cross-ubuntu:2021-18.04
|
||||
artifact-name: Athena
|
||||
build-options: "-Ponlylinuxathena"
|
||||
- container: wpilib/raspbian-cross-ubuntu:10-18.04
|
||||
artifact-name: Raspbian
|
||||
build-options: "-Ponlylinuxraspbian"
|
||||
- container: wpilib/aarch64-cross-ubuntu:bionic-18.04
|
||||
artifact-name: Aarch64
|
||||
build-options: "-Ponlylinuxaarch64bionic"
|
||||
- container: wpilib/ubuntu-base:18.04
|
||||
artifact-name: Linux
|
||||
build-options: "-Dorg.gradle.jvmargs=-Xmx2g"
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ubuntu-latest
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
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 -PbuildServer ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: build/allOutputs
|
||||
|
||||
build-host:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
artifact-name: Win64
|
||||
architecture: x64
|
||||
- os: windows-latest
|
||||
artifact-name: Win32
|
||||
architecture: x86
|
||||
- os: macos-latest
|
||||
artifact-name: macOS
|
||||
architecture: x64
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
architecture: ${{ matrix.architecture }}
|
||||
- name: Import Developer ID Certificate
|
||||
uses: wpilibsuite/import-signing-certificate@v1
|
||||
with:
|
||||
certificate-data: ${{ secrets.APPLE_CERTIFICATE_DATA }}
|
||||
certificate-passphrase: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- name: Set Keychain Lock Timeout
|
||||
run: security set-keychain-settings -lut 3600
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- name: Set release environment variable
|
||||
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
- name: Sign Libraries with Developer ID
|
||||
run: ./gradlew build -PbuildServer -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: build/allOutputs
|
||||
|
||||
build-documentation:
|
||||
name: "Build - Documentation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 13
|
||||
- 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 docs:zipDocs -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Documentation
|
||||
path: docs/build/outputs
|
||||
|
||||
build-cmake:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
name: Linux
|
||||
container: wpilib/roborio-cross-ubuntu:2020-18.04
|
||||
flags: ""
|
||||
- os: macos-latest
|
||||
name: macOS
|
||||
container: ""
|
||||
flags: "-DWITH_JAVA=OFF"
|
||||
name: "Build - CMake ${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
if [ "$RUNNER_OS" == "macOS" ]; then
|
||||
brew install opencv
|
||||
fi
|
||||
- name: configure
|
||||
run: mkdir build && cd build && cmake -DWITH_GUI=OFF ${{ matrix.flags }} ..
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: make -j3
|
||||
- name: test
|
||||
working-directory: build
|
||||
run: make test
|
||||
|
||||
build-cmake-vcpkg:
|
||||
name: "Build - CMake Windows"
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Prepare vcpkg
|
||||
uses: lukka/run-vcpkg@v4
|
||||
with:
|
||||
vcpkgArguments: opencv
|
||||
vcpkgDirectory: ${{ runner.workspace }}/vcpkg/
|
||||
vcpkgGitCommitId: 544f8e4593764f78faa94bac2adb81cca5232943
|
||||
vcpkgTriplet: x64-windows
|
||||
- name: Configure & Build
|
||||
uses: lukka/run-cmake@v3
|
||||
with:
|
||||
buildDirectory: ${{ runner.workspace }}/build/
|
||||
cmakeAppendedArgs: -DWITH_JAVA=OFF
|
||||
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
|
||||
useVcpkgToolchainFile: true
|
||||
- name: Run Tests
|
||||
run: ctest -C "Debug"
|
||||
working-directory: ${{ runner.workspace }}/build/
|
||||
|
||||
wpiformat:
|
||||
name: "wpiformat"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Fetch all history and metadata
|
||||
run: |
|
||||
git fetch --prune --unshallow
|
||||
git checkout -b pr
|
||||
git branch -f master origin/master
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Install clang-format
|
||||
run: sudo apt-get update -q && sudo apt-get install clang-format-10
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
- name: Run
|
||||
run: wpiformat -clang 10
|
||||
- name: Check Output
|
||||
run: git --no-pager diff --exit-code HEAD
|
||||
|
||||
combine:
|
||||
name: Combine
|
||||
needs: [build-docker, build-host, build-documentation]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
repository: wpilibsuite/build-tools
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: combiner/products/build/allOutputs
|
||||
- name: Flatten Artifacts
|
||||
run: rsync -a --delete combiner/products/build/allOutputs/*/* combiner/products/build/allOutputs/
|
||||
- name: Check version number exists
|
||||
run: |
|
||||
cat combiner/products/build/allOutputs/version.txt
|
||||
test -s combiner/products/build/allOutputs/version.txt
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Combine
|
||||
if: |
|
||||
!startsWith(github.ref, 'refs/tags/v') &&
|
||||
github.ref != 'refs/heads/master'
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib
|
||||
- name: Combine (Master)
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
github.ref == 'refs/heads/master'
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib
|
||||
env:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- name: Combine (Release)
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib -PreleaseRepoPublish
|
||||
env:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Maven
|
||||
path: ~/releases
|
||||
51
.github/workflows/cmake.yml
vendored
Normal file
51
.github/workflows/cmake.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: CMake
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
name: Linux
|
||||
container: wpilib/roborio-cross-ubuntu:2022-20.04
|
||||
flags: ""
|
||||
- os: macOS-11
|
||||
name: macOS
|
||||
container: ""
|
||||
flags: "-DWITH_JAVA=OFF"
|
||||
|
||||
name: "Build - ${{ matrix.name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install opencv (macOS)
|
||||
run: brew install opencv
|
||||
if: runner.os == 'macOS'
|
||||
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
|
||||
- name: configure
|
||||
run: mkdir build && cd build && cmake ${{ matrix.flags }} ..
|
||||
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc)
|
||||
|
||||
- name: test
|
||||
working-directory: build
|
||||
run: ctest --output-on-failure
|
||||
57
.github/workflows/comment-command.yml
vendored
Normal file
57
.github/workflows/comment-command.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: Comment Commands
|
||||
on:
|
||||
issue_comment:
|
||||
types: [ created ]
|
||||
|
||||
jobs:
|
||||
wpiformat:
|
||||
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/wpiformat')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: React Rocket
|
||||
uses: actions/github-script@v4
|
||||
with:
|
||||
script: |
|
||||
const {owner, repo} = context.issue
|
||||
github.reactions.createForIssueComment({
|
||||
owner,
|
||||
repo,
|
||||
comment_id: context.payload.comment.id,
|
||||
content: "rocket",
|
||||
});
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
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
|
||||
run: |
|
||||
gh pr checkout $NUMBER
|
||||
env:
|
||||
GITHUB_TOKEN: "${{ secrets.COMMENT_COMMAND_PAT_TOKEN }}"
|
||||
NUMBER: ${{ github.event.issue.number }}
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
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/focal/ llvm-toolchain-focal-14 main' >> /etc/apt/sources.list.d/proposed-repositories.list"
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -y clang-format-14
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
- name: Run wpiformat
|
||||
run: wpiformat -clang 14
|
||||
- name: Commit
|
||||
run: |
|
||||
# Set credentials
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
# Commit
|
||||
git commit -am "wpiformat"
|
||||
git push
|
||||
65
.github/workflows/documentation.yml
vendored
Normal file
65
.github/workflows/documentation.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Documentation
|
||||
|
||||
on: [push, workflow_dispatch]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
BASE_PATH: allwpilib/docs
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: "Documentation - Publish"
|
||||
runs-on: ubuntu-latest
|
||||
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
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 13
|
||||
- name: Install libclang-9
|
||||
run: sudo apt update && sudo apt install -y libclang-cpp9 libclang1-9
|
||||
- name: Set environment variables (Development)
|
||||
run: |
|
||||
echo "TARGET_FOLDER=$BASE_PATH/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
|
||||
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
|
||||
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.4.1
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.GH_DEPLOY_KEY }}
|
||||
- name: Deploy Java 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@3.7.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
|
||||
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
|
||||
19
.github/workflows/gazebo.yml
vendored
Normal file
19
.github/workflows/gazebo.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Gazebo
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build"
|
||||
runs-on: ubuntu-latest
|
||||
container: wpilib/gazebo-ubuntu:20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew simulation:frc_gazebo_plugins:build simulation:halsim_gazebo:build -PbuildServer -PforceGazebo
|
||||
@@ -1,10 +1,14 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
on: [pull_request, push]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
|
||||
183
.github/workflows/gradle.yml
vendored
Normal file
183
.github/workflows/gradle.yml
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
name: Gradle
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-docker:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- container: wpilib/roborio-cross-ubuntu:2022-20.04
|
||||
artifact-name: Athena
|
||||
build-options: "-Ponlylinuxathena"
|
||||
- container: wpilib/raspbian-cross-ubuntu:10-20.04
|
||||
artifact-name: Arm32
|
||||
build-options: "-Ponlylinuxarm32"
|
||||
- container: wpilib/aarch64-cross-ubuntu:bionic-20.04
|
||||
artifact-name: Arm64
|
||||
build-options: "-Ponlylinuxarm64"
|
||||
- container: wpilib/ubuntu-base:20.04
|
||||
artifact-name: Linux
|
||||
build-options: "-Ponlylinuxx86-64"
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ubuntu-latest
|
||||
container: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
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 }}
|
||||
env:
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: build/allOutputs
|
||||
|
||||
build-host:
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.14
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-2019
|
||||
artifact-name: Win64Debug
|
||||
architecture: x64
|
||||
task: "build"
|
||||
build-options: "-PciDebugOnly --max-workers 1"
|
||||
- os: windows-2019
|
||||
artifact-name: Win64Release
|
||||
architecture: x64
|
||||
build-options: "-PciReleaseOnly --max-workers 1"
|
||||
task: "copyAllOutputs"
|
||||
- os: macOS-11
|
||||
artifact-name: macOS
|
||||
architecture: x64
|
||||
build-options: "-Pbuildalldesktop"
|
||||
task: "build"
|
||||
name: "Build - ${{ matrix.artifact-name }}"
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
architecture: ${{ matrix.architecture }}
|
||||
- name: Import Developer ID Certificate
|
||||
uses: wpilibsuite/import-signing-certificate@v1
|
||||
with:
|
||||
certificate-data: ${{ secrets.APPLE_CERTIFICATE_DATA }}
|
||||
certificate-passphrase: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- name: Set Keychain Lock Timeout
|
||||
run: security set-keychain-settings -lut 3600
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- name: Set release environment variable
|
||||
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew ${{ matrix.task }} --build-cache -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
env:
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- name: Sign Libraries with Developer ID
|
||||
run: ./gradlew build -PbuildServer -PskipJavaFormat -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
if: |
|
||||
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ matrix.artifact-name }}
|
||||
path: build/allOutputs
|
||||
|
||||
build-documentation:
|
||||
name: "Build - Documentation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 13
|
||||
- name: Install libclang-9
|
||||
run: sudo apt update && sudo apt install -y libclang-cpp9 libclang1-9
|
||||
- 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 docs:zipDocs --build-cache -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
env:
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Documentation
|
||||
path: docs/build/outputs
|
||||
|
||||
combine:
|
||||
name: Combine
|
||||
needs: [build-docker, build-host, build-documentation]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: wpilibsuite/build-tools
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: combiner/products/build/allOutputs
|
||||
- name: Flatten Artifacts
|
||||
run: rsync -a --delete combiner/products/build/allOutputs/*/* combiner/products/build/allOutputs/
|
||||
- name: Check version number exists
|
||||
run: |
|
||||
cat combiner/products/build/allOutputs/version.txt
|
||||
test -s combiner/products/build/allOutputs/version.txt
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Combine
|
||||
if: |
|
||||
!startsWith(github.ref, 'refs/tags/v') &&
|
||||
github.ref != 'refs/heads/main'
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib
|
||||
- name: Combine (Master)
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
github.ref == 'refs/heads/main'
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib
|
||||
env:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- name: Combine (Release)
|
||||
if: |
|
||||
github.repository_owner == 'wpilibsuite' &&
|
||||
startsWith(github.ref, 'refs/tags/v')
|
||||
run: cd combiner && ./gradlew publish -Pallwpilib -PreleaseRepoPublish
|
||||
env:
|
||||
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
|
||||
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
|
||||
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Maven
|
||||
path: ~/releases
|
||||
111
.github/workflows/lint-format.yml
vendored
Normal file
111
.github/workflows/lint-format.yml
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
name: Lint and Format
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches-ignore:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
wpiformat:
|
||||
name: "wpiformat"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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@v2
|
||||
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/focal/ llvm-toolchain-focal-14 main' >> /etc/apt/sources.list.d/proposed-repositories.list"
|
||||
sudo apt-get update -q
|
||||
sudo apt-get install -y clang-format-14
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
- name: Run
|
||||
run: wpiformat -clang 14
|
||||
- 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@v2
|
||||
with:
|
||||
name: wpiformat fixes
|
||||
path: wpiformat-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
tidy:
|
||||
name: "clang-tidy"
|
||||
runs-on: ubuntu-latest
|
||||
container: wpilib/roborio-cross-ubuntu:2022-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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@v2
|
||||
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/focal/ llvm-toolchain-focal-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
|
||||
- name: Install wpiformat
|
||||
run: pip3 install wpiformat
|
||||
- name: Create compile_commands.json
|
||||
run: ./gradlew generateCompileCommands -Ptoolchain-optional-roboRio
|
||||
- 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
|
||||
javaformat:
|
||||
name: "Java format"
|
||||
runs-on: ubuntu-latest
|
||||
container: wpilib/ubuntu-base:20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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
|
||||
run: ./gradlew javaFormat spotbugsMain spotbugsTest spotbugsDev
|
||||
- name: Check output
|
||||
run: git --no-pager diff --exit-code HEAD
|
||||
- name: Generate diff
|
||||
run: git diff HEAD > javaformat-fixes.patch
|
||||
if: ${{ failure() }}
|
||||
documentation:
|
||||
name: "Documentation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 13
|
||||
- name: Install libclang-9
|
||||
run: sudo apt update && sudo apt install -y libclang-cpp9 libclang1-9
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew docs:zipDocs -PbuildServer -PdocWarningsAsErrors ${{ env.EXTRA_GRADLE_ARGS }}
|
||||
59
.github/workflows/sanitizers.yml
vendored
Normal file
59
.github/workflows/sanitizers.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Sanitizers
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: asan
|
||||
cmake-flags: "-DCMAKE_BUILD_TYPE=Asan"
|
||||
ctest-env: ""
|
||||
ctest-flags: "-E 'ntcore|wpilibc'"
|
||||
- name: tsan
|
||||
cmake-flags: "-DCMAKE_BUILD_TYPE=Tsan"
|
||||
ctest-env: "TSAN_OPTIONS=second_deadlock_stack=1"
|
||||
ctest-flags: "-E 'ntcore|cscore|cameraserver|wpilibc|wpilibNewCommands'"
|
||||
- name: ubsan
|
||||
cmake-flags: "-DCMAKE_BUILD_TYPE=Ubsan"
|
||||
ctest-env: ""
|
||||
ctest-flags: ""
|
||||
name: "${{ matrix.name }}"
|
||||
runs-on: ubuntu-latest
|
||||
container: wpilib/roborio-cross-ubuntu:2022-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt install -y gcc-11 g++-11
|
||||
sudo update-alternatives \
|
||||
--install /usr/bin/gcc gcc /usr/bin/gcc-11 11 \
|
||||
--slave /usr/bin/g++ g++ /usr/bin/g++-11
|
||||
sudo update-alternatives --set gcc /usr/bin/gcc-11
|
||||
|
||||
- name: Set up Python 3.8
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
- name: Install jinja
|
||||
run: python -m pip install jinja2
|
||||
|
||||
- name: configure
|
||||
run: mkdir build && cd build && cmake ${{ matrix.cmake-flags }} ..
|
||||
|
||||
- name: build
|
||||
working-directory: build
|
||||
run: cmake --build . --parallel $(nproc)
|
||||
|
||||
- name: test
|
||||
working-directory: build
|
||||
run: ${{ matrix.ctest-env }} ctest --output-on-failure ${{ matrix.ctest-flags }}
|
||||
63
.github/workflows/upstream-utils.yml
vendored
Normal file
63
.github/workflows/upstream-utils.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
name: Upstream utils
|
||||
|
||||
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-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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@v2
|
||||
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
|
||||
./update_eigen.py
|
||||
- name: Run update_fmt.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_fmt.py
|
||||
- name: Run update_libuv.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_libuv.py
|
||||
- name: Run update_llvm.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_llvm.py
|
||||
- name: Run update_stack_walker.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_stack_walker.py
|
||||
- name: Run update_memory.py
|
||||
run: |
|
||||
cd upstream_utils
|
||||
./update_memory.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
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -222,5 +222,12 @@ compile_commands.json
|
||||
# clang configuration and clangd cache
|
||||
.clang
|
||||
.clangd/
|
||||
.cache/
|
||||
|
||||
imgui.ini
|
||||
|
||||
# Bazel
|
||||
/.ijwb/
|
||||
/bazel-*
|
||||
user.bazelrc
|
||||
coverage_report/
|
||||
|
||||
@@ -9,9 +9,15 @@ cppSrcFileInclude {
|
||||
\.cpp$
|
||||
}
|
||||
|
||||
modifiableFileExclude {
|
||||
\.patch$
|
||||
gradlew
|
||||
}
|
||||
|
||||
generatedFileExclude {
|
||||
FRCNetComm\.java$
|
||||
simulation/gz_msgs/src/include/simulation/gz_msgs/msgs\.h$
|
||||
fieldImages/src/main/native/resources/
|
||||
}
|
||||
|
||||
repoRootNameOverride {
|
||||
@@ -23,6 +29,7 @@ includeOtherLibs {
|
||||
^cameraserver/
|
||||
^cscore
|
||||
^drake/
|
||||
^fmt/
|
||||
^hal/
|
||||
^imgui
|
||||
^implot
|
||||
@@ -37,4 +44,5 @@ includeOtherLibs {
|
||||
^wpi/
|
||||
^wpigui
|
||||
^wpimath/
|
||||
^wpinet/
|
||||
}
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) {year} FIRST. All Rights Reserved.{padding}*/
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"enableCppIntellisense": true,
|
||||
"currentLanguage": "cpp",
|
||||
"projectYear": "2020",
|
||||
"projectYear": "intellisense",
|
||||
"teamNumber": 0
|
||||
}
|
||||
|
||||
146
CMakeLists.txt
146
CMakeLists.txt
@@ -1,25 +1,33 @@
|
||||
# Disable in-source builds to prevent source tree corruption.
|
||||
if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")
|
||||
if(" ${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL " ${CMAKE_CURRENT_BINARY_DIR}")
|
||||
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")
|
||||
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()
|
||||
|
||||
project(allwpilib)
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules")
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
message(STATUS "Platform version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
|
||||
|
||||
set(WPILIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
INCLUDE(CPack)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_BINARY_DIR}/jar)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/lib)
|
||||
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)
|
||||
@@ -44,7 +52,9 @@ ENDIF("${isSystemDir}" STREQUAL "-1")
|
||||
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_CSCORE "Build cscore (needs OpenCV)" ON)
|
||||
option(WITH_WPILIB "Build hal, wpilibc/j, wpimath, and myRobot (needs OpenCV)" ON)
|
||||
option(WITH_WPIMATH "Build wpimath" ON)
|
||||
option(WITH_WPILIB "Build hal, wpilibc/j, and myRobot (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)
|
||||
option(WITH_SIMULATION_MODULES "Build simulation modules" ON)
|
||||
@@ -54,6 +64,7 @@ option(WITH_EXTERNAL_HAL "Use a separately built HAL" OFF)
|
||||
set(EXTERNAL_HAL_FILE "" CACHE FILEPATH "Location to look for an external HAL CMake File")
|
||||
|
||||
# Options for using a package manager (vcpkg) for certain dependencies.
|
||||
option(USE_VCPKG_FMTLIB "Use vcpkg fmtlib" OFF)
|
||||
option(USE_VCPKG_LIBUV "Use vcpkg libuv" OFF)
|
||||
option(USE_VCPKG_EIGEN "Use vcpkg eigen" OFF)
|
||||
|
||||
@@ -106,6 +117,13 @@ FATAL: Cannot build simulation modules with wpilib disabled.
|
||||
")
|
||||
endif()
|
||||
|
||||
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 wpilib)
|
||||
set( include_dest wpilib/include )
|
||||
set( main_lib_dest wpilib/lib )
|
||||
@@ -126,27 +144,102 @@ if (USE_VCPKG_EIGEN)
|
||||
set (EIGEN_VCPKG_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)")
|
||||
set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
|
||||
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
|
||||
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
|
||||
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
|
||||
set(WPILIBNEWCOMMANDS_DEP_REPLACE "find_dependency(wpilibNewCommands)")
|
||||
endif()
|
||||
|
||||
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
|
||||
set(SELF_DIR "$\{SELF_DIR\}")
|
||||
|
||||
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
|
||||
if(isMultiConfig)
|
||||
if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
|
||||
endif()
|
||||
if(NOT "Tsan" IN_LIST CMAKE_CONFIGURATION_TYPES)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES Tsan)
|
||||
endif()
|
||||
if(NOT "Ubsan" IN_LIST CMAKE_CONFIGURATION_TYPES)
|
||||
list(APPEND CMAKE_CONFIGURATION_TYPES Ubsan)
|
||||
endif()
|
||||
else()
|
||||
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)
|
||||
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
|
||||
endif()
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
if (WITH_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(googletest)
|
||||
@@ -154,11 +247,28 @@ if (WITH_TESTS)
|
||||
endif()
|
||||
|
||||
add_subdirectory(wpiutil)
|
||||
add_subdirectory(wpinet)
|
||||
add_subdirectory(ntcore)
|
||||
|
||||
if (WITH_WPIMATH)
|
||||
add_subdirectory(wpimath)
|
||||
endif()
|
||||
|
||||
if (WITH_GUI)
|
||||
add_subdirectory(fieldImages)
|
||||
add_subdirectory(imgui)
|
||||
add_subdirectory(wpigui)
|
||||
add_subdirectory(glass)
|
||||
add_subdirectory(outlineviewer)
|
||||
if (LIBSSH_FOUND)
|
||||
add_subdirectory(roborioteamnumbersetter)
|
||||
add_subdirectory(datalogtool)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_WPILIB OR WITH_SIMULATION_MODULES)
|
||||
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(hal)
|
||||
endif()
|
||||
|
||||
if (WITH_CSCORE)
|
||||
@@ -166,20 +276,22 @@ if (WITH_CSCORE)
|
||||
set(CAMERASERVER_DEP_REPLACE ${CAMERASERVER_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(cscore)
|
||||
add_subdirectory(cameraserver)
|
||||
if (WITH_WPILIB)
|
||||
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
|
||||
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(hal)
|
||||
add_subdirectory(wpimath)
|
||||
add_subdirectory(wpilibj)
|
||||
add_subdirectory(wpilibc)
|
||||
add_subdirectory(myRobot)
|
||||
endif()
|
||||
|
||||
if (WITH_WPILIB)
|
||||
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
|
||||
add_subdirectory(wpilibj)
|
||||
add_subdirectory(wpilibc)
|
||||
add_subdirectory(wpilibNewCommands)
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory(wpilibcExamples)
|
||||
endif()
|
||||
add_subdirectory(myRobot)
|
||||
endif()
|
||||
|
||||
if (WITH_SIMULATION_MODULES AND NOT WITH_EXTERNAL_HAL)
|
||||
add_subdirectory(simulation)
|
||||
endif()
|
||||
|
||||
configure_file(wpilib-config.cmake.in ${CMAKE_BINARY_DIR}/wpilib-config.cmake )
|
||||
install(FILES ${CMAKE_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 ${wpilib_config_dir})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to WPILib
|
||||
|
||||
So you want to contribute your changes back to WPILib. Great! We have a few contributing rules that will help you make sure your changes will be accepted into the project. Please remember to follow the rules in the [code of conduct](https://github.com/wpilibsuite/allwpilib/blob/master/CODE_OF_CONDUCT.md), and behave with Gracious Professionalism.
|
||||
So you want to contribute your changes back to WPILib. Great! We have a few contributing rules that will help you make sure your changes will be accepted into the project. Please remember to follow the rules in the [code of conduct](https://github.com/wpilibsuite/allwpilib/blob/main/CODE_OF_CONDUCT.md), and behave with Gracious Professionalism.
|
||||
|
||||
- [General Contribution Rules](#general-contribution-rules)
|
||||
- [What to Contribute](#what-to-contribute)
|
||||
@@ -37,15 +37,17 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
|
||||
|
||||
## Coding Guidelines
|
||||
|
||||
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 10.0 with wpiformat.
|
||||
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 14.0 with wpiformat.
|
||||
|
||||
While the library should be fully formatted according to the styles, additional elements of the style guide were not followed when the library was initially created. All new code should follow the guidelines. If you are looking for some easy ramp-up tasks, finding areas that don't follow the style guide and fixing them is very welcome.
|
||||
|
||||
When writing math expressions in documentation, use https://www.unicodeit.net/ to convert LaTeX to a Unicode equivalent that's easier to read. Not all expressions will translate (e.g., superscripts of superscripts) so focus on making it readable by someone who isn't familiar with LaTeX. If content on multiple lines needs to be aligned in Doxygen/Javadoc comments (e.g., integration/summation limits, matrices packed with square brackets and superscripts for them), put them in @verbatim/@endverbatim blocks in Doxygen or `<pre>` tags in Javadoc so they render with monospace font.
|
||||
|
||||
## Submitting Changes
|
||||
|
||||
### Pull Request Format
|
||||
|
||||
Changes should be submitted as a Pull Request against the master 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 master. We do this to make sure that the git history isn't too cluttered.
|
||||
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.
|
||||
|
||||
### Merge Process
|
||||
|
||||
|
||||
12
LICENSE.md
12
LICENSE.md
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2019 FIRST
|
||||
Copyright (c) 2009-2022 FIRST and other WPILib contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
@@ -8,12 +8,12 @@ modification, are permitted provided that the following conditions are met:
|
||||
* 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 FIRST nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
* Neither the name of FIRST, WPILib, nor the names of other WPILib
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY FIRST AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
## Publishing Third Party Dependencies
|
||||
Currently the 3rd party deps are imgui, opencv, and google test
|
||||
|
||||
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).
|
||||
A variable needs to be added called `RUN_AZURE_ARTIFACTORY_RELEASE`, with a value of `true`. Then when the pipeline gets started, the final build outputs will be updated to artifactory.
|
||||
|
||||
To use newer versions of C++ dependencies, in `shared/config.gradle`, update the version related to the specific dependency.
|
||||
For Java dependencies, there is likely a file related to the specific dependency in the shared folder. Update the version in there.
|
||||
|
||||
Note, changing artifact locations (This includes changing the artifact year currently, I have an issue open to change this) requires updating the `native-utils` plugin
|
||||
|
||||
## Publishing allwpilib
|
||||
allwpilib publishes to the development repo on every push to master. To publish a release build, upload a new tag, and a release will automatically be built and published.
|
||||
|
||||
## Publishing desktop tools
|
||||
Desktop tools publish to the development repo on every push to master. To publish a release build, upload a new tag, and a release will automatically be built and published.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
## Publishing Third Party Dependencies
|
||||
Currently the 3rd party deps are imgui, opencv, and google test
|
||||
|
||||
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).
|
||||
A variable needs to be added called `RUN_AZURE_ARTIFACTORY_RELEASE`, with a value of `true`. Then when the pipeline gets started, the final build outputs will be updated to artifactory.
|
||||
|
||||
To use newer versions of C++ dependencies, in `shared/config.gradle`, update the version related to the specific dependency.
|
||||
For Java dependencies, there is likely a file related to the specific dependency in the shared folder. Update the version in there.
|
||||
|
||||
Note, changing artifact locations (This includes changing the artifact year currently, I have an issue open to change this) requires updating the `native-utils` plugin
|
||||
|
||||
## Publishing allwpilib
|
||||
allwpilib publishes to the development repo on every push to main. To publish a release build, upload a new tag, and a release will automatically be built and published.
|
||||
|
||||
## Publishing desktop tools
|
||||
Desktop tools publish to the development repo on every push to main. To publish a release build, upload a new tag, and a release will automatically be built and published.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -9,7 +9,7 @@ We provide two repositories. These repositories are:
|
||||
* (Development) https://frcmaven.wpi.edu/artifactory/development/
|
||||
|
||||
The release repository is where official WPILib releases are pushed.
|
||||
The development repository is where development releases of every commit to [master](https://github.com/wpilibsuite/allwpilib/tree/master) is pushed.
|
||||
The development repository is where development releases of every commit to [main](https://github.com/wpilibsuite/allwpilib/tree/main) is pushed.
|
||||
|
||||
## Artifact classifiers
|
||||
We provide two base types of artifacts.
|
||||
@@ -69,15 +69,36 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
|
||||
* wpiutil
|
||||
|
||||
* wpigui
|
||||
* imgui
|
||||
|
||||
* ntcore
|
||||
* wpiutil
|
||||
|
||||
* wpimath
|
||||
* wpiutil
|
||||
|
||||
* glass/libglass
|
||||
* wpiutil
|
||||
* wpimath
|
||||
* wpigui
|
||||
|
||||
* glass/libglassnt
|
||||
* wpiutil
|
||||
* ntcore
|
||||
* wpimath
|
||||
* wpigui
|
||||
|
||||
* hal
|
||||
* wpiutil
|
||||
|
||||
* halsim
|
||||
* imgui
|
||||
* wpiutil
|
||||
|
||||
* ntcore
|
||||
* wpiutil
|
||||
* ntcore
|
||||
* wpimath
|
||||
* wpigui
|
||||
* libglass
|
||||
* libglassnt
|
||||
|
||||
* cscore
|
||||
* opencv
|
||||
@@ -101,6 +122,7 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* cameraserver
|
||||
* ntcore
|
||||
* cscore
|
||||
* wpimath
|
||||
* wpiutil
|
||||
|
||||
* wpilibNewCommands
|
||||
@@ -109,15 +131,9 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
|
||||
* cameraserver
|
||||
* ntcore
|
||||
* cscore
|
||||
* wpimath
|
||||
* wpiutil
|
||||
|
||||
* wpilibNewCommands
|
||||
* wpilibc
|
||||
* hal
|
||||
* cameraserver
|
||||
* ntcore
|
||||
* cscore
|
||||
* wpiutil
|
||||
|
||||
### Third Party Artifacts
|
||||
|
||||
@@ -128,3 +144,4 @@ All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
|
||||
* googletest
|
||||
* imgui
|
||||
* opencv
|
||||
* libssh
|
||||
|
||||
@@ -6,13 +6,15 @@ This article contains instructions on building projects using a development buil
|
||||
|
||||
## Development Build
|
||||
|
||||
Development builds are the per-commit build hosted everytime 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).
|
||||
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).
|
||||
|
||||
In order 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.
|
||||
In order 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`
|
||||
|
||||
```groovy
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useDevelopment = true
|
||||
wpi.wpilibVersion = 'YEAR.+'
|
||||
wpi.versions.wpilibVersion = '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.
|
||||
@@ -21,11 +23,13 @@ Java
|
||||
```groovy
|
||||
plugins {
|
||||
id "java"
|
||||
id "edu.wpi.first.GradleRIO" version "2020.3.2"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useDevelopment = true
|
||||
wpi.wpilibVersion = '2020.+'
|
||||
wpi.versions.wpilibVersion = '2023.+'
|
||||
wpi.versions.wpimathVersion = '2023.+'
|
||||
```
|
||||
|
||||
C++
|
||||
@@ -33,11 +37,13 @@ C++
|
||||
plugins {
|
||||
id "cpp"
|
||||
id "google-test-test-suite"
|
||||
id "edu.wpi.first.GradleRIO" version "2020.3.2"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useDevelopment = true
|
||||
wpi.wpilibVersion = '2020.+'
|
||||
wpi.versions.wpilibVersion = '2023.+'
|
||||
wpi.versions.wpimathVersion = '2023.+'
|
||||
```
|
||||
|
||||
## Local Build
|
||||
@@ -48,11 +54,13 @@ Java
|
||||
```groovy
|
||||
plugins {
|
||||
id "java"
|
||||
id "edu.wpi.first.GradleRIO" version "2020.3.2"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useFrcMavenLocalDevelopment = true
|
||||
wpi.wpilibVersion = 'YEAR.424242.+'
|
||||
wpi.versions.wpilibVersion = 'YEAR.424242.+'
|
||||
wpi.versions.wpimathVersion = 'YEAR.424242.+'
|
||||
```
|
||||
|
||||
C++
|
||||
@@ -60,9 +68,26 @@ C++
|
||||
plugins {
|
||||
id "cpp"
|
||||
id "google-test-test-suite"
|
||||
id "edu.wpi.first.GradleRIO" version "2020.3.2"
|
||||
id "edu.wpi.first.GradleRIO" version "2023.0.0-alpha-1"
|
||||
}
|
||||
|
||||
wpi.maven.useLocal = false
|
||||
wpi.maven.useFrcMavenLocalDevelopment = true
|
||||
wpi.wpilibVersion = 'YEAR.424242.+'
|
||||
wpi.versions.wpilibVersion = 'YEAR.424242.+'
|
||||
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 `admin` account (`lvuser` will fail to run in many cases). In the admin home directory, a file for each deploy type will exist (`myRobotCpp`, `myRobotCppStatic` and `myRobotJavaRun`). These can be run to start up the corresponding project.
|
||||
|
||||
@@ -35,8 +35,10 @@ The following build options are available:
|
||||
* This option will build C++ unit tests. These can be run via `make test`.
|
||||
* `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.
|
||||
* `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, wpilibc/j, and wpimath 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.
|
||||
* 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_SIMULATION_MODULES` (ON Default)
|
||||
* This option will build simulation modules, including wpigui and the HALSim plugins.
|
||||
* `WITH_EXTERNAL_HAL` (OFF Default)
|
||||
@@ -48,7 +50,7 @@ The following build options are available:
|
||||
|
||||
## Build Setup
|
||||
|
||||
The WPILib CMake build does not allow in source builds. Because the `build` directory is used by Gradle, we recommend a `buildcmake` directory in the root. This folder is included in the gitignore.
|
||||
The WPILib CMake build does not allow in source builds. Because the `build` directory is used by Gradle, we recommend a `build-cmake` directory in the root. This folder is included in the gitignore.
|
||||
|
||||
Once you have a build folder, run CMake configuration in that build directory with the following command.
|
||||
|
||||
|
||||
58
README.md
58
README.md
@@ -1,6 +1,8 @@
|
||||
# WPILib Project
|
||||
|
||||

|
||||
[](https://first.wpi.edu/wpilib/allwpilib/docs/development/cpp/)
|
||||
[](https://first.wpi.edu/wpilib/allwpilib/docs/development/java/)
|
||||
|
||||
Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WPILibC projects. These are the core libraries for creating robot programs for the roboRIO.
|
||||
|
||||
@@ -14,7 +16,7 @@ Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WP
|
||||
- [Using Development Builds](#using-development-builds)
|
||||
- [Custom toolchain location](#custom-toolchain-location)
|
||||
- [Gazebo simulation](#gazebo-simulation)
|
||||
- [Formatting/linting with wpiformat](#formattinglinting-with-wpiformat)
|
||||
- [Formatting/Linting](#formattinglinting)
|
||||
- [CMake](#cmake)
|
||||
- [Publishing](#publishing)
|
||||
- [Structure and Organization](#structure-and-organization)
|
||||
@@ -24,6 +26,15 @@ Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WP
|
||||
|
||||
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).
|
||||
|
||||
# Quick Start
|
||||
|
||||
Below is a list of instructions that guide you through cloning, building, publishing and using local allwpilib binaries in a robot project. This quick start is not intended as a replacement for the information further listed in this document.
|
||||
|
||||
1. Clone the repository with `git clone https://github.com/wpilibsuite/allwpilib.git`
|
||||
2. Build the repository with `./gradlew build` or `./gradlew build --build-cache` if you have an internet connection
|
||||
3. Publish the artifacts locally by running `./gradlew publish`
|
||||
4. [Update your](OtherVersions.md) `build.gradle` [to use the artifacts](OtherVersions.md)
|
||||
|
||||
# Building WPILib
|
||||
|
||||
Using Gradle makes building WPILib very straightforward. It only has a few dependencies on outside tools, such as the ARM cross compiler for creating roboRIO binaries.
|
||||
@@ -31,18 +42,27 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen
|
||||
## Requirements
|
||||
|
||||
- [JDK 11](https://adoptopenjdk.net/)
|
||||
- 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
|
||||
- C++ compiler
|
||||
- On Linux, install GCC
|
||||
- On Windows, install [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/community/) and select the C++ programming language during installation (Gradle can't use the build tools for Visual Studio 2019)
|
||||
- On Linux, install GCC 8 or greater
|
||||
- On Windows, install [Visual Studio Community 2022 or 2019](https://visualstudio.microsoft.com/vs/community/) and select the C++ programming language during installation (Gradle can't use the build tools for Visual Studio)
|
||||
- On macOS, install the Xcode command-line build tools via `xcode-select --install`
|
||||
- [ARM compiler toolchain](https://github.com/wpilibsuite/roborio-toolchain/releases)
|
||||
- For 2020 and beyond, use GCC version 7 or greater
|
||||
- ARM compiler toolchain
|
||||
- Run `./gradlew installRoboRioToolchain` after cloning this repository
|
||||
- If the WPILib installer was used, this toolchain is already installed
|
||||
- Raspberry Pi toolchain (optional)
|
||||
- Run `./gradlew installArm32Toolchain` after cloning this repository
|
||||
|
||||
On macOS ARM, run `softwareupdate --install-rosetta`. This is necessary to be able to use the macOS x86 roboRIO toolchain on ARM.
|
||||
|
||||
## Setup
|
||||
|
||||
Clone the WPILib repository. If the toolchains are not installed, install them, and make sure they are available on the system PATH.
|
||||
Clone the WPILib repository and follow the instructions above for installing any required tooling.
|
||||
|
||||
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/master/README.md) for wpiformat setup instructions.
|
||||
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/main/README.md) for wpiformat setup instructions.
|
||||
|
||||
## Building
|
||||
|
||||
@@ -62,16 +82,26 @@ The gradlew wrapper only exists in the root of the main project, so be sure to r
|
||||
|
||||
There are a few tasks other than `build` available. To see them, run the meta-task `tasks`. This will print a list of all available tasks, with a description of each task.
|
||||
|
||||
If opening from a fresh clone, generated java dependencies will not exist. Most IDEs will not run the generation tasks, which will cause lots of IDE errors. Manually run `./gradlew compileJava` from a terminal to run all the compile tasks, and then refresh your IDE's configuration (In VS Code open settings.gradle and save).
|
||||
|
||||
### Faster builds
|
||||
|
||||
`./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.
|
||||
|
||||
`testDesktopCpp` and `testDesktopJava` tasks also exist for the projects `wpiutil`, `ntcore`, `cscore`, `hal` `wpilibOldCommands`, `wpilibNewCommands` and `cameraserver`. These can be ran with `./gradlew :projectName:task`.
|
||||
`testDesktopCpp` and `testDesktopJava` tasks also exist for the projects `wpiutil`, `ntcore`, `cscore`, `hal` `wpilibNewCommands` and `cameraserver`. 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.
|
||||
|
||||
### Build Cache
|
||||
|
||||
Run with `--build-cache` on the command-line to use the shared [build cache](https://docs.gradle.org/current/userguide/build_cache.html) artifacts generated by the continuous integration server. Example:
|
||||
|
||||
```bash
|
||||
./gradlew build --build-cache
|
||||
```
|
||||
|
||||
### Using Development Builds
|
||||
|
||||
Please read the documentation available [here](OtherVersions.md)
|
||||
@@ -86,10 +116,10 @@ If you have installed the FRC Toolchain to a directory other than the default, o
|
||||
|
||||
### Gazebo simulation
|
||||
|
||||
If you also want simulation to be built, add -PmakeSim. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of Gazebo should work, even on Windows if you build Gazebo from source. Correct means CMake needs to be able to find gazebo-config.cmake. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
|
||||
If you also want to force building Gazebo simulation support, add -PforceGazebo. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of Gazebo should work, even on Windows if you build Gazebo from source. Correct means CMake needs to be able to find gazebo-config.cmake. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
|
||||
|
||||
```bash
|
||||
./gradlew build -PmakeSim
|
||||
./gradlew build -PforceGazebo
|
||||
```
|
||||
|
||||
If you prefer to use CMake directly, the you can still do so.
|
||||
@@ -111,7 +141,9 @@ wpiformat can be executed anywhere in the repository via `py -3 -m wpiformat` on
|
||||
|
||||
#### Java Code Quality Tools
|
||||
|
||||
The Java code quality tools (checkstyle, pmd, etc.) can be run with the `./gradlew javaFormat` task.
|
||||
The Java code quality tools Checkstyle, PMD, and Spotless can be run via `./gradlew javaFormat`. SpotBugs can be run via the `spotbugsMain`, `spotbugsTest`, and `spotbugsDev` tasks. These tools will all be run automatically by the `build` task. To disable this behavior, pass the `-PskipJavaFormat` flag.
|
||||
|
||||
If you only want to run the Java autoformatter, run `./gradlew spotlessApply`.
|
||||
|
||||
### CMake
|
||||
|
||||
@@ -136,7 +168,9 @@ The Simulation directory contains extra simulation tools and libraries, such as
|
||||
|
||||
The integration test directories for C++ and Java contain test code that runs on our test-system. When you submit code for review, it is tested by those programs. If you add new functionality you should make sure to write tests for it so we don't break it in the future.
|
||||
|
||||
The hal directory contains more C++ code meant to run on the roboRIO. HAL is an acronym for "Hardware Abstraction Layer", and it interfaces with the NI Libraries. The NI Libraries contain the low-level code for controlling devices on your robot. The NI Libraries are found in the ni-libraries folder.
|
||||
The hal directory contains more C++ code meant to run on the roboRIO. HAL is an acronym for "Hardware Abstraction Layer", and it interfaces with the NI Libraries. The NI Libraries contain the low-level code for controlling devices on your robot. The NI Libraries are found in the [ni-libraries](https://github.com/wpilibsuite/ni-libraries) project.
|
||||
|
||||
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).
|
||||
|
||||
|
||||
@@ -17,38 +17,36 @@ Program Locations
|
||||
------- ---------
|
||||
RoboRIO Libraries ni-libraries
|
||||
Google Test gtest
|
||||
LLVM wpiutil/src/main/native/include/wpi/{various files}
|
||||
wpiutil/src/main/native/cpp/llvm/
|
||||
wpiutil/src/main/native/cpp/leb128.cpp
|
||||
wpiutil/src/test/native/cpp/leb128Test.cpp
|
||||
JSON for Modern C++ wpiutil/src/main/native/include/wpi/json.h
|
||||
wpiutil/src/main/native/cpp/json_*.cpp
|
||||
LLVM wpiutil/src/main/native/thirdparty/llvm
|
||||
wpiutil/src/test/native/cpp/llvm/
|
||||
JSON for Modern C++ wpiutil/src/main/native/thirdparty/json
|
||||
wpiutil/src/test/native/cpp/json/
|
||||
libuv wpiutil/src/main/native/include/uv.h
|
||||
wpiutil/src/main/native/include/uv/
|
||||
wpiutil/src/main/native/libuv/
|
||||
sigslot wpiutil/src/main/native/include/wpi/Signal.h
|
||||
wpiutil/src/test/native/cpp/sigslot/
|
||||
tcpsockets wpiutil/src/main/native/cpp/TCP{Stream,Connector,Acceptor}.cpp
|
||||
wpiutil/src/main/native/include/wpi/TCP*.h
|
||||
Bootstrap wpiutil/src/main/native/resources/bootstrap-*
|
||||
CoreUI wpiutil/src/main/native/resources/coreui-*
|
||||
Feather Icons wpiutil/src/main/native/resources/feather-*
|
||||
jQuery wpiutil/src/main/native/resources/jquery-*
|
||||
popper.js wpiutil/src/main/native/resources/popper-*
|
||||
libuv wpinet/src/main/native/thirdparty/libuv/
|
||||
fmtlib wpiutil/src/main/native/thirdparty/fmtlib/
|
||||
sigslot wpiutil/src/main/native/thirdparty/sigslot
|
||||
tcpsockets wpinet/src/main/native/thirdparty/tcpsockets
|
||||
MPack wpiutil/src/main/native/thirdparty/mpack
|
||||
Bootstrap wpinet/src/main/native/resources/bootstrap-*
|
||||
CoreUI wpinet/src/main/native/resources/coreui-*
|
||||
Feather Icons wpinet/src/main/native/resources/feather-*
|
||||
jQuery wpinet/src/main/native/resources/jquery-*
|
||||
popper.js wpinet/src/main/native/resources/popper-*
|
||||
units wpimath/src/main/native/include/units/
|
||||
Eigen wpimath/src/main/native/eigeninclude/
|
||||
wpimath/src/main/native/include/unsupported/
|
||||
Eigen wpimath/src/main/native/thirdparty/eigen/include/
|
||||
StackWalker wpiutil/src/main/native/windows/StackWalker.*
|
||||
TCB span wpiutil/src/main/native/thirdparty/include/wpi/span.h
|
||||
wpiutil/src/test/native/cpp/span/
|
||||
GHC filesystem wpiutil/src/main/native/thirdparty/include/wpi/ghc/
|
||||
Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineParameterizer.java
|
||||
wpilibj/src/main/java/edu/wpi/first/wpilibj/trajectory/TrajectoryParameterizer.java
|
||||
wpilibc/src/main/native/include/spline/SplineParameterizer.h
|
||||
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/cpp/drake/common/drake_assert_and_throw.cpp
|
||||
wpimath/src/main/native/cpp/drake/math/discrete_algebraic_riccati_equation.cpp
|
||||
|
||||
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
|
||||
|
||||
==============================================================================
|
||||
Google Test License
|
||||
@@ -84,12 +82,247 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
==============================================================================
|
||||
LLVM Release License
|
||||
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
|
||||
==============================================================================
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
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.
|
||||
|
||||
|
||||
---- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
|
||||
==============================================================================
|
||||
Software from third parties included in the LLVM Project:
|
||||
==============================================================================
|
||||
The LLVM Project contains third party software which is under different license
|
||||
terms. All such code will be identified clearly using at least one of two
|
||||
mechanisms:
|
||||
1) It will be in a separate directory tree with its own `LICENSE.txt` or
|
||||
`LICENSE` file at the top containing the specific license and restrictions
|
||||
which apply to that software, or
|
||||
2) It will contain specific license and restriction terms at the top of every
|
||||
file.
|
||||
|
||||
==============================================================================
|
||||
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
|
||||
==============================================================================
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign.
|
||||
Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
@@ -231,6 +464,32 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
==============================================================================
|
||||
MPacks License
|
||||
==============================================================================
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2021 Nicholas Fraser and the MPack authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
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.
|
||||
|
||||
|
||||
==============================================================================
|
||||
Bootstrap License
|
||||
==============================================================================
|
||||
@@ -845,3 +1104,125 @@ 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
|
||||
=====================
|
||||
Copyright © 2018—2020 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
This library is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the Do What the **** You Want
|
||||
to Public License, Version 2, as published by the WTFPL Task Force.
|
||||
See http://www.wtfpl.net/ for more details.
|
||||
|
||||
======================
|
||||
Boost Software License
|
||||
======================
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
======
|
||||
fmtlib
|
||||
======
|
||||
Copyright (c) 2012 - present, Victor Zverovich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 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.
|
||||
|
||||
--- Optional exception to the license ---
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into a machine-executable object form of such
|
||||
source code, you may redistribute such embedded portions in such object form
|
||||
without including the above copyright and permission notices.
|
||||
|
||||
==============
|
||||
GHC filesystem
|
||||
==============
|
||||
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
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.
|
||||
|
||||
==================
|
||||
V8 export-template
|
||||
==================
|
||||
Copyright 2014, the V8 project authors. 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 Google Inc. 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
|
||||
OWNER 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,88 +4,88 @@ trigger:
|
||||
batch: true
|
||||
branches:
|
||||
include:
|
||||
- master
|
||||
- master
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
jobs:
|
||||
- job: IntegrationTests
|
||||
displayName: Integration Tests
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
- stage: Build
|
||||
jobs:
|
||||
- job: IntegrationTests
|
||||
displayName: Integration Tests
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
|
||||
container:
|
||||
image: wpilib/roborio-cross-ubuntu:2021-18.04
|
||||
container:
|
||||
image: wpilib/roborio-cross-ubuntu:2022-18.04
|
||||
|
||||
timeoutInMinutes: 0
|
||||
timeoutInMinutes: 0
|
||||
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ''
|
||||
gradleWrapperFile: 'gradlew'
|
||||
gradleOptions: '-Xmx3072m'
|
||||
publishJUnitResults: false
|
||||
testResultsFiles: '**/TEST-*.xml'
|
||||
tasks: 'copyWpilibJIntegrationTestJarToOutput copyWpilibCTestLibrariesToOutput'
|
||||
options: '-Ponlylinuxathena -PbuildServer'
|
||||
steps:
|
||||
- task: Gradle@2
|
||||
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
|
||||
inputs:
|
||||
workingDirectory: ""
|
||||
gradleWrapperFile: "gradlew"
|
||||
gradleOptions: "-Xmx3072m"
|
||||
publishJUnitResults: false
|
||||
testResultsFiles: "**/TEST-*.xml"
|
||||
tasks: "copyWpilibJIntegrationTestJarToOutput copyWpilibCTestLibrariesToOutput"
|
||||
options: "-Ponlylinuxathena -PbuildServer -PskipJavaFormat"
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Integration Tests'
|
||||
targetPath: 'build/integrationTestFiles'
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: "Integration Tests"
|
||||
targetPath: "build/integrationTestFiles"
|
||||
|
||||
- stage: TestBench
|
||||
displayName: Test Bench
|
||||
jobs:
|
||||
- job: Cpp
|
||||
displayName: C++
|
||||
pool: RoboRioConnections
|
||||
timeoutInMinutes: 30
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Integration Tests'
|
||||
targetPath: 'build/integrationTestFiles'
|
||||
- stage: TestBench
|
||||
displayName: Test Bench
|
||||
jobs:
|
||||
- job: Cpp
|
||||
displayName: C++
|
||||
pool: RoboRioConnections
|
||||
timeoutInMinutes: 30
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: "Integration Tests"
|
||||
targetPath: "build/integrationTestFiles"
|
||||
|
||||
- task: ShellScript@2
|
||||
displayName: Run C++ Tests
|
||||
inputs:
|
||||
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
|
||||
args: 'cpp -A "--gtest_output=xml:/home/admin/testResults/cppreport.xml"'
|
||||
- task: ShellScript@2
|
||||
displayName: Run C++ Tests
|
||||
inputs:
|
||||
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
|
||||
args: 'cpp -A "--gtest_output=xml:/home/admin/testResults/cppreport.xml"'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish C++ Test Results
|
||||
inputs:
|
||||
testResultsFormat: 'JUnit'
|
||||
testResultsFiles: '*.xml'
|
||||
testRunTitle: 'C++ Test Report'
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish C++ Test Results
|
||||
inputs:
|
||||
testResultsFormat: "JUnit"
|
||||
testResultsFiles: "*.xml"
|
||||
testRunTitle: "C++ Test Report"
|
||||
searchFolder: "$(System.DefaultWorkingDirectory)/test-reports"
|
||||
|
||||
- job: Java
|
||||
pool: RoboRioConnections
|
||||
timeoutInMinutes: 30
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: 'Integration Tests'
|
||||
targetPath: 'build/integrationTestFiles'
|
||||
- job: Java
|
||||
pool: RoboRioConnections
|
||||
timeoutInMinutes: 30
|
||||
workspace:
|
||||
clean: all
|
||||
steps:
|
||||
- task: DownloadPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: "Integration Tests"
|
||||
targetPath: "build/integrationTestFiles"
|
||||
|
||||
- task: ShellScript@2
|
||||
displayName: Run Java Tests
|
||||
inputs:
|
||||
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
|
||||
args: 'java'
|
||||
- task: ShellScript@2
|
||||
displayName: Run Java Tests
|
||||
inputs:
|
||||
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
|
||||
args: "java"
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Java Test Results
|
||||
inputs:
|
||||
testResultsFormat: 'JUnit'
|
||||
testResultsFiles: '*.xml'
|
||||
testRunTitle: 'Java Test Report'
|
||||
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Java Test Results
|
||||
inputs:
|
||||
testResultsFormat: "JUnit"
|
||||
testResultsFiles: "*.xml"
|
||||
testRunTitle: "Java Test Report"
|
||||
searchFolder: "$(System.DefaultWorkingDirectory)/test-reports"
|
||||
|
||||
60
build.gradle
60
build.gradle
@@ -1,31 +1,39 @@
|
||||
import edu.wpi.first.toolchain.*
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn'
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.hubspot.jinjava:jinjava:2.6.0'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'base'
|
||||
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.0.2'
|
||||
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.1.0'
|
||||
id 'edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin' version '2020.2'
|
||||
id 'edu.wpi.first.NativeUtils' apply false
|
||||
id 'edu.wpi.first.GradleJni' version '0.10.1'
|
||||
id 'edu.wpi.first.GradleVsCode' version '0.11.0'
|
||||
id 'edu.wpi.first.GradleJni' version '1.0.0'
|
||||
id 'edu.wpi.first.GradleVsCode'
|
||||
id 'idea'
|
||||
id 'visual-studio'
|
||||
id 'net.ltgt.errorprone' version '1.1.1' apply false
|
||||
id 'com.github.johnrengelman.shadow' version '5.2.0' apply false
|
||||
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.4.2' apply false
|
||||
id 'com.github.spotbugs' version '5.0.8' apply false
|
||||
}
|
||||
|
||||
if (project.hasProperty('buildServer')) {
|
||||
wpilibVersioning.buildServerMode = true
|
||||
wpilibVersioning.useAllTags = true
|
||||
}
|
||||
|
||||
if (project.hasProperty('releaseMode')) {
|
||||
wpilibVersioning.releaseMode = true
|
||||
wpilibVersioning.useAllTags = true
|
||||
}
|
||||
wpilibVersioning.buildServerMode = project.hasProperty('buildServer')
|
||||
wpilibVersioning.releaseMode = project.hasProperty('releaseMode')
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn'
|
||||
}
|
||||
}
|
||||
if (project.hasProperty('releaseMode')) {
|
||||
wpilibRepositories.addAllReleaseRepositories(it)
|
||||
@@ -79,7 +87,12 @@ task copyAllOutputs(type: Copy) {
|
||||
build.dependsOn copyAllOutputs
|
||||
copyAllOutputs.dependsOn outputVersions
|
||||
|
||||
def copyReleaseOnly = project.hasProperty('ciReleaseOnly')
|
||||
|
||||
ext.addTaskToCopyAllOutputs = { task ->
|
||||
if (copyReleaseOnly && task.name.contains('debug')) {
|
||||
return
|
||||
}
|
||||
copyAllOutputs.dependsOn task
|
||||
copyAllOutputs.inputs.file task.archivePath
|
||||
copyAllOutputs.from task.archivePath
|
||||
@@ -106,6 +119,13 @@ subprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// Enables UTF-8 support in Javadoc
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption("charset", "utf-8")
|
||||
options.addStringOption("docencoding", "utf-8")
|
||||
options.addStringOption("encoding", "utf-8")
|
||||
}
|
||||
|
||||
// Sign outputs with Developer ID
|
||||
if (project.hasProperty("developerID")) {
|
||||
tasks.withType(AbstractLinkTask) { task ->
|
||||
@@ -117,8 +137,12 @@ subprojects {
|
||||
String path = task.getLinkedFile().getAsFile().get().getAbsolutePath()
|
||||
exec {
|
||||
workingDir rootDir
|
||||
def args = ["sh", "-c", "codesign --force --strict --timestamp --options=runtime " +
|
||||
"--verbose -s ${project.findProperty("developerID")} ${path}"]
|
||||
def args = [
|
||||
"sh",
|
||||
"-c",
|
||||
"codesign --force --strict --timestamp --options=runtime " +
|
||||
"--verbose -s ${project.findProperty("developerID")} ${path}"
|
||||
]
|
||||
commandLine args
|
||||
}
|
||||
}
|
||||
@@ -132,5 +156,5 @@ ext.getCurrentArch = {
|
||||
}
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '6.0.1'
|
||||
gradleVersion = '7.5.1'
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ repositories {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation "edu.wpi.first:native-utils:2021.0.4"
|
||||
implementation "edu.wpi.first:native-utils:2023.1.0"
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import groovy.transform.CompileStatic
|
||||
import javax.inject.Inject
|
||||
import jaci.gradle.deploy.artifact.MavenArtifact
|
||||
import jaci.gradle.deploy.context.DeployContext
|
||||
import org.gradle.api.Project
|
||||
import jaci.gradle.ActionWrapper
|
||||
|
||||
import java.util.function.Function
|
||||
|
||||
@CompileStatic
|
||||
class JREArtifact extends MavenArtifact {
|
||||
Function<DeployContext, Boolean> buildRequiresJre = (Function<DeployContext, Boolean>){ true }
|
||||
|
||||
void setJreDependency(String dep) {
|
||||
dependency = project.dependencies.add(configuration(), dep)
|
||||
}
|
||||
|
||||
@Inject
|
||||
JREArtifact(String name, Project project) {
|
||||
super(name, project)
|
||||
configuration = project.configurations.create(configuration())
|
||||
|
||||
onlyIf = { DeployContext ctx ->
|
||||
(buildRequiresJre.apply(ctx) && jreMissing(ctx)) || project.hasProperty("force-redeploy-jre")
|
||||
}
|
||||
|
||||
predeploy << new ActionWrapper({ DeployContext ctx ->
|
||||
ctx.logger.log('Deploying RoboRIO JRE (this will take a while)...')
|
||||
})
|
||||
|
||||
directory = '/tmp'
|
||||
filename = 'frcjre.ipk'
|
||||
|
||||
postdeploy << new ActionWrapper({ DeployContext ctx ->
|
||||
ctx.logger.log('Installing JRE...')
|
||||
ctx.execute('opkg remove frc2020-openjdk*; opkg install /tmp/frcjre.ipk; rm /tmp/frcjre.ipk')
|
||||
ctx.logger.log('JRE Deployed!')
|
||||
})
|
||||
}
|
||||
|
||||
String configuration() {
|
||||
return name + 'frcjre'
|
||||
}
|
||||
|
||||
boolean jreMissing(DeployContext ctx) {
|
||||
return ctx.execute('if [[ -f "/usr/local/frc/JRE/bin/java" ]]; then echo OK; else echo MISSING; fi').result.contains("MISSING")
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.tasks.Delete
|
||||
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
@@ -44,7 +46,7 @@ import org.gradle.platform.base.ComponentType;
|
||||
import org.gradle.platform.base.TypeBuilder;
|
||||
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
|
||||
import groovy.transform.CompileStatic;
|
||||
import edu.wpi.first.nativeutils.tasks.ExportsGenerationTask
|
||||
import edu.wpi.first.nativeutils.exports.ExportsGenerationTask
|
||||
|
||||
@CompileStatic
|
||||
class SingleNativeBuild implements Plugin<Project> {
|
||||
@@ -87,6 +89,14 @@ class SingleNativeBuild implements Plugin<Project> {
|
||||
subs << component
|
||||
}
|
||||
}
|
||||
Delete deleteObjects = null
|
||||
if (project.hasProperty('buildServer')) {
|
||||
deleteObjects = project.tasks.create('deleteObjects', Delete)
|
||||
project.tasks.named('build').configure { Task t ->
|
||||
t.dependsOn deleteObjects
|
||||
return
|
||||
}
|
||||
}
|
||||
subs.each {
|
||||
((NativeLibrarySpec) it).binaries.each { oBinary ->
|
||||
if (oBinary.buildable == false) {
|
||||
@@ -136,6 +146,10 @@ class SingleNativeBuild implements Plugin<Project> {
|
||||
tree.include '**/*.o'
|
||||
tree.include '**/*.obj'
|
||||
link.source tree
|
||||
if (project.hasProperty('buildServer')) {
|
||||
deleteObjects.dependsOn link
|
||||
deleteObjects.delete tree
|
||||
}
|
||||
} else if (binary instanceof StaticLibraryBinarySpec) {
|
||||
def sBinary = (StaticLibraryBinarySpec) binary
|
||||
ObjectFilesToBinary assemble = (ObjectFilesToBinary) sBinary.tasks.createStaticLib
|
||||
@@ -145,6 +159,10 @@ class SingleNativeBuild implements Plugin<Project> {
|
||||
tree.include '**/*.o'
|
||||
tree.include '**/*.obj'
|
||||
assemble.source tree
|
||||
if (project.hasProperty('buildServer')) {
|
||||
deleteObjects.dependsOn assemble
|
||||
deleteObjects.delete tree
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
buildSrc/src/main/groovy/WPIJREArtifact.groovy
Normal file
48
buildSrc/src/main/groovy/WPIJREArtifact.groovy
Normal file
@@ -0,0 +1,48 @@
|
||||
import groovy.transform.CompileStatic
|
||||
import javax.inject.Inject
|
||||
import edu.wpi.first.deployutils.deploy.artifact.MavenArtifact
|
||||
import edu.wpi.first.deployutils.deploy.context.DeployContext
|
||||
import org.gradle.api.Project
|
||||
import edu.wpi.first.deployutils.ActionWrapper
|
||||
import edu.wpi.first.deployutils.deploy.target.RemoteTarget
|
||||
import edu.wpi.first.deployutils.PredicateWrapper
|
||||
|
||||
import java.util.function.Function
|
||||
|
||||
@CompileStatic
|
||||
public class WPIJREArtifact extends MavenArtifact {
|
||||
private final String configName;
|
||||
|
||||
public String getConfigName() {
|
||||
return configName;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public WPIJREArtifact(String name, RemoteTarget target) {
|
||||
super(name, target);
|
||||
String configName = name + "frcjre";
|
||||
this.configName = configName;
|
||||
Project project = target.getProject();
|
||||
getConfiguration().set(project.getConfigurations().create(configName));
|
||||
getDependency().set(project.getDependencies().add(configName, "edu.wpi.first.jdk:roborio-2022:11.0.12u5-1"));
|
||||
|
||||
setOnlyIf(new PredicateWrapper({ DeployContext ctx ->
|
||||
return jreMissing(ctx) || project.hasProperty("force-redeploy-jre");
|
||||
}));
|
||||
|
||||
getDirectory().set("/tmp");
|
||||
getFilename().set("frcjre.ipk");
|
||||
|
||||
getPostdeploy().add(new ActionWrapper({ DeployContext ctx ->
|
||||
ctx.getLogger().log("Installing JRE...");
|
||||
ctx.execute("opkg remove frc2022-openjdk*; opkg install /tmp/frcjre.ipk; rm /tmp/frcjre.ipk");
|
||||
ctx.getLogger().log("JRE Deployed!");
|
||||
}));
|
||||
}
|
||||
|
||||
private boolean jreMissing(DeployContext ctx) {
|
||||
return ctx.execute("if [[ -f \"/usr/local/frc/JRE/bin/java\" ]]; then echo OK; else echo MISSING; fi").getResult().contains("MISSING");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ repoRootNameOverride {
|
||||
}
|
||||
|
||||
includeOtherLibs {
|
||||
^fmt/
|
||||
^hal/
|
||||
^networktables/
|
||||
^opencv2/
|
||||
|
||||
@@ -9,7 +9,7 @@ find_package( OpenCV REQUIRED )
|
||||
if (WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
|
||||
#find java files, copy them locally
|
||||
|
||||
@@ -53,8 +53,8 @@ else()
|
||||
set (cameraserver_config_dir share/cameraserver)
|
||||
endif()
|
||||
|
||||
configure_file(cameraserver-config.cmake.in ${CMAKE_BINARY_DIR}/cameraserver-config.cmake )
|
||||
install(FILES ${CMAKE_BINARY_DIR}/cameraserver-config.cmake 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 ${cameraserver_config_dir})
|
||||
install(EXPORT cameraserver DESTINATION ${cameraserver_config_dir})
|
||||
|
||||
file(GLOB multiCameraServer_src multiCameraServer/src/main/native/cpp/*.cpp)
|
||||
|
||||
@@ -11,18 +11,20 @@ apply from: "${rootDir}/shared/javacpp/setupBuild.gradle"
|
||||
|
||||
dependencies {
|
||||
implementation project(':wpiutil')
|
||||
implementation project(':wpinet')
|
||||
implementation project(':ntcore')
|
||||
implementation project(':cscore')
|
||||
devImplementation project(':wpiutil')
|
||||
devImplementation project(':wpinet')
|
||||
devImplementation project(':ntcore')
|
||||
devImplementation project(':cscore')
|
||||
}
|
||||
|
||||
ext {
|
||||
sharedCvConfigs = [cameraserver : [],
|
||||
cameraserverBase: [],
|
||||
cameraserverDev : [],
|
||||
cameraserverTest: []]
|
||||
cameraserverBase: [],
|
||||
cameraserverDev : [],
|
||||
cameraserverTest: []]
|
||||
staticCvConfigs = [:]
|
||||
useJava = true
|
||||
useCpp = true
|
||||
@@ -32,14 +34,19 @@ apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
nativeUtils.exportsConfigs {
|
||||
cameraserver {
|
||||
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = [
|
||||
'_CT??_R0?AV_System_error',
|
||||
'_CT??_R0?AVexception',
|
||||
'_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error',
|
||||
'_CT??_R0?AVsystem_error',
|
||||
'_CTA5?AVfailure',
|
||||
'_TI5?AVfailure',
|
||||
'_CT??_R0?AVout_of_range',
|
||||
'_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range',
|
||||
'_CT??_R0?AVbad_cast'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +59,7 @@ model {
|
||||
}
|
||||
lib project: ':ntcore', library: 'ntcore', linkage: 'shared'
|
||||
lib project: ':cscore', library: 'cscore', linkage: 'shared'
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,13 +23,16 @@ mainClassName = 'edu.wpi.Main'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.code.gson:gson:2.8.5'
|
||||
implementation 'com.google.code.gson:gson:2.8.9'
|
||||
|
||||
implementation project(':wpiutil')
|
||||
implementation project(':wpinet')
|
||||
implementation project(':ntcore')
|
||||
implementation project(':cscore')
|
||||
implementation project(':cameraserver')
|
||||
@@ -38,7 +41,6 @@ dependencies {
|
||||
model {
|
||||
components {
|
||||
multiCameraServerCpp(NativeExecutableSpec) {
|
||||
targetBuildTypes 'release'
|
||||
sources {
|
||||
cpp {
|
||||
source {
|
||||
@@ -52,10 +54,11 @@ model {
|
||||
}
|
||||
}
|
||||
binaries.all { binary ->
|
||||
lib project: ':cameraserver', library: 'cameraserver', linkage: 'static'
|
||||
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
|
||||
lib project: ':cscore', library: 'cscore', linkage: 'static'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
|
||||
lib project: ':cameraserver', library: 'cameraserver', linkage: 'static'
|
||||
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
|
||||
lib project: ':cscore', library: 'cscore', linkage: 'static'
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'static'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,50 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import edu.wpi.cscore.VideoSource;
|
||||
import edu.wpi.first.cameraserver.CameraServer;
|
||||
import edu.wpi.first.cscore.VideoSource;
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
JSON format:
|
||||
{
|
||||
"team": <team number>,
|
||||
"ntmode": <"client" or "server", "client" if unspecified>
|
||||
"cameras": [
|
||||
{
|
||||
"name": <camera name>
|
||||
"path": <path, e.g. "/dev/video0">
|
||||
"pixel format": <"MJPEG", "YUYV", etc> // optional
|
||||
"width": <video mode width> // optional
|
||||
"height": <video mode height> // optional
|
||||
"fps": <video mode fps> // optional
|
||||
"brightness": <percentage brightness> // optional
|
||||
"white balance": <"auto", "hold", value> // optional
|
||||
"exposure": <"auto", "hold", value> // optional
|
||||
"properties": [ // optional
|
||||
{
|
||||
"name": <property name>
|
||||
"value": <property value>
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
JSON format:
|
||||
{
|
||||
"team": <team number>,
|
||||
"ntmode": <"client" or "server", "client" if unspecified>
|
||||
"cameras": [
|
||||
{
|
||||
"name": <camera name>
|
||||
"path": <path, e.g. "/dev/video0">
|
||||
"pixel format": <"MJPEG", "YUYV", etc> // optional
|
||||
"width": <video mode width> // optional
|
||||
"height": <video mode height> // optional
|
||||
"fps": <video mode fps> // optional
|
||||
"brightness": <percentage brightness> // optional
|
||||
"white balance": <"auto", "hold", value> // optional
|
||||
"exposure": <"auto", "hold", value> // optional
|
||||
"properties": [ // optional
|
||||
{
|
||||
"name": <property name>
|
||||
"value": <property value>
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
public final class Main {
|
||||
private static String configFile = "/boot/frc.json";
|
||||
@@ -61,23 +56,18 @@ public final class Main {
|
||||
public JsonObject config;
|
||||
}
|
||||
|
||||
public static int team;
|
||||
public static boolean server;
|
||||
public static List<CameraConfig> cameras = new ArrayList<>();
|
||||
private static int team;
|
||||
private static boolean server;
|
||||
private static List<CameraConfig> cameras = new ArrayList<>();
|
||||
|
||||
private Main() {
|
||||
}
|
||||
private Main() {}
|
||||
|
||||
/**
|
||||
* Report parse error.
|
||||
*/
|
||||
/** Report parse error. */
|
||||
public static void parseError(String str) {
|
||||
System.err.println("config error in '" + configFile + "': " + str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read single camera configuration.
|
||||
*/
|
||||
/** Read single camera configuration. */
|
||||
public static boolean readCameraConfig(JsonObject config) {
|
||||
CameraConfig cam = new CameraConfig();
|
||||
|
||||
@@ -103,10 +93,7 @@ public final class Main {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read configuration file.
|
||||
*/
|
||||
@SuppressWarnings("PMD.CyclomaticComplexity")
|
||||
/** Read configuration file. */
|
||||
public static boolean readConfig() {
|
||||
// parse file
|
||||
JsonElement top;
|
||||
@@ -160,22 +147,17 @@ public final class Main {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start running the camera.
|
||||
*/
|
||||
/** Start running the camera. */
|
||||
public static void startCamera(CameraConfig config) {
|
||||
System.out.println("Starting camera '" + config.name + "' on " + config.path);
|
||||
VideoSource camera = CameraServer.getInstance().startAutomaticCapture(
|
||||
config.name, config.path);
|
||||
VideoSource camera = CameraServer.startAutomaticCapture(config.name, config.path);
|
||||
|
||||
Gson gson = new GsonBuilder().create();
|
||||
|
||||
camera.setConfigJson(gson.toJson(config.config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Main.
|
||||
*/
|
||||
/** Main. */
|
||||
public static void main(String... args) {
|
||||
if (args.length > 0) {
|
||||
configFile = args[0];
|
||||
@@ -202,7 +184,7 @@ public final class Main {
|
||||
}
|
||||
|
||||
// loop forever
|
||||
for (;;) {
|
||||
for (; ; ) {
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException ex) {
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <cstdio>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <wpi/StringRef.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/fmt/raw_ostream.h>
|
||||
#include <wpi/json.h>
|
||||
#include <wpi/raw_istream.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
@@ -108,7 +107,7 @@ bool ReadConfig() {
|
||||
try {
|
||||
j = wpi::json::parse(is);
|
||||
} catch (const wpi::json::parse_error& e) {
|
||||
ParseError() << "byte " << e.byte << ": " << e.what() << '\n';
|
||||
fmt::print(ParseError(), "byte {}: {}\n", e.byte, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -130,10 +129,9 @@ bool ReadConfig() {
|
||||
if (j.count("ntmode") != 0) {
|
||||
try {
|
||||
auto str = j.at("ntmode").get<std::string>();
|
||||
wpi::StringRef s(str);
|
||||
if (s.equals_lower("client")) {
|
||||
if (wpi::equals_lower(str, "client")) {
|
||||
server = false;
|
||||
} else if (s.equals_lower("server")) {
|
||||
} else if (wpi::equals_lower(str, "server")) {
|
||||
server = true;
|
||||
} else {
|
||||
ParseError() << "could not understand ntmode value '" << str << "'\n";
|
||||
@@ -146,7 +144,9 @@ bool ReadConfig() {
|
||||
// cameras
|
||||
try {
|
||||
for (auto&& camera : j.at("cameras")) {
|
||||
if (!ReadCameraConfig(camera)) return false;
|
||||
if (!ReadCameraConfig(camera)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (const wpi::json::exception& e) {
|
||||
ParseError() << "could not read cameras: " << e.what() << '\n';
|
||||
@@ -157,34 +157,41 @@ bool ReadConfig() {
|
||||
}
|
||||
|
||||
void StartCamera(const CameraConfig& config) {
|
||||
wpi::outs() << "Starting camera '" << config.name << "' on " << config.path
|
||||
<< '\n';
|
||||
auto camera = frc::CameraServer::GetInstance()->StartAutomaticCapture(
|
||||
config.name, config.path);
|
||||
fmt::print("Starting camera '{}' on {}\n", config.name, config.path);
|
||||
auto camera =
|
||||
frc::CameraServer::StartAutomaticCapture(config.name, config.path);
|
||||
|
||||
camera.SetConfigJson(config.config);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc >= 2) configFile = argv[1];
|
||||
if (argc >= 2) {
|
||||
configFile = argv[1];
|
||||
}
|
||||
|
||||
// read configuration
|
||||
if (!ReadConfig()) return EXIT_FAILURE;
|
||||
if (!ReadConfig()) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// start NetworkTables
|
||||
auto ntinst = nt::NetworkTableInstance::GetDefault();
|
||||
if (server) {
|
||||
wpi::outs() << "Setting up NetworkTables server\n";
|
||||
std::puts("Setting up NetworkTables server");
|
||||
ntinst.StartServer();
|
||||
} else {
|
||||
wpi::outs() << "Setting up NetworkTables client for team " << team << '\n';
|
||||
fmt::print("Setting up NetworkTables client for team {}\n", team);
|
||||
ntinst.StartClientTeam(team);
|
||||
}
|
||||
|
||||
// start cameras
|
||||
for (auto&& camera : cameras) StartCamera(camera);
|
||||
for (auto&& camera : cameras) {
|
||||
StartCamera(camera);
|
||||
}
|
||||
|
||||
// loop forever
|
||||
for (;;) std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
for (;;) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.cameraserver;
|
||||
|
||||
public final class DevMain {
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) {}
|
||||
|
||||
}
|
||||
|
||||
private DevMain() {
|
||||
}
|
||||
private DevMain() {}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
int main() {}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,9 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.cameraserver;
|
||||
|
||||
|
||||
public interface CameraServerShared {
|
||||
/**
|
||||
* get the main thread id func.
|
||||
|
||||
@@ -1,56 +1,48 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.cameraserver;
|
||||
|
||||
public final class CameraServerSharedStore {
|
||||
private static CameraServerShared cameraServerShared;
|
||||
|
||||
private CameraServerSharedStore() {
|
||||
}
|
||||
private CameraServerSharedStore() {}
|
||||
|
||||
/**
|
||||
* get the CameraServerShared object.
|
||||
* Get the CameraServerShared object.
|
||||
*
|
||||
* @return The CameraServerSharedObject
|
||||
*/
|
||||
public static synchronized CameraServerShared getCameraServerShared() {
|
||||
if (cameraServerShared == null) {
|
||||
cameraServerShared = new CameraServerShared() {
|
||||
cameraServerShared =
|
||||
new CameraServerShared() {
|
||||
@Override
|
||||
public void reportVideoServer(int id) {}
|
||||
|
||||
@Override
|
||||
public void reportVideoServer(int id) {
|
||||
@Override
|
||||
public void reportUsbCamera(int id) {}
|
||||
|
||||
}
|
||||
@Override
|
||||
public void reportDriverStationError(String error) {}
|
||||
|
||||
@Override
|
||||
public void reportUsbCamera(int id) {
|
||||
@Override
|
||||
public void reportAxisCamera(int id) {}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportDriverStationError(String error) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportAxisCamera(int id) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getRobotMainThreadId() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public Long getRobotMainThreadId() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
return cameraServerShared;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the CameraServerShared object.
|
||||
* Set the CameraServerShared object.
|
||||
*
|
||||
* @param shared The CameraServerShared object.
|
||||
*/
|
||||
public static synchronized void setCameraServerShared(CameraServerShared shared) {
|
||||
cameraServerShared = shared;
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.vision;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
* A vision pipeline is responsible for running a group of
|
||||
* OpenCV algorithms to extract data from an image.
|
||||
* A vision pipeline is responsible for running a group of OpenCV algorithms to extract data from an
|
||||
* image.
|
||||
*
|
||||
* @see VisionRunner
|
||||
* @see VisionThread
|
||||
*/
|
||||
public interface VisionPipeline {
|
||||
/**
|
||||
* Processes the image input and sets the result objects.
|
||||
* Implementations should make these objects accessible.
|
||||
* Processes the image input and sets the result objects. Implementations should make these
|
||||
* objects accessible.
|
||||
*
|
||||
* @param image The image to process.
|
||||
*/
|
||||
void process(Mat image);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.vision;
|
||||
|
||||
import edu.wpi.first.cameraserver.CameraServerSharedStore;
|
||||
import edu.wpi.first.cscore.CvSink;
|
||||
import edu.wpi.first.cscore.VideoSource;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import edu.wpi.cscore.CvSink;
|
||||
import edu.wpi.cscore.VideoSource;
|
||||
import edu.wpi.first.cameraserver.CameraServerSharedStore;
|
||||
|
||||
/**
|
||||
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines
|
||||
* from robot 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.
|
||||
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines from robot
|
||||
* 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.
|
||||
*
|
||||
* @see VisionPipeline
|
||||
* @see VisionThread
|
||||
@@ -45,17 +41,16 @@ public class VisionRunner<P extends VisionPipeline> {
|
||||
* @param pipeline the vision pipeline that ran
|
||||
*/
|
||||
void copyPipelineOutputs(P pipeline);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to
|
||||
* the {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert
|
||||
* user code when it is safe to access the pipeline's outputs.
|
||||
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to the
|
||||
* {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert user
|
||||
* code when it is safe to access the pipeline's outputs.
|
||||
*
|
||||
* @param videoSource the video source to use to supply images for the pipeline
|
||||
* @param pipeline the vision pipeline to run
|
||||
* @param listener a function to call after the pipeline has finished running
|
||||
* @param pipeline the vision pipeline to run
|
||||
* @param listener a function to call after the pipeline has finished running
|
||||
*/
|
||||
public VisionRunner(VideoSource videoSource, P pipeline, Listener<? super P> listener) {
|
||||
this.m_pipeline = pipeline;
|
||||
@@ -64,15 +59,15 @@ public class VisionRunner<P extends VisionPipeline> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the pipeline one time, giving it the next image from the video source specified
|
||||
* in the constructor. This will block until the source either has an image or throws an error.
|
||||
* If the source successfully supplied a frame, the pipeline's image input will be set,
|
||||
* the pipeline will run, and the listener specified in the constructor will be called to notify
|
||||
* it that the pipeline ran.
|
||||
* Runs the pipeline one time, giving it the next image from the video source specified in the
|
||||
* constructor. This will block until the source either has an image or throws an error. If the
|
||||
* source successfully supplied a frame, the pipeline's image input will be set, the pipeline will
|
||||
* run, and the listener specified in the constructor will be called to notify it that the
|
||||
* pipeline ran.
|
||||
*
|
||||
* <p>This method is exposed to allow teams to add additional functionality or have their own
|
||||
* ways to run the pipeline. Most teams, however, should just use {@link #runForever} in its own
|
||||
* thread using a {@link VisionThread}.</p>
|
||||
* <p>This method is exposed to allow teams to add additional functionality or have their own ways
|
||||
* to run the pipeline. Most teams, however, should just use {@link #runForever} in its own thread
|
||||
* using a {@link VisionThread}.
|
||||
*/
|
||||
public void runOnce() {
|
||||
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
|
||||
@@ -98,11 +93,11 @@ public class VisionRunner<P extends VisionPipeline> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must
|
||||
* be run in a dedicated thread, and cannot be used in the main robot thread because
|
||||
* it will freeze the robot program.
|
||||
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must be run in a
|
||||
* dedicated thread, and cannot be used in the main robot thread because it will freeze the robot
|
||||
* program.
|
||||
*
|
||||
* <p><strong>Do not call this method directly from the main thread.</strong></p>
|
||||
* <p><strong>Do not call this method directly from the main thread.</strong>
|
||||
*
|
||||
* @throws IllegalStateException if this is called from the main robot thread
|
||||
* @see VisionThread
|
||||
@@ -119,9 +114,7 @@ public class VisionRunner<P extends VisionPipeline> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a RunForever() loop.
|
||||
*/
|
||||
/** Stop a RunForever() loop. */
|
||||
public void stop() {
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.vision;
|
||||
|
||||
import edu.wpi.cscore.VideoSource;
|
||||
import edu.wpi.first.cscore.VideoSource;
|
||||
|
||||
/**
|
||||
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread;
|
||||
* it does not prevent the program from exiting when all other non-daemon threads
|
||||
* have finished running.
|
||||
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread; it
|
||||
* does not prevent the program from exiting when all other non-daemon threads have finished
|
||||
* running.
|
||||
*
|
||||
* @see VisionPipeline
|
||||
* @see VisionRunner
|
||||
@@ -34,14 +31,12 @@ public class VisionThread extends Thread {
|
||||
* equivalent to {@code new VisionThread(new VisionRunner<>(videoSource, pipeline, listener))}.
|
||||
*
|
||||
* @param videoSource the source for images the pipeline should process
|
||||
* @param pipeline the pipeline to run
|
||||
* @param listener the listener to copy outputs from the pipeline after it runs
|
||||
* @param <P> the type of the pipeline
|
||||
* @param pipeline the pipeline to run
|
||||
* @param listener the listener to copy outputs from the pipeline after it runs
|
||||
* @param <P> the type of the pipeline
|
||||
*/
|
||||
public <P extends VisionPipeline> VisionThread(VideoSource videoSource,
|
||||
P pipeline,
|
||||
VisionRunner.Listener<? super P> listener) {
|
||||
public <P extends VisionPipeline> VisionThread(
|
||||
VideoSource videoSource, P pipeline, VisionRunner.Listener<? super P> listener) {
|
||||
this(new VisionRunner<>(videoSource, pipeline, listener));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* Classes in the {@code edu.wpi.first.vision} package are designed to
|
||||
* simplify using OpenCV vision processing code from a robot program.
|
||||
* Classes in the {@code edu.wpi.first.vision} package are designed to simplify using OpenCV vision
|
||||
* processing code from a robot program.
|
||||
*
|
||||
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous: <br>
|
||||
*
|
||||
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous:
|
||||
* <br>
|
||||
* <pre><code>
|
||||
* public class Robot extends IterativeRobot
|
||||
* public class Robot extends TimedRobot
|
||||
* implements VisionRunner.Listener<MyFindTotePipeline> {
|
||||
*
|
||||
* // A USB camera connected to the roboRIO.
|
||||
* private {@link edu.wpi.cscore.VideoSource VideoSource} usbCamera;
|
||||
* private {@link edu.wpi.first.cscore.VideoSource VideoSource} usbCamera;
|
||||
*
|
||||
* // A vision pipeline. This could be handwritten or generated by GRIP.
|
||||
* // This has to implement {@link edu.wpi.first.vision.VisionPipeline}.
|
||||
@@ -47,7 +44,7 @@
|
||||
*
|
||||
* {@literal @}Override
|
||||
* public void robotInit() {
|
||||
* usbCamera = CameraServer.getInstance().startAutomaticCapture(0);
|
||||
* usbCamera = CameraServer.startAutomaticCapture(0);
|
||||
* findTotePipeline = new MyFindTotePipeline();
|
||||
* findToteThread = new VisionThread(usbCamera, findTotePipeline, this);
|
||||
* }
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 "cameraserver/CameraServer.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <networktables/NetworkTable.h>
|
||||
#include <networktables/NetworkTableInstance.h>
|
||||
#include <wpi/DenseMap.h>
|
||||
#include <wpi/ManagedStatic.h>
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
#include <wpi/StringMap.h>
|
||||
#include <wpi/mutex.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
|
||||
#include "cameraserver/CameraServerShared.h"
|
||||
#include "ntcore_cpp.h"
|
||||
@@ -26,8 +23,9 @@ using namespace frc;
|
||||
|
||||
static constexpr char const* kPublishName = "/CameraPublisher";
|
||||
|
||||
struct CameraServer::Impl {
|
||||
Impl();
|
||||
namespace {
|
||||
struct Instance {
|
||||
Instance();
|
||||
std::shared_ptr<nt::NetworkTable> GetSourceTable(CS_Source source);
|
||||
std::vector<std::string> GetSinkStreamValues(CS_Sink sink);
|
||||
std::vector<std::string> GetSourceStreamValues(CS_Source source);
|
||||
@@ -40,41 +38,39 @@ struct CameraServer::Impl {
|
||||
wpi::StringMap<cs::VideoSink> m_sinks;
|
||||
wpi::DenseMap<CS_Sink, CS_Source> m_fixedSources;
|
||||
wpi::DenseMap<CS_Source, std::shared_ptr<nt::NetworkTable>> m_tables;
|
||||
std::shared_ptr<nt::NetworkTable> m_publishTable;
|
||||
std::shared_ptr<nt::NetworkTable> m_publishTable{
|
||||
nt::NetworkTableInstance::GetDefault().GetTable(kPublishName)};
|
||||
cs::VideoListener m_videoListener;
|
||||
int m_tableListener;
|
||||
int m_nextPort;
|
||||
int m_nextPort{CameraServer::kBasePort};
|
||||
std::vector<std::string> m_addresses;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
CameraServer* CameraServer::GetInstance() {
|
||||
struct Creator {
|
||||
static void* call() { return new CameraServer{}; }
|
||||
};
|
||||
struct Deleter {
|
||||
static void call(void* ptr) { delete static_cast<CameraServer*>(ptr); }
|
||||
};
|
||||
static wpi::ManagedStatic<CameraServer, Creator, Deleter> instance;
|
||||
return &(*instance);
|
||||
static Instance& GetInstance() {
|
||||
static Instance instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
static wpi::StringRef MakeSourceValue(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
static std::string_view MakeSourceValue(CS_Source source,
|
||||
wpi::SmallVectorImpl<char>& buf) {
|
||||
CS_Status status = 0;
|
||||
buf.clear();
|
||||
switch (cs::GetSourceKind(source, &status)) {
|
||||
case CS_SOURCE_USB: {
|
||||
wpi::StringRef prefix{"usb:"};
|
||||
std::string_view prefix{"usb:"};
|
||||
buf.append(prefix.begin(), prefix.end());
|
||||
auto path = cs::GetUsbCameraPath(source, &status);
|
||||
buf.append(path.begin(), path.end());
|
||||
break;
|
||||
}
|
||||
case CS_SOURCE_HTTP: {
|
||||
wpi::StringRef prefix{"ip:"};
|
||||
std::string_view prefix{"ip:"};
|
||||
buf.append(prefix.begin(), prefix.end());
|
||||
auto urls = cs::GetHttpCameraUrls(source, &status);
|
||||
if (!urls.empty()) buf.append(urls[0].begin(), urls[0].end());
|
||||
if (!urls.empty()) {
|
||||
buf.append(urls[0].begin(), urls[0].end());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CS_SOURCE_CV:
|
||||
@@ -83,27 +79,25 @@ static wpi::StringRef MakeSourceValue(CS_Source source,
|
||||
return "unknown:";
|
||||
}
|
||||
|
||||
return wpi::StringRef{buf.begin(), buf.size()};
|
||||
return {buf.begin(), buf.size()};
|
||||
}
|
||||
|
||||
static std::string MakeStreamValue(const wpi::Twine& address, int port) {
|
||||
return ("mjpg:http://" + address + wpi::Twine(':') + wpi::Twine(port) +
|
||||
"/?action=stream")
|
||||
.str();
|
||||
static std::string MakeStreamValue(std::string_view address, int port) {
|
||||
return fmt::format("mjpg:http://{}:{}/?action=stream", address, port);
|
||||
}
|
||||
|
||||
std::shared_ptr<nt::NetworkTable> CameraServer::Impl::GetSourceTable(
|
||||
CS_Source source) {
|
||||
std::shared_ptr<nt::NetworkTable> Instance::GetSourceTable(CS_Source source) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
return m_tables.lookup(source);
|
||||
}
|
||||
|
||||
std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
|
||||
std::vector<std::string> Instance::GetSinkStreamValues(CS_Sink sink) {
|
||||
CS_Status status = 0;
|
||||
|
||||
// Ignore all but MjpegServer
|
||||
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG)
|
||||
return std::vector<std::string>{};
|
||||
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get port
|
||||
int port = cs::GetMjpegServerPort(sink, &status);
|
||||
@@ -119,7 +113,9 @@ std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
|
||||
values.emplace_back(MakeStreamValue(cs::GetHostname() + ".local", port));
|
||||
|
||||
for (const auto& addr : m_addresses) {
|
||||
if (addr == "127.0.0.1") continue; // ignore localhost
|
||||
if (addr == "127.0.0.1") {
|
||||
continue; // ignore localhost
|
||||
}
|
||||
values.emplace_back(MakeStreamValue(addr, port));
|
||||
}
|
||||
}
|
||||
@@ -127,17 +123,19 @@ std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
|
||||
return values;
|
||||
}
|
||||
|
||||
std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
|
||||
CS_Source source) {
|
||||
std::vector<std::string> Instance::GetSourceStreamValues(CS_Source source) {
|
||||
CS_Status status = 0;
|
||||
|
||||
// Ignore all but HttpCamera
|
||||
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP)
|
||||
return std::vector<std::string>{};
|
||||
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Generate values
|
||||
auto values = cs::GetHttpCameraUrls(source, &status);
|
||||
for (auto& value : values) value = "mjpg:" + value;
|
||||
for (auto& value : values) {
|
||||
value = "mjpg:" + value;
|
||||
}
|
||||
|
||||
#ifdef __FRC_ROBORIO__
|
||||
// Look to see if we have a passthrough server for this source
|
||||
@@ -159,7 +157,7 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
|
||||
return values;
|
||||
}
|
||||
|
||||
void CameraServer::Impl::UpdateStreamValues() {
|
||||
void Instance::UpdateStreamValues() {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
// Over all the sinks...
|
||||
for (const auto& i : m_sinks) {
|
||||
@@ -168,16 +166,24 @@ void CameraServer::Impl::UpdateStreamValues() {
|
||||
|
||||
// Get the source's subtable (if none exists, we're done)
|
||||
CS_Source source = m_fixedSources.lookup(sink);
|
||||
if (source == 0) source = cs::GetSinkSource(sink, &status);
|
||||
if (source == 0) continue;
|
||||
if (source == 0) {
|
||||
source = cs::GetSinkSource(sink, &status);
|
||||
}
|
||||
if (source == 0) {
|
||||
continue;
|
||||
}
|
||||
auto table = m_tables.lookup(source);
|
||||
if (table) {
|
||||
// Don't set stream values if this is a HttpCamera passthrough
|
||||
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) continue;
|
||||
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set table value
|
||||
auto values = GetSinkStreamValues(sink);
|
||||
if (!values.empty()) table->GetEntry("streams").SetStringArray(values);
|
||||
if (!values.empty()) {
|
||||
table->GetEntry("streams").SetStringArray(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +196,9 @@ void CameraServer::Impl::UpdateStreamValues() {
|
||||
if (table) {
|
||||
// Set table value
|
||||
auto values = GetSourceStreamValues(source);
|
||||
if (!values.empty()) table->GetEntry("streams").SetStringArray(values);
|
||||
if (!values.empty()) {
|
||||
table->GetEntry("streams").SetStringArray(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,79 +221,72 @@ static std::string PixelFormatToString(int pixelFormat) {
|
||||
}
|
||||
|
||||
static std::string VideoModeToString(const cs::VideoMode& mode) {
|
||||
std::string rv;
|
||||
wpi::raw_string_ostream oss{rv};
|
||||
oss << mode.width << "x" << mode.height;
|
||||
oss << " " << PixelFormatToString(mode.pixelFormat) << " ";
|
||||
oss << mode.fps << " fps";
|
||||
return oss.str();
|
||||
return fmt::format("{}x{} {} {} fps", mode.width, mode.height,
|
||||
PixelFormatToString(mode.pixelFormat), mode.fps);
|
||||
}
|
||||
|
||||
static std::vector<std::string> GetSourceModeValues(int source) {
|
||||
std::vector<std::string> rv;
|
||||
CS_Status status = 0;
|
||||
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status))
|
||||
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status)) {
|
||||
rv.emplace_back(VideoModeToString(mode));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void PutSourcePropertyValue(nt::NetworkTable* table,
|
||||
const cs::VideoEvent& event, bool isNew) {
|
||||
wpi::SmallString<64> name;
|
||||
wpi::SmallString<64> infoName;
|
||||
if (wpi::StringRef{event.name}.startswith("raw_")) {
|
||||
name = "RawProperty/";
|
||||
name += event.name;
|
||||
infoName = "RawPropertyInfo/";
|
||||
infoName += event.name;
|
||||
std::string_view namePrefix;
|
||||
std::string_view infoPrefix;
|
||||
if (wpi::starts_with(event.name, "raw_")) {
|
||||
namePrefix = "RawProperty";
|
||||
infoPrefix = "RawPropertyInfo";
|
||||
} else {
|
||||
name = "Property/";
|
||||
name += event.name;
|
||||
infoName = "PropertyInfo/";
|
||||
infoName += event.name;
|
||||
namePrefix = "Property";
|
||||
infoPrefix = "PropertyInfo";
|
||||
}
|
||||
|
||||
wpi::SmallString<64> buf;
|
||||
CS_Status status = 0;
|
||||
nt::NetworkTableEntry entry = table->GetEntry(name);
|
||||
nt::NetworkTableEntry entry =
|
||||
table->GetEntry(fmt::format("{}/{}", namePrefix, event.name));
|
||||
switch (event.propertyKind) {
|
||||
case CS_PROP_BOOLEAN:
|
||||
if (isNew)
|
||||
if (isNew) {
|
||||
entry.SetDefaultBoolean(event.value != 0);
|
||||
else
|
||||
} else {
|
||||
entry.SetBoolean(event.value != 0);
|
||||
}
|
||||
break;
|
||||
case CS_PROP_INTEGER:
|
||||
case CS_PROP_ENUM:
|
||||
if (isNew) {
|
||||
entry.SetDefaultDouble(event.value);
|
||||
table->GetEntry(infoName + "/min")
|
||||
table->GetEntry(fmt::format("{}/{}/min", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyMin(event.propertyHandle, &status));
|
||||
table->GetEntry(infoName + "/max")
|
||||
table->GetEntry(fmt::format("{}/{}/max", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyMax(event.propertyHandle, &status));
|
||||
table->GetEntry(infoName + "/step")
|
||||
table->GetEntry(fmt::format("{}/{}/step", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyStep(event.propertyHandle, &status));
|
||||
table->GetEntry(infoName + "/default")
|
||||
table->GetEntry(fmt::format("{}/{}/default", infoPrefix, event.name))
|
||||
.SetDouble(cs::GetPropertyDefault(event.propertyHandle, &status));
|
||||
} else {
|
||||
entry.SetDouble(event.value);
|
||||
}
|
||||
break;
|
||||
case CS_PROP_STRING:
|
||||
if (isNew)
|
||||
if (isNew) {
|
||||
entry.SetDefaultString(event.valueStr);
|
||||
else
|
||||
} else {
|
||||
entry.SetString(event.valueStr);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CameraServer::Impl::Impl()
|
||||
: m_publishTable{nt::NetworkTableInstance::GetDefault().GetTable(
|
||||
kPublishName)},
|
||||
m_nextPort(kBasePort) {
|
||||
Instance::Instance() {
|
||||
// We publish sources to NetworkTables using the following structure:
|
||||
// "/CameraPublisher/{Source.Name}/" - root
|
||||
// - "source" (string): Descriptive, prefixed with type (e.g. "usb:0")
|
||||
@@ -351,41 +352,48 @@ CameraServer::Impl::Impl()
|
||||
}
|
||||
case cs::VideoEvent::kSourceDisconnected: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table) table->GetEntry("connected").SetBoolean(false);
|
||||
if (table) {
|
||||
table->GetEntry("connected").SetBoolean(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cs::VideoEvent::kSourceVideoModesUpdated: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table)
|
||||
if (table) {
|
||||
table->GetEntry("modes").SetStringArray(
|
||||
GetSourceModeValues(event.sourceHandle));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cs::VideoEvent::kSourceVideoModeChanged: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table)
|
||||
if (table) {
|
||||
table->GetEntry("mode").SetString(VideoModeToString(event.mode));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cs::VideoEvent::kSourcePropertyCreated: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table) PutSourcePropertyValue(table.get(), event, true);
|
||||
if (table) {
|
||||
PutSourcePropertyValue(table.get(), event, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cs::VideoEvent::kSourcePropertyValueUpdated: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table) PutSourcePropertyValue(table.get(), event, false);
|
||||
if (table) {
|
||||
PutSourcePropertyValue(table.get(), event, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cs::VideoEvent::kSourcePropertyChoicesUpdated: {
|
||||
auto table = GetSourceTable(event.sourceHandle);
|
||||
if (table) {
|
||||
wpi::SmallString<64> name{"PropertyInfo/"};
|
||||
name += event.name;
|
||||
name += "/choices";
|
||||
auto choices =
|
||||
cs::GetEnumPropertyChoices(event.propertyHandle, &status);
|
||||
table->GetEntry(name).SetStringArray(choices);
|
||||
table
|
||||
->GetEntry(fmt::format("PropertyInfo/{}/choices", event.name))
|
||||
.SetStringArray(choices);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -409,32 +417,36 @@ CameraServer::Impl::Impl()
|
||||
// else tries to change it.
|
||||
wpi::SmallString<64> buf;
|
||||
m_tableListener = nt::NetworkTableInstance::GetDefault().AddEntryListener(
|
||||
kPublishName + wpi::Twine('/'),
|
||||
fmt::format("{}/", kPublishName),
|
||||
[=](const nt::EntryNotification& event) {
|
||||
wpi::StringRef relativeKey =
|
||||
event.name.substr(wpi::StringRef(kPublishName).size() + 1);
|
||||
auto relativeKey = wpi::drop_front(
|
||||
event.name, std::string_view{kPublishName}.size() + 1);
|
||||
|
||||
// get source (sourceName/...)
|
||||
auto subKeyIndex = relativeKey.find('/');
|
||||
if (subKeyIndex == wpi::StringRef::npos) return;
|
||||
wpi::StringRef sourceName = relativeKey.slice(0, subKeyIndex);
|
||||
if (subKeyIndex == std::string_view::npos) {
|
||||
return;
|
||||
}
|
||||
auto sourceName = wpi::slice(relativeKey, 0, subKeyIndex);
|
||||
auto sourceIt = m_sources.find(sourceName);
|
||||
if (sourceIt == m_sources.end()) return;
|
||||
if (sourceIt == m_sources.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get subkey
|
||||
relativeKey = relativeKey.substr(subKeyIndex + 1);
|
||||
relativeKey.remove_prefix(subKeyIndex + 1);
|
||||
|
||||
// handle standard names
|
||||
wpi::StringRef propName;
|
||||
std::string_view propName;
|
||||
nt::NetworkTableEntry entry{event.entry};
|
||||
if (relativeKey == "mode") {
|
||||
// reset to current mode
|
||||
entry.SetString(VideoModeToString(sourceIt->second.GetVideoMode()));
|
||||
return;
|
||||
} else if (relativeKey.startswith("Property/")) {
|
||||
propName = relativeKey.substr(9);
|
||||
} else if (relativeKey.startswith("RawProperty/")) {
|
||||
propName = relativeKey.substr(12);
|
||||
} else if (wpi::starts_with(relativeKey, "Property/")) {
|
||||
propName = wpi::substr(relativeKey, 9);
|
||||
} else if (wpi::starts_with(relativeKey, "RawProperty/")) {
|
||||
propName = wpi::substr(relativeKey, 12);
|
||||
} else {
|
||||
return; // ignore
|
||||
}
|
||||
@@ -461,26 +473,23 @@ CameraServer::Impl::Impl()
|
||||
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_UPDATE);
|
||||
}
|
||||
|
||||
CameraServer::CameraServer() : m_impl(new Impl) {}
|
||||
|
||||
CameraServer::~CameraServer() {}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture() {
|
||||
cs::UsbCamera camera = StartAutomaticCapture(m_impl->m_defaultUsbDevice++);
|
||||
cs::UsbCamera camera =
|
||||
StartAutomaticCapture(::GetInstance().m_defaultUsbDevice++);
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->ReportUsbCamera(camera.GetHandle());
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) {
|
||||
cs::UsbCamera camera{"USB Camera " + wpi::Twine(dev), dev};
|
||||
cs::UsbCamera camera{fmt::format("USB Camera {}", dev), dev};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->ReportUsbCamera(camera.GetHandle());
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
|
||||
int dev) {
|
||||
cs::UsbCamera camera{name, dev};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -489,8 +498,8 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
const wpi::Twine& path) {
|
||||
cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
|
||||
std::string_view path) {
|
||||
cs::UsbCamera camera{name, path};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -498,7 +507,7 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& host) {
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view host) {
|
||||
return AddAxisCamera("Axis Camera", host);
|
||||
}
|
||||
|
||||
@@ -510,12 +519,12 @@ cs::AxisCamera CameraServer::AddAxisCamera(const std::string& host) {
|
||||
return AddAxisCamera("Axis Camera", host);
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(wpi::ArrayRef<std::string> hosts) {
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(wpi::span<const std::string> hosts) {
|
||||
return AddAxisCamera("Axis Camera", hosts);
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
const wpi::Twine& host) {
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
std::string_view host) {
|
||||
cs::AxisCamera camera{name, host};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -523,7 +532,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
const char* host) {
|
||||
cs::AxisCamera camera{name, host};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -532,7 +541,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
const std::string& host) {
|
||||
cs::AxisCamera camera{name, host};
|
||||
StartAutomaticCapture(camera);
|
||||
@@ -541,8 +550,8 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
wpi::ArrayRef<std::string> hosts) {
|
||||
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
|
||||
wpi::span<const std::string> hosts) {
|
||||
cs::AxisCamera camera{name, hosts};
|
||||
StartAutomaticCapture(camera);
|
||||
auto csShared = GetCameraServerShared();
|
||||
@@ -550,11 +559,11 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
|
||||
return camera;
|
||||
}
|
||||
|
||||
cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
|
||||
cs::MjpegServer CameraServer::AddSwitchedCamera(std::string_view name) {
|
||||
// create a dummy CvSource
|
||||
cs::CvSource source{name, cs::VideoMode::PixelFormat::kMJPEG, 160, 120, 30};
|
||||
cs::MjpegServer server = StartAutomaticCapture(source);
|
||||
m_impl->m_fixedSources[server.GetHandle()] = source.GetHandle();
|
||||
::GetInstance().m_fixedSources[server.GetHandle()] = source.GetHandle();
|
||||
|
||||
return server;
|
||||
}
|
||||
@@ -562,22 +571,23 @@ cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
|
||||
cs::MjpegServer CameraServer::StartAutomaticCapture(
|
||||
const cs::VideoSource& camera) {
|
||||
AddCamera(camera);
|
||||
auto server = AddServer(wpi::Twine("serve_") + camera.GetName());
|
||||
auto server = AddServer(fmt::format("serve_{}", camera.GetName()));
|
||||
server.SetSource(camera);
|
||||
return server;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo() {
|
||||
auto& inst = ::GetInstance();
|
||||
cs::VideoSource source;
|
||||
{
|
||||
auto csShared = GetCameraServerShared();
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) {
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
if (inst.m_primarySourceName.empty()) {
|
||||
csShared->SetCameraServerError("no camera available");
|
||||
return cs::CvSink{};
|
||||
}
|
||||
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
|
||||
if (it == m_impl->m_sources.end()) {
|
||||
auto it = inst.m_sources.find(inst.m_primarySourceName);
|
||||
if (it == inst.m_sources.end()) {
|
||||
csShared->SetCameraServerError("no camera available");
|
||||
return cs::CvSink{};
|
||||
}
|
||||
@@ -587,40 +597,40 @@ cs::CvSink CameraServer::GetVideo() {
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
|
||||
auto& inst = ::GetInstance();
|
||||
wpi::SmallString<64> name{"opencv_"};
|
||||
name += camera.GetName();
|
||||
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sinks.find(name);
|
||||
if (it != m_impl->m_sinks.end()) {
|
||||
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 " +
|
||||
wpi::Twine(kind));
|
||||
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};
|
||||
cs::CvSink newsink{name.str()};
|
||||
newsink.SetSource(camera);
|
||||
AddServer(newsink);
|
||||
return newsink;
|
||||
}
|
||||
|
||||
cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
|
||||
wpi::SmallString<64> nameBuf;
|
||||
wpi::StringRef nameStr = name.toStringRef(nameBuf);
|
||||
cs::CvSink CameraServer::GetVideo(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
cs::VideoSource source;
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sources.find(nameStr);
|
||||
if (it == m_impl->m_sources.end()) {
|
||||
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 " + nameStr);
|
||||
csShared->SetCameraServerError("could not find camera {}", name);
|
||||
return cs::CvSink{};
|
||||
}
|
||||
source = it->second;
|
||||
@@ -628,89 +638,99 @@ cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
|
||||
return GetVideo(source);
|
||||
}
|
||||
|
||||
cs::CvSource CameraServer::PutVideo(const wpi::Twine& name, int width,
|
||||
cs::CvSource CameraServer::PutVideo(std::string_view name, int width,
|
||||
int height) {
|
||||
cs::CvSource source{name, cs::VideoMode::kMJPEG, width, height, 30};
|
||||
StartAutomaticCapture(source);
|
||||
return source;
|
||||
}
|
||||
|
||||
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
|
||||
cs::MjpegServer CameraServer::AddServer(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
int port;
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
port = m_impl->m_nextPort++;
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
port = inst.m_nextPort++;
|
||||
}
|
||||
return AddServer(name, port);
|
||||
}
|
||||
|
||||
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name, int port) {
|
||||
cs::MjpegServer CameraServer::AddServer(std::string_view name, int port) {
|
||||
cs::MjpegServer server{name, port};
|
||||
AddServer(server);
|
||||
return server;
|
||||
}
|
||||
|
||||
void CameraServer::AddServer(const cs::VideoSink& server) {
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
m_impl->m_sinks.try_emplace(server.GetName(), server);
|
||||
auto& inst = ::GetInstance();
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
inst.m_sinks.try_emplace(server.GetName(), server);
|
||||
}
|
||||
|
||||
void CameraServer::RemoveServer(const wpi::Twine& name) {
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
wpi::SmallString<64> nameBuf;
|
||||
m_impl->m_sinks.erase(name.toStringRef(nameBuf));
|
||||
void CameraServer::RemoveServer(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
inst.m_sinks.erase(name);
|
||||
}
|
||||
|
||||
cs::VideoSink CameraServer::GetServer() {
|
||||
wpi::SmallString<64> name;
|
||||
auto& inst = ::GetInstance();
|
||||
std::string name;
|
||||
{
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) {
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
if (inst.m_primarySourceName.empty()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("no camera available");
|
||||
return cs::VideoSink{};
|
||||
}
|
||||
name = "serve_";
|
||||
name += m_impl->m_primarySourceName;
|
||||
name = fmt::format("serve_{}", inst.m_primarySourceName);
|
||||
}
|
||||
return GetServer(name);
|
||||
}
|
||||
|
||||
cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
|
||||
wpi::SmallString<64> nameBuf;
|
||||
wpi::StringRef nameStr = name.toStringRef(nameBuf);
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
auto it = m_impl->m_sinks.find(nameStr);
|
||||
if (it == m_impl->m_sinks.end()) {
|
||||
cs::VideoSink CameraServer::GetServer(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
auto it = inst.m_sinks.find(name);
|
||||
if (it == inst.m_sinks.end()) {
|
||||
auto csShared = GetCameraServerShared();
|
||||
csShared->SetCameraServerError("could not find server " + nameStr);
|
||||
csShared->SetCameraServerError("could not find server {}", name);
|
||||
return cs::VideoSink{};
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void CameraServer::AddCamera(const cs::VideoSource& camera) {
|
||||
auto& inst = ::GetInstance();
|
||||
std::string name = camera.GetName();
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) m_impl->m_primarySourceName = name;
|
||||
m_impl->m_sources.try_emplace(name, camera);
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
if (inst.m_primarySourceName.empty()) {
|
||||
inst.m_primarySourceName = name;
|
||||
}
|
||||
inst.m_sources.try_emplace(name, camera);
|
||||
}
|
||||
|
||||
void CameraServer::RemoveCamera(const wpi::Twine& name) {
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
wpi::SmallString<64> nameBuf;
|
||||
m_impl->m_sources.erase(name.toStringRef(nameBuf));
|
||||
void CameraServer::RemoveCamera(std::string_view name) {
|
||||
auto& inst = ::GetInstance();
|
||||
std::scoped_lock lock(inst.m_mutex);
|
||||
inst.m_sources.erase(name);
|
||||
}
|
||||
|
||||
void CameraServer::SetSize(int size) {
|
||||
std::scoped_lock lock(m_impl->m_mutex);
|
||||
if (m_impl->m_primarySourceName.empty()) return;
|
||||
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
|
||||
if (it == m_impl->m_sources.end()) return;
|
||||
if (size == kSize160x120)
|
||||
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)
|
||||
} else if (size == kSize320x240) {
|
||||
it->second.SetResolution(320, 240);
|
||||
else if (size == kSize640x480)
|
||||
} else if (size == kSize640x480) {
|
||||
it->second.SetResolution(640, 480);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 "cameraserver/CameraServerShared.h"
|
||||
|
||||
@@ -15,9 +12,12 @@ class DefaultCameraServerShared : public frc::CameraServerShared {
|
||||
void ReportUsbCamera(int id) override {}
|
||||
void ReportAxisCamera(int id) override {}
|
||||
void ReportVideoServer(int id) override {}
|
||||
void SetCameraServerError(const wpi::Twine& error) override {}
|
||||
void SetVisionRunnerError(const wpi::Twine& error) override {}
|
||||
void ReportDriverStationError(const wpi::Twine& error) override {}
|
||||
void SetCameraServerErrorV(fmt::string_view format,
|
||||
fmt::format_args args) override {}
|
||||
void SetVisionRunnerErrorV(fmt::string_view format,
|
||||
fmt::format_args args) override {}
|
||||
void ReportDriverStationErrorV(fmt::string_view format,
|
||||
fmt::format_args args) override {}
|
||||
std::pair<std::thread::id, bool> GetRobotMainThreadId() const override {
|
||||
return std::make_pair(std::thread::id(), false);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 "vision/VisionRunner.h"
|
||||
|
||||
@@ -23,7 +20,7 @@ VisionRunnerBase::VisionRunnerBase(cs::VideoSource videoSource)
|
||||
}
|
||||
|
||||
// Located here and not in header due to cv::Mat forward declaration.
|
||||
VisionRunnerBase::~VisionRunnerBase() {}
|
||||
VisionRunnerBase::~VisionRunnerBase() = default;
|
||||
|
||||
void VisionRunnerBase::RunOnce() {
|
||||
auto csShared = frc::GetCameraServerShared();
|
||||
@@ -36,7 +33,7 @@ void VisionRunnerBase::RunOnce() {
|
||||
auto frameTime = m_cvSink.GrabFrame(*m_image);
|
||||
if (frameTime == 0) {
|
||||
auto error = m_cvSink.GetError();
|
||||
csShared->ReportDriverStationError(error);
|
||||
csShared->ReportDriverStationError(error.c_str());
|
||||
} else {
|
||||
DoProcess(*m_image);
|
||||
}
|
||||
@@ -56,4 +53,6 @@ void VisionRunnerBase::RunForever() {
|
||||
}
|
||||
}
|
||||
|
||||
void VisionRunnerBase::Stop() { m_enabled = false; }
|
||||
void VisionRunnerBase::Stop() {
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2014-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <wpi/ArrayRef.h>
|
||||
#include <wpi/Twine.h>
|
||||
#include <wpi/span.h>
|
||||
|
||||
#include "cscore.h"
|
||||
#include "cscore_cv.h"
|
||||
@@ -32,11 +28,6 @@ class CameraServer {
|
||||
static constexpr int kSize320x240 = 1;
|
||||
static constexpr int kSize160x120 = 2;
|
||||
|
||||
/**
|
||||
* Get the CameraServer instance.
|
||||
*/
|
||||
static CameraServer* GetInstance();
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
*
|
||||
@@ -48,7 +39,7 @@ class CameraServer {
|
||||
* with device 0, creating a camera named "USB Camera 0". Subsequent calls
|
||||
* increment the device number (e.g. 1, 2, etc).
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture();
|
||||
static cs::UsbCamera StartAutomaticCapture();
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
@@ -58,7 +49,7 @@ class CameraServer {
|
||||
*
|
||||
* @param dev The device number of the camera interface
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture(int dev);
|
||||
static cs::UsbCamera StartAutomaticCapture(int dev);
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
@@ -66,7 +57,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param dev The device number of the camera interface
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name, int dev);
|
||||
static cs::UsbCamera StartAutomaticCapture(std::string_view name, int dev);
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard.
|
||||
@@ -74,8 +65,8 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param path The device path (e.g. "/dev/video0") of the camera
|
||||
*/
|
||||
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name,
|
||||
const wpi::Twine& path);
|
||||
static cs::UsbCamera StartAutomaticCapture(std::string_view name,
|
||||
std::string_view path);
|
||||
|
||||
/**
|
||||
* Start automatically capturing images to send to the dashboard from
|
||||
@@ -83,7 +74,7 @@ class CameraServer {
|
||||
*
|
||||
* @param camera Camera
|
||||
*/
|
||||
cs::MjpegServer StartAutomaticCapture(const cs::VideoSource& camera);
|
||||
static cs::MjpegServer StartAutomaticCapture(const cs::VideoSource& camera);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -92,7 +83,7 @@ class CameraServer {
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& host);
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -101,7 +92,7 @@ class CameraServer {
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const char* host);
|
||||
static cs::AxisCamera AddAxisCamera(const char* host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -110,7 +101,7 @@ class CameraServer {
|
||||
*
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const std::string& host);
|
||||
static cs::AxisCamera AddAxisCamera(const std::string& host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -119,7 +110,7 @@ class CameraServer {
|
||||
*
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(wpi::ArrayRef<std::string> hosts);
|
||||
static cs::AxisCamera AddAxisCamera(wpi::span<const std::string> hosts);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -129,7 +120,7 @@ class CameraServer {
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
template <typename T>
|
||||
cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
|
||||
static cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -137,7 +128,8 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const wpi::Twine& host);
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
std::string_view host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -145,7 +137,7 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const char* host);
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name, const char* host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -153,7 +145,8 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const std::string& host);
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
const std::string& host);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -161,8 +154,8 @@ class CameraServer {
|
||||
* @param name The name to give the camera
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
|
||||
wpi::ArrayRef<std::string> hosts);
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
wpi::span<const std::string> hosts);
|
||||
|
||||
/**
|
||||
* Adds an Axis IP camera.
|
||||
@@ -171,8 +164,8 @@ class CameraServer {
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
template <typename T>
|
||||
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
|
||||
std::initializer_list<T> hosts);
|
||||
static cs::AxisCamera AddAxisCamera(std::string_view name,
|
||||
std::initializer_list<T> hosts);
|
||||
|
||||
/**
|
||||
* Adds a virtual camera for switching between two streams. Unlike the
|
||||
@@ -180,7 +173,7 @@ class CameraServer {
|
||||
* VideoSource. Calling SetSource() on the returned object can be used
|
||||
* to switch the actual source of the stream.
|
||||
*/
|
||||
cs::MjpegServer AddSwitchedCamera(const wpi::Twine& name);
|
||||
static cs::MjpegServer AddSwitchedCamera(std::string_view name);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the primary camera feed. This allows you to
|
||||
@@ -189,7 +182,7 @@ class CameraServer {
|
||||
* <p>This is only valid to call after a camera feed has been added
|
||||
* with startAutomaticCapture() or addServer().
|
||||
*/
|
||||
cs::CvSink GetVideo();
|
||||
static cs::CvSink GetVideo();
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
@@ -197,7 +190,7 @@ class CameraServer {
|
||||
*
|
||||
* @param camera Camera (e.g. as returned by startAutomaticCapture).
|
||||
*/
|
||||
cs::CvSink GetVideo(const cs::VideoSource& camera);
|
||||
static cs::CvSink GetVideo(const cs::VideoSource& camera);
|
||||
|
||||
/**
|
||||
* Get OpenCV access to the specified camera. This allows you to get
|
||||
@@ -205,7 +198,7 @@ class CameraServer {
|
||||
*
|
||||
* @param name Camera name
|
||||
*/
|
||||
cs::CvSink GetVideo(const wpi::Twine& name);
|
||||
static cs::CvSink GetVideo(std::string_view name);
|
||||
|
||||
/**
|
||||
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
|
||||
@@ -215,35 +208,36 @@ class CameraServer {
|
||||
* @param width Width of the image being sent
|
||||
* @param height Height of the image being sent
|
||||
*/
|
||||
cs::CvSource PutVideo(const wpi::Twine& name, int width, int height);
|
||||
static cs::CvSource PutVideo(std::string_view name, int width, int height);
|
||||
|
||||
/**
|
||||
* Adds a MJPEG server at the next available port.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
cs::MjpegServer AddServer(const wpi::Twine& name);
|
||||
static cs::MjpegServer AddServer(std::string_view name);
|
||||
|
||||
/**
|
||||
* Adds a MJPEG server.
|
||||
*
|
||||
* @param name Server name
|
||||
* @param port Port number
|
||||
*/
|
||||
cs::MjpegServer AddServer(const wpi::Twine& name, int port);
|
||||
static cs::MjpegServer AddServer(std::string_view name, int port);
|
||||
|
||||
/**
|
||||
* Adds an already created server.
|
||||
*
|
||||
* @param server Server
|
||||
*/
|
||||
void AddServer(const cs::VideoSink& server);
|
||||
static void AddServer(const cs::VideoSink& server);
|
||||
|
||||
/**
|
||||
* Removes a server by name.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
void RemoveServer(const wpi::Twine& name);
|
||||
static void RemoveServer(std::string_view name);
|
||||
|
||||
/**
|
||||
* Get server for the primary camera feed.
|
||||
@@ -251,28 +245,28 @@ class CameraServer {
|
||||
* This is only valid to call after a camera feed has been added with
|
||||
* StartAutomaticCapture() or AddServer().
|
||||
*/
|
||||
cs::VideoSink GetServer();
|
||||
static cs::VideoSink GetServer();
|
||||
|
||||
/**
|
||||
* Gets a server by name.
|
||||
*
|
||||
* @param name Server name
|
||||
*/
|
||||
cs::VideoSink GetServer(const wpi::Twine& name);
|
||||
static cs::VideoSink GetServer(std::string_view name);
|
||||
|
||||
/**
|
||||
* Adds an already created camera.
|
||||
*
|
||||
* @param camera Camera
|
||||
*/
|
||||
void AddCamera(const cs::VideoSource& camera);
|
||||
static void AddCamera(const cs::VideoSource& camera);
|
||||
|
||||
/**
|
||||
* Removes a camera by name.
|
||||
*
|
||||
* @param name Camera name
|
||||
*/
|
||||
void RemoveCamera(const wpi::Twine& name);
|
||||
static void RemoveCamera(std::string_view name);
|
||||
|
||||
/**
|
||||
* Sets the size of the image to use. Use the public kSize constants to set
|
||||
@@ -283,14 +277,10 @@ class CameraServer {
|
||||
* StartAutomaticCapture() instead.
|
||||
* @param size The size to use
|
||||
*/
|
||||
void SetSize(int size);
|
||||
static void SetSize(int size);
|
||||
|
||||
private:
|
||||
CameraServer();
|
||||
~CameraServer();
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
CameraServer() = default;
|
||||
};
|
||||
|
||||
} // namespace frc
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cameraserver/CameraServer.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
template <typename T>
|
||||
@@ -20,10 +19,12 @@ inline cs::AxisCamera CameraServer::AddAxisCamera(
|
||||
|
||||
template <typename T>
|
||||
inline cs::AxisCamera CameraServer::AddAxisCamera(
|
||||
const wpi::Twine& name, std::initializer_list<T> hosts) {
|
||||
std::string_view name, std::initializer_list<T> hosts) {
|
||||
std::vector<std::string> vec;
|
||||
vec.reserve(hosts.size());
|
||||
for (const auto& host : hosts) vec.emplace_back(host);
|
||||
for (const auto& host : hosts) {
|
||||
vec.emplace_back(host);
|
||||
}
|
||||
return AddAxisCamera(name, vec);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -11,7 +8,7 @@
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <wpi/Twine.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
namespace frc {
|
||||
class CameraServerShared {
|
||||
@@ -20,10 +17,28 @@ class CameraServerShared {
|
||||
virtual void ReportUsbCamera(int id) = 0;
|
||||
virtual void ReportAxisCamera(int id) = 0;
|
||||
virtual void ReportVideoServer(int id) = 0;
|
||||
virtual void SetCameraServerError(const wpi::Twine& error) = 0;
|
||||
virtual void SetVisionRunnerError(const wpi::Twine& error) = 0;
|
||||
virtual void ReportDriverStationError(const wpi::Twine& error) = 0;
|
||||
virtual void SetCameraServerErrorV(fmt::string_view format,
|
||||
fmt::format_args args) = 0;
|
||||
virtual void SetVisionRunnerErrorV(fmt::string_view format,
|
||||
fmt::format_args args) = 0;
|
||||
virtual void ReportDriverStationErrorV(fmt::string_view format,
|
||||
fmt::format_args args) = 0;
|
||||
virtual std::pair<std::thread::id, bool> GetRobotMainThreadId() const = 0;
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void SetCameraServerError(const S& format, Args&&... args) {
|
||||
SetCameraServerErrorV(format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void SetVisionRunnerError(const S& format, Args&&... args) {
|
||||
SetVisionRunnerErrorV(format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void ReportDriverStationError(const S& format, Args&&... args) {
|
||||
ReportDriverStationErrorV(format, fmt::make_format_args(args...));
|
||||
}
|
||||
};
|
||||
|
||||
CameraServerShared* GetCameraServerShared();
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
@@ -47,14 +44,14 @@ class VisionRunnerBase {
|
||||
*
|
||||
* <p>This method is exposed to allow teams to add additional functionality or
|
||||
* have their own ways to run the pipeline. Most teams, however, should just
|
||||
* use {@link #runForever} in its own thread using a std::thread.</p>
|
||||
* use RunForever() in its own thread using a std::thread.</p>
|
||||
*/
|
||||
void RunOnce();
|
||||
|
||||
/**
|
||||
* A convenience method that calls {@link #runOnce()} in an infinite loop.
|
||||
* This must be run in a dedicated thread, and cannot be used in the main
|
||||
* robot thread because it will freeze the robot program.
|
||||
* A convenience method that calls runOnce() in an infinite loop. This must be
|
||||
* run in a dedicated thread, and cannot be used in the main robot thread
|
||||
* because it will freeze the robot program.
|
||||
*
|
||||
* <strong>Do not call this method directly from the main thread.</strong>
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vision/VisionRunner.h"
|
||||
|
||||
namespace frc {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.
|
||||
|
||||
int main() { return 0; }
|
||||
int main() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ macro(wpilib_add_test name srcdir)
|
||||
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
|
||||
endif()
|
||||
if (MSVC)
|
||||
target_compile_options(${name}_test PRIVATE /wd4251 /wd4101)
|
||||
target_compile_options(${name}_test PRIVATE /wd4101 /wd4251)
|
||||
endif()
|
||||
add_test(NAME ${name} COMMAND ${name}_test)
|
||||
endmacro()
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
macro(wpilib_target_warnings target)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter -Wno-error=deprecated-declarations)
|
||||
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter ${WPILIB_TARGET_WARNINGS})
|
||||
else()
|
||||
target_compile_options(${target} PRIVATE /wd4244 /wd4267 /wd4146 /WX /wd4996)
|
||||
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>)
|
||||
elseif(UNIX AND APPLE)
|
||||
target_compile_options(${target} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-anon-enum-enum-conversion>)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
116
cmake/modules/FindLIBSSH.cmake
Normal file
116
cmake/modules/FindLIBSSH.cmake
Normal file
@@ -0,0 +1,116 @@
|
||||
# - Try to find LibSSH
|
||||
# Once done this will define
|
||||
#
|
||||
# LIBSSH_FOUND - system has LibSSH
|
||||
# LIBSSH_INCLUDE_DIRS - the LibSSH include directory
|
||||
# LIBSSH_LIBRARIES - link these to use LibSSH
|
||||
# LIBSSH_VERSION -
|
||||
#
|
||||
# Author Michal Vasko <mvasko@cesnet.cz>
|
||||
# Copyright (c) 2020 CESNET, z.s.p.o.
|
||||
#
|
||||
# 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 copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
#
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if(LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(LIBSSH_FOUND TRUE)
|
||||
else()
|
||||
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
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
if(LIBSSH_INCLUDE_DIR AND LIBSSH_LIBRARY)
|
||||
# learn libssh version
|
||||
if(EXISTS ${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h)
|
||||
set(LIBSSH_HEADER_PATH ${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h)
|
||||
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]+")
|
||||
if(NOT LIBSSH_VERSION_MAJOR)
|
||||
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]+")
|
||||
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]+")
|
||||
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${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"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_LIBRARY}
|
||||
)
|
||||
string(REPLACE "libssh.dylib" "libssh_threads.dylib"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_THREADS_LIBRARY}
|
||||
)
|
||||
string(REPLACE "ssh.so" "ssh_threads.so"
|
||||
LIBSSH_THREADS_LIBRARY
|
||||
${LIBSSH_THREADS_LIBRARY}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LIBSSH_INCLUDE_DIRS ${LIBSSH_INCLUDE_DIR})
|
||||
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
|
||||
REQUIRED_VARS LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES
|
||||
VERSION_VAR LIBSSH_VERSION)
|
||||
endif()
|
||||
@@ -7,7 +7,7 @@ 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 <wpi/StringRef.h>\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}")
|
||||
@@ -17,7 +17,7 @@ FILE(APPEND "${output}" "const unsigned char* ${prefix}${funcName}(size_t* len)
|
||||
IF(NOT namespace STREQUAL "")
|
||||
FILE(APPEND "${output}" "namespace ${namespace} {\n")
|
||||
ENDIF()
|
||||
FILE(APPEND "${output}" "wpi::StringRef ${funcName}() {\n return wpi::StringRef(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
|
||||
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 @@
|
||||
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
|
||||
set(GNU_MACHINE "arm-frc2021-linux-gnueabi" CACHE STRING "GNU compiler triple")
|
||||
set(GNU_MACHINE "arm-frc2022-linux-gnueabi" CACHE STRING "GNU compiler triple")
|
||||
set(SOFTFP yes)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/arm.toolchain.cmake")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
|
||||
# load settings in case of "try compile"
|
||||
set(TOOLCHAIN_CONFIG_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
|
||||
set(TOOLCHAIN_CONFIG_FILE "${WPILIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
|
||||
get_property(__IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
|
||||
if(__IN_TRY_COMPILE)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake" OPTIONAL) # CMAKE_BINARY_DIR is different
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake" OPTIONAL) # WPILIB_BINARY_DIR is different
|
||||
macro(toolchain_save_config)
|
||||
# nothing
|
||||
endmacro()
|
||||
|
||||
115
crossConnIntegrationTests/build.gradle
Normal file
115
crossConnIntegrationTests/build.gradle
Normal file
@@ -0,0 +1,115 @@
|
||||
import org.gradle.language.base.internal.ProjectLayout
|
||||
import edu.wpi.first.deployutils.deploy.target.RemoteTarget
|
||||
import edu.wpi.first.deployutils.deploy.target.location.SshDeployLocation
|
||||
import edu.wpi.first.deployutils.deploy.artifact.*
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
apply plugin: 'cpp'
|
||||
apply plugin: 'visual-studio'
|
||||
apply plugin: 'edu.wpi.first.NativeUtils'
|
||||
apply plugin: ExtraTasks
|
||||
|
||||
apply plugin: 'edu.wpi.first.DeployUtils'
|
||||
|
||||
apply from: '../shared/config.gradle'
|
||||
|
||||
ext {
|
||||
sharedCvConfigs = [crossConnIntegrationTests: []]
|
||||
staticCvConfigs = [:]
|
||||
useJava = false
|
||||
useCpp = true
|
||||
staticGtestConfigs = [crossConnIntegrationTests: []]
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
apply from: "${rootDir}/shared/googletest.gradle"
|
||||
|
||||
deploy {
|
||||
targets {
|
||||
roborio(RemoteTarget) {
|
||||
directory = '/home/admin'
|
||||
maxChannels = 4
|
||||
locations {
|
||||
ssh(SshDeployLocation) {
|
||||
address = "172.22.11.2"
|
||||
user = 'admin'
|
||||
password = ''
|
||||
ipv6 = false
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
all {
|
||||
predeploy << { ctx ->
|
||||
ctx.execute('/usr/local/frc/bin/frcKillRobot.sh -t')
|
||||
}
|
||||
postdeploy << { ctx ->
|
||||
ctx.execute("sync")
|
||||
ctx.execute("ldconfig")
|
||||
}
|
||||
}
|
||||
|
||||
crossConnIntegrationTests(NativeExecutableArtifact) {
|
||||
libraryDirectory = '/usr/local/frc/third-party/lib'
|
||||
postdeploy << { ctx ->
|
||||
ctx.execute('chmod +x crossConnIntegrationTests')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model {
|
||||
components {
|
||||
crossConnIntegrationTests(NativeExecutableSpec) {
|
||||
targetBuildTypes 'debug'
|
||||
nativeUtils.useRequiredLibrary(it, 'googletest_static')
|
||||
binaries.all { binary ->
|
||||
if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
|
||||
if (binary.buildType.name == 'debug') {
|
||||
deploy.targets.roborio.artifacts.crossConnIntegrationTests.binary = binary
|
||||
}
|
||||
|
||||
binary.sources {
|
||||
athenaCpp(CppSourceSet) {
|
||||
source {
|
||||
srcDirs = ['src/main/native/cpp']
|
||||
includes = ['**/*.cpp']
|
||||
}
|
||||
exportedHeaders {
|
||||
srcDirs = ['src/main/native/include']
|
||||
includes = ['**/*.h']
|
||||
}
|
||||
}
|
||||
}
|
||||
project(':hal').addHalDependency(binary, 'shared')
|
||||
project(':hal').addHalJniDependency(binary)
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
|
||||
if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
|
||||
nativeUtils.useRequiredLibrary(binary, 'ni_link_libraries', 'ni_runtime_libraries')
|
||||
}
|
||||
} else {
|
||||
binary.sources {
|
||||
simCpp(CppSourceSet) {
|
||||
source {
|
||||
srcDirs 'src/main/native/dt'
|
||||
includes = ['**/*.cpp']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('deployTests') {
|
||||
try {
|
||||
dependsOn tasks.named('deployCrossConnIntegrationTestsLibrariesRoborio')
|
||||
dependsOn tasks.named('deployCrossConnIntegrationTestsRoborio')
|
||||
} catch (ignored) {
|
||||
}
|
||||
}
|
||||
112
crossConnIntegrationTests/src/main/native/cpp/AnalogTest.cpp
Normal file
112
crossConnIntegrationTests/src/main/native/cpp/AnalogTest.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
// 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 <hal/AnalogInput.h>
|
||||
#include <hal/AnalogOutput.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
class AnalogCrossTest : public ::testing::TestWithParam<std::pair<int, int>> {};
|
||||
|
||||
TEST_P(AnalogCrossTest, AnalogCross) {
|
||||
auto param = GetParam();
|
||||
|
||||
int32_t status = 0;
|
||||
AnalogInputHandle input{param.first, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
AnalogOutputHandle output{param.second, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
for (double i = 0; i < 5; i += 0.1) {
|
||||
HAL_SetAnalogOutput(output, i, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_NEAR(i, HAL_GetAnalogVoltage(input, &status), 0.01);
|
||||
ASSERT_EQ(0, status);
|
||||
}
|
||||
|
||||
for (double i = 5; i > 0; i -= 0.1) {
|
||||
HAL_SetAnalogOutput(output, i, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_NEAR(i, HAL_GetAnalogVoltage(input, &status), 0.01);
|
||||
ASSERT_EQ(0, status);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AnalogInputTest, AllocateAll) {
|
||||
wpi::SmallVector<AnalogInputHandle, 21> analogHandles;
|
||||
for (int i = 0; i < HAL_GetNumAnalogInputs(); i++) {
|
||||
int32_t status = 0;
|
||||
analogHandles.emplace_back(AnalogInputHandle(i, &status));
|
||||
ASSERT_EQ(status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AnalogInputTest, MultipleAllocateFails) {
|
||||
int32_t status = 0;
|
||||
AnalogInputHandle handle(0, &status);
|
||||
ASSERT_NE(handle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
|
||||
AnalogInputHandle handle2(0, &status);
|
||||
ASSERT_EQ(handle2, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
TEST(AnalogInputTest, OverAllocateFails) {
|
||||
int32_t status = 0;
|
||||
AnalogInputHandle handle(HAL_GetNumAnalogInputs(), &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(AnalogInputTest, UnderAllocateFails) {
|
||||
int32_t status = 0;
|
||||
AnalogInputHandle handle(-1, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(AnalogOutputTest, AllocateAll) {
|
||||
wpi::SmallVector<AnalogOutputHandle, 21> analogHandles;
|
||||
for (int i = 0; i < HAL_GetNumAnalogOutputs(); i++) {
|
||||
int32_t status = 0;
|
||||
analogHandles.emplace_back(AnalogOutputHandle(i, &status));
|
||||
ASSERT_EQ(status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(AnalogOutputTest, MultipleAllocateFails) {
|
||||
int32_t status = 0;
|
||||
AnalogOutputHandle handle(0, &status);
|
||||
ASSERT_NE(handle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
|
||||
AnalogOutputHandle handle2(0, &status);
|
||||
ASSERT_EQ(handle2, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
TEST(AnalogOutputTest, OverAllocateFails) {
|
||||
int32_t status = 0;
|
||||
AnalogOutputHandle handle(HAL_GetNumAnalogOutputs(), &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(AnalogOutputTest, UnderAllocateFails) {
|
||||
int32_t status = 0;
|
||||
AnalogOutputHandle handle(-1, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AnalogCrossConnectsTests, AnalogCrossTest,
|
||||
::testing::ValuesIn(AnalogCrossConnects));
|
||||
101
crossConnIntegrationTests/src/main/native/cpp/DIOTest.cpp
Normal file
101
crossConnIntegrationTests/src/main/native/cpp/DIOTest.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// 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 <hal/DIO.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
class DIOTest : public ::testing::TestWithParam<std::pair<int, int>> {};
|
||||
|
||||
TEST_P(DIOTest, DIOCross) {
|
||||
auto param = GetParam();
|
||||
int32_t status = 0;
|
||||
DIOHandle first{param.first, false, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
DIOHandle second{param.second, true, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetDIO(first, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_FALSE(HAL_GetDIO(first, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_FALSE(HAL_GetDIO(second, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetDIO(first, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_TRUE(HAL_GetDIO(second, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetDIODirection(first, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetDIODirection(second, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetDIO(second, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_FALSE(HAL_GetDIO(first, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetDIO(second, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_TRUE(HAL_GetDIO(first, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
}
|
||||
|
||||
TEST(DIOTest, AllocateAll) {
|
||||
wpi::SmallVector<DIOHandle, 32> dioHandles;
|
||||
for (int i = 0; i < HAL_GetNumDigitalChannels(); i++) {
|
||||
int32_t status = 0;
|
||||
dioHandles.emplace_back(i, true, &status);
|
||||
ASSERT_EQ(status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DIOTest, MultipleAllocateFails) {
|
||||
int32_t status = 0;
|
||||
DIOHandle handle(0, true, &status);
|
||||
ASSERT_NE(handle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
|
||||
DIOHandle handle2(0, true, &status);
|
||||
ASSERT_EQ(handle2, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
TEST(DIOTest, OverAllocateFails) {
|
||||
int32_t status = 0;
|
||||
DIOHandle handle(HAL_GetNumDigitalChannels(), true, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(DIOTest, UnderAllocateFails) {
|
||||
int32_t status = 0;
|
||||
DIOHandle handle(-1, true, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(DIOTest, CrossAllocationFails) {
|
||||
int32_t status = 0;
|
||||
PWMHandle pwmHandle(10, &status);
|
||||
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
DIOHandle handle(10, true, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DIOCrossConnectsTests, DIOTest,
|
||||
::testing::ValuesIn(DIOCrossConnects));
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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 <hal/HAL.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
class DutyCycleTest : public ::testing::TestWithParam<std::pair<int, int>> {};
|
||||
|
||||
TEST_P(DutyCycleTest, DutyCycle) {
|
||||
auto param = GetParam();
|
||||
|
||||
int32_t status = 0;
|
||||
PWMHandle pwmHandle(param.first, &status);
|
||||
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
// Ensure our PWM is disabled, and set up properly
|
||||
HAL_SetPWMRaw(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);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetPWMPeriodScale(pwmHandle, 0, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
DIOHandle dioHandle{param.second, true, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
DutyCycleHandle dutyCycle{dioHandle, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetPWMSpeed(pwmHandle, 0.5, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
// Sleep enough time for the frequency to converge
|
||||
usleep(3500000);
|
||||
|
||||
ASSERT_NEAR(1000 / 5.05,
|
||||
(double)HAL_GetDutyCycleFrequency(dutyCycle, &status), 1);
|
||||
|
||||
// TODO measure output
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(DutyCycleCrossConnTests, DutyCycleTest,
|
||||
::testing::ValuesIn(PWMCrossConnects));
|
||||
10
crossConnIntegrationTests/src/main/native/cpp/Main.cpp
Normal file
10
crossConnIntegrationTests/src/main/native/cpp/Main.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// 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 "gtest/gtest.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
358
crossConnIntegrationTests/src/main/native/cpp/PWMTest.cpp
Normal file
358
crossConnIntegrationTests/src/main/native/cpp/PWMTest.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
// 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 <atomic>
|
||||
#include <thread>
|
||||
|
||||
#include <hal/DMA.h>
|
||||
#include <hal/HAL.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpi/condition_variable.h>
|
||||
#include <wpi/priority_mutex.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
class PWMTest : public ::testing::TestWithParam<std::pair<int, int>> {};
|
||||
|
||||
void TestTimingDMA(int squelch, std::pair<int, int> param) {
|
||||
// Initialize DMA
|
||||
int32_t status = 0;
|
||||
DMAHandle dmaHandle(&status);
|
||||
ASSERT_NE(dmaHandle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
status = 0;
|
||||
PWMHandle pwmHandle(param.first, &status);
|
||||
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
|
||||
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_SetPWMPeriodScale(pwmHandle, squelch, &status);
|
||||
|
||||
unsigned int checkPeriod = 0;
|
||||
switch (squelch) {
|
||||
case (0):
|
||||
checkPeriod = 5050;
|
||||
break;
|
||||
case (1):
|
||||
checkPeriod = 10100;
|
||||
break;
|
||||
case (3):
|
||||
checkPeriod = 20200;
|
||||
break;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
DIOHandle dioHandle(param.second, true, &status);
|
||||
ASSERT_NE(dioHandle, HAL_kInvalidHandle);
|
||||
|
||||
HAL_AddDMADigitalSource(dmaHandle, dioHandle, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetDMAExternalTrigger(dmaHandle, dioHandle,
|
||||
HAL_AnalogTriggerType::HAL_Trigger_kInWindow, true,
|
||||
true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
// Loop to test 5 speeds
|
||||
for (unsigned int testWidth = 1000; testWidth < 2100; testWidth += 250) {
|
||||
HAL_StartDMA(dmaHandle, 1024, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
while (true) {
|
||||
int32_t remaining = 0;
|
||||
HAL_DMASample testSample;
|
||||
HAL_ReadDMA(dmaHandle, &testSample, 0.01, &remaining, &status);
|
||||
if (remaining == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_SetPWMSpeed(pwmHandle, (testWidth - 1000) / 1000.0, &status);
|
||||
|
||||
constexpr const int kSampleCount = 15;
|
||||
HAL_DMASample dmaSamples[kSampleCount];
|
||||
int readCount = 0;
|
||||
while (readCount < kSampleCount) {
|
||||
status = 0;
|
||||
int32_t remaining = 0;
|
||||
HAL_DMAReadStatus readStatus = HAL_ReadDMA(
|
||||
dmaHandle, &dmaSamples[readCount], 1.0, &remaining, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_EQ(HAL_DMAReadStatus::HAL_DMA_OK, readStatus);
|
||||
readCount++;
|
||||
}
|
||||
|
||||
HAL_SetPWMSpeed(pwmHandle, 0, &status);
|
||||
HAL_StopDMA(dmaHandle, &status);
|
||||
|
||||
// Find first rising edge
|
||||
int startIndex = 4;
|
||||
while (startIndex < 6) {
|
||||
status = 0;
|
||||
auto value = HAL_GetDMASampleDigitalSource(&dmaSamples[startIndex],
|
||||
dioHandle, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
if (value) {
|
||||
break;
|
||||
}
|
||||
startIndex++;
|
||||
}
|
||||
ASSERT_LT(startIndex, 6);
|
||||
|
||||
// Check that samples alternate
|
||||
bool previous = false;
|
||||
int iterationCount = 0;
|
||||
for (int i = startIndex; i < startIndex + 8; i++) {
|
||||
auto value =
|
||||
HAL_GetDMASampleDigitalSource(&dmaSamples[i], dioHandle, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_NE(previous, value);
|
||||
previous = !previous;
|
||||
iterationCount++;
|
||||
}
|
||||
ASSERT_EQ(iterationCount, 8);
|
||||
iterationCount = 0;
|
||||
|
||||
// Check width between samples
|
||||
for (int i = startIndex; i < startIndex + 8; i += 2) {
|
||||
auto width = HAL_GetDMASampleTime(&dmaSamples[i + 1], &status) -
|
||||
HAL_GetDMASampleTime(&dmaSamples[i], &status);
|
||||
ASSERT_NEAR(testWidth, width, 10);
|
||||
iterationCount++;
|
||||
}
|
||||
ASSERT_EQ(iterationCount, 4);
|
||||
iterationCount = 0;
|
||||
|
||||
// Check period between samples
|
||||
for (int i = startIndex; i < startIndex + 6; i += 2) {
|
||||
auto period = HAL_GetDMASampleTime(&dmaSamples[i + 2], &status) -
|
||||
HAL_GetDMASampleTime(&dmaSamples[i], &status);
|
||||
ASSERT_NEAR(checkPeriod, period, 10);
|
||||
iterationCount++;
|
||||
}
|
||||
ASSERT_EQ(iterationCount, 3);
|
||||
}
|
||||
}
|
||||
|
||||
struct InterruptCheckData {
|
||||
wpi::SmallVector<uint64_t, 8> risingStamps;
|
||||
wpi::SmallVector<uint64_t, 8> fallingStamps;
|
||||
wpi::priority_mutex mutex;
|
||||
wpi::condition_variable cond;
|
||||
HAL_InterruptHandle handle;
|
||||
};
|
||||
|
||||
// TODO switch this to DMA
|
||||
void TestTiming(int squelch, std::pair<int, int> param) {
|
||||
// Initialize interrupt
|
||||
int32_t status = 0;
|
||||
InterruptHandle interruptHandle(&status);
|
||||
// Ensure we have a valid interrupt handle
|
||||
ASSERT_NE(interruptHandle, HAL_kInvalidHandle);
|
||||
|
||||
status = 0;
|
||||
PWMHandle pwmHandle(param.first, &status);
|
||||
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_SetPWMPeriodScale(pwmHandle, squelch, &status);
|
||||
|
||||
unsigned int checkPeriod = 0;
|
||||
switch (squelch) {
|
||||
case (0):
|
||||
checkPeriod = 5050;
|
||||
break;
|
||||
case (1):
|
||||
checkPeriod = 10100;
|
||||
break;
|
||||
case (3):
|
||||
checkPeriod = 20200;
|
||||
break;
|
||||
}
|
||||
|
||||
status = 0;
|
||||
DIOHandle dioHandle(param.second, true, &status);
|
||||
ASSERT_NE(dioHandle, HAL_kInvalidHandle);
|
||||
|
||||
InterruptCheckData interruptData;
|
||||
interruptData.handle = interruptHandle;
|
||||
|
||||
// Can use any type for the interrupt handle
|
||||
HAL_RequestInterrupts(interruptHandle, dioHandle,
|
||||
HAL_AnalogTriggerType::HAL_Trigger_kInWindow, &status);
|
||||
|
||||
HAL_SetInterruptUpSourceEdge(interruptHandle, true, true, &status);
|
||||
|
||||
// Loop to test 5 speeds
|
||||
for (unsigned int i = 1000; i < 2100; i += 250) {
|
||||
interruptData.risingStamps.clear();
|
||||
interruptData.fallingStamps.clear();
|
||||
|
||||
std::atomic_bool runThread{true};
|
||||
|
||||
status = 0;
|
||||
std::thread interruptThread([&]() {
|
||||
while (runThread) {
|
||||
int32_t threadStatus = 0;
|
||||
auto mask =
|
||||
HAL_WaitForInterrupt(interruptHandle, 5, true, &threadStatus);
|
||||
|
||||
if ((mask & 0x100) == 0x100 && interruptData.risingStamps.size() == 0 &&
|
||||
interruptData.fallingStamps.size() == 0) {
|
||||
// Falling edge at start of tracking. Skip
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t status = 0;
|
||||
if ((mask & 0x1) == 0x1) {
|
||||
auto ts = HAL_ReadInterruptRisingTimestamp(interruptHandle, &status);
|
||||
// Rising Edge
|
||||
interruptData.risingStamps.push_back(ts);
|
||||
} else if ((mask & 0x100) == 0x100) {
|
||||
auto ts = HAL_ReadInterruptFallingTimestamp(interruptHandle, &status);
|
||||
// Falling Edge
|
||||
interruptData.fallingStamps.push_back(ts);
|
||||
}
|
||||
|
||||
if (interruptData.risingStamps.size() >= 4 &&
|
||||
interruptData.fallingStamps.size() >= 4) {
|
||||
interruptData.cond.notify_all();
|
||||
runThread = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure our interrupt actually got created correctly.
|
||||
ASSERT_EQ(status, 0);
|
||||
HAL_SetPWMSpeed(pwmHandle, (i - 1000) / 1000.0, &status);
|
||||
ASSERT_EQ(status, 0);
|
||||
{
|
||||
std::unique_lock<wpi::priority_mutex> lock(interruptData.mutex);
|
||||
// Wait for lock
|
||||
// TODO: Add Timeout
|
||||
auto timeout = interruptData.cond.wait_for(lock, std::chrono::seconds(2));
|
||||
if (timeout == std::cv_status::timeout) {
|
||||
runThread = false;
|
||||
if (interruptThread.joinable()) {
|
||||
interruptThread.join();
|
||||
}
|
||||
ASSERT_TRUE(false); // Exit test as failure on timeout
|
||||
}
|
||||
}
|
||||
|
||||
HAL_SetPWMRaw(pwmHandle, 0, &status);
|
||||
|
||||
// Ensure our interrupts have the proper counts
|
||||
ASSERT_EQ(interruptData.risingStamps.size(),
|
||||
interruptData.fallingStamps.size());
|
||||
|
||||
ASSERT_GT(interruptData.risingStamps.size(), 0u);
|
||||
|
||||
ASSERT_EQ(interruptData.risingStamps.size() % 2, 0u);
|
||||
ASSERT_EQ(interruptData.fallingStamps.size() % 2, 0u);
|
||||
|
||||
for (size_t j = 0; j < interruptData.risingStamps.size(); j++) {
|
||||
uint64_t width =
|
||||
interruptData.fallingStamps[j] - interruptData.risingStamps[j];
|
||||
ASSERT_NEAR(width, i, 10);
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < interruptData.risingStamps.size() - 1; j++) {
|
||||
uint64_t period =
|
||||
interruptData.risingStamps[j + 1] - interruptData.risingStamps[j];
|
||||
ASSERT_NEAR(period, checkPeriod, 10);
|
||||
}
|
||||
runThread = false;
|
||||
if (interruptThread.joinable()) {
|
||||
interruptThread.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(PWMTest, Timing4x) {
|
||||
auto param = GetParam();
|
||||
TestTiming(3, param);
|
||||
}
|
||||
|
||||
TEST_P(PWMTest, Timing2x) {
|
||||
auto param = GetParam();
|
||||
TestTiming(1, param);
|
||||
}
|
||||
|
||||
TEST_P(PWMTest, Timing1x) {
|
||||
auto param = GetParam();
|
||||
TestTiming(0, param);
|
||||
}
|
||||
|
||||
TEST_P(PWMTest, TimingDMA4x) {
|
||||
auto param = GetParam();
|
||||
TestTimingDMA(3, param);
|
||||
}
|
||||
|
||||
TEST_P(PWMTest, TimingDMA2x) {
|
||||
auto param = GetParam();
|
||||
TestTimingDMA(1, param);
|
||||
}
|
||||
|
||||
TEST_P(PWMTest, TimingDMA1x) {
|
||||
auto param = GetParam();
|
||||
TestTimingDMA(0, param);
|
||||
}
|
||||
|
||||
TEST(PWMTest, AllocateAll) {
|
||||
wpi::SmallVector<PWMHandle, 21> pwmHandles;
|
||||
for (int i = 0; i < HAL_GetNumPWMChannels(); i++) {
|
||||
int32_t status = 0;
|
||||
pwmHandles.emplace_back(PWMHandle(i, &status));
|
||||
ASSERT_EQ(status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PWMTest, MultipleAllocateFails) {
|
||||
int32_t status = 0;
|
||||
PWMHandle handle(0, &status);
|
||||
ASSERT_NE(handle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
|
||||
PWMHandle handle2(0, &status);
|
||||
ASSERT_EQ(handle2, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
TEST(PWMTest, OverAllocateFails) {
|
||||
int32_t status = 0;
|
||||
PWMHandle handle(HAL_GetNumPWMChannels(), &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(PWMTest, UnderAllocateFails) {
|
||||
int32_t status = 0;
|
||||
PWMHandle handle(-1, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(PWMTest, CrossAllocationFails) {
|
||||
int32_t status = 0;
|
||||
DIOHandle dioHandle(10, true, &status);
|
||||
ASSERT_NE(dioHandle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
PWMHandle handle(10, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(PWMCrossConnectTests, PWMTest,
|
||||
::testing::ValuesIn(PWMCrossConnects));
|
||||
@@ -0,0 +1,50 @@
|
||||
// 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 <hal/AnalogInput.h>
|
||||
#include <hal/Relay.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
class RelayAnalogTest : public ::testing::TestWithParam<std::pair<int, int>> {};
|
||||
|
||||
TEST_P(RelayAnalogTest, RelayAnalogCross) {
|
||||
auto param = GetParam();
|
||||
|
||||
int32_t status = 0;
|
||||
RelayHandle relay{param.first, true, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
AnalogInputHandle analog{param.second, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
AnalogTriggerHandle trigger{analog, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetAnalogTriggerLimitsVoltage(trigger, 1.5, 3.0, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(relay, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_FALSE(HAL_GetAnalogTriggerTriggerState(trigger, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(relay, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_TRUE(HAL_GetAnalogTriggerTriggerState(trigger, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(relay, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_FALSE(HAL_GetAnalogTriggerTriggerState(trigger, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(RelayAnalogCrossConnectsTests, RelayAnalogTest,
|
||||
::testing::ValuesIn(RelayAnalogCrossConnects));
|
||||
@@ -0,0 +1,104 @@
|
||||
// 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 <hal/Relay.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
|
||||
#include "CrossConnects.h"
|
||||
#include "LifetimeWrappers.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace hlt;
|
||||
|
||||
class RelayDigitalTest : public ::testing::TestWithParam<RelayCross> {};
|
||||
|
||||
TEST_P(RelayDigitalTest, RelayCross) {
|
||||
auto param = GetParam();
|
||||
int32_t status = 0;
|
||||
RelayHandle fwd{param.Relay, true, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
RelayHandle rev{param.Relay, false, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
DIOHandle fwdInput{param.FwdDio, true, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
DIOHandle revInput{param.RevDio, true, &status};
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(fwd, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetRelay(rev, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_FALSE(HAL_GetDIO(fwdInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_FALSE(HAL_GetDIO(revInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(fwd, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetRelay(rev, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_FALSE(HAL_GetDIO(fwdInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_TRUE(HAL_GetDIO(revInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(fwd, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetRelay(rev, false, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_TRUE(HAL_GetDIO(fwdInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_FALSE(HAL_GetDIO(revInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
|
||||
HAL_SetRelay(fwd, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
HAL_SetRelay(rev, true, &status);
|
||||
ASSERT_EQ(0, status);
|
||||
usleep(1000);
|
||||
ASSERT_TRUE(HAL_GetDIO(fwdInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
ASSERT_TRUE(HAL_GetDIO(revInput, &status));
|
||||
ASSERT_EQ(0, status);
|
||||
}
|
||||
|
||||
TEST(RelayDigitalTest, AllocateAll) {
|
||||
wpi::SmallVector<RelayHandle, 32> relayHandles;
|
||||
for (int i = 0; i < HAL_GetNumRelayChannels(); i++) {
|
||||
int32_t status = 0;
|
||||
relayHandles.emplace_back(i / 2, i % 2, &status);
|
||||
ASSERT_EQ(status, 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RelayDigitalTest, MultipleAllocateFails) {
|
||||
int32_t status = 0;
|
||||
RelayHandle handle(0, true, &status);
|
||||
ASSERT_NE(handle, HAL_kInvalidHandle);
|
||||
ASSERT_EQ(status, 0);
|
||||
|
||||
RelayHandle handle2(0, true, &status);
|
||||
ASSERT_EQ(handle2, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
|
||||
}
|
||||
|
||||
TEST(RelayDigitalTest, OverAllocateFails) {
|
||||
int32_t status = 0;
|
||||
RelayHandle handle(HAL_GetNumRelayChannels(), true, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
TEST(RelayDigitalTest, UnderAllocateFails) {
|
||||
int32_t status = 0;
|
||||
RelayHandle handle(-1, true, &status);
|
||||
ASSERT_EQ(handle, HAL_kInvalidHandle);
|
||||
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(RelayDigitalCrossConnectsTests, RelayDigitalTest,
|
||||
::testing::ValuesIn(RelayCrossConnects));
|
||||
@@ -0,0 +1,71 @@
|
||||
// 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 <cstdlib>
|
||||
#include <thread>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <hal/HAL.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mockds/MockDS.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
class TestEnvironment : public testing::Environment {
|
||||
bool m_alreadySetUp = false;
|
||||
MockDS m_mockDS;
|
||||
|
||||
public:
|
||||
TestEnvironment() {
|
||||
// Only set up once. This allows gtest_repeat to be used to automatically
|
||||
// repeat tests.
|
||||
if (m_alreadySetUp) {
|
||||
return;
|
||||
}
|
||||
m_alreadySetUp = true;
|
||||
|
||||
if (!HAL_Initialize(500, 0)) {
|
||||
fmt::print(stderr, "FATAL ERROR: HAL could not be initialized\n");
|
||||
std::exit(-1);
|
||||
}
|
||||
|
||||
m_mockDS.Start();
|
||||
|
||||
// This sets up the network communications library to enable the driver
|
||||
// station. After starting network coms, it will loop until the driver
|
||||
// station returns that the robot is enabled, to ensure that tests will be
|
||||
// able to run on the hardware.
|
||||
HAL_ObserveUserProgramStarting();
|
||||
|
||||
fmt::print("Started coms\n");
|
||||
|
||||
int enableCounter = 0;
|
||||
|
||||
auto checkEnabled = []() {
|
||||
HAL_ControlWord controlWord;
|
||||
std::memset(&controlWord, 0, sizeof(controlWord));
|
||||
HAL_GetControlWord(&controlWord);
|
||||
return controlWord.enabled && controlWord.dsAttached;
|
||||
};
|
||||
while (!checkEnabled()) {
|
||||
if (enableCounter > 50) {
|
||||
// Robot did not enable properly after 5 seconds.
|
||||
// Force exit
|
||||
fmt::print(stderr, " Failed to enable. Aborting\n");
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(100ms);
|
||||
|
||||
fmt::print("Waiting for enable: {}\n", enableCounter++);
|
||||
}
|
||||
std::this_thread::sleep_for(500ms);
|
||||
}
|
||||
|
||||
~TestEnvironment() override { m_mockDS.Stop(); }
|
||||
};
|
||||
|
||||
testing::Environment* const environment =
|
||||
testing::AddGlobalTestEnvironment(new TestEnvironment);
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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 "MockDS.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <hal/cpp/fpga_clock.h>
|
||||
#include <wpi/Logger.h>
|
||||
#include <wpi/SmallVector.h>
|
||||
#include <wpinet/UDPClient.h>
|
||||
|
||||
static void LoggerFunc(unsigned int level, const char* file, unsigned int line,
|
||||
const char* msg) {
|
||||
if (level == 20) {
|
||||
fmt::print(stderr, "DS: {}\n", msg);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string_view levelmsg;
|
||||
if (level >= 50) {
|
||||
levelmsg = "CRITICAL";
|
||||
} else if (level >= 40) {
|
||||
levelmsg = "ERROR";
|
||||
} else if (level >= 30) {
|
||||
levelmsg = "WARNING";
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
fmt::print(stderr, "DS: {}: {} ({}:{})\n", levelmsg, msg, file, line);
|
||||
}
|
||||
|
||||
static void generateEnabledDsPacket(wpi::SmallVectorImpl<uint8_t>& data,
|
||||
uint16_t sendCount) {
|
||||
data.clear();
|
||||
data.push_back(sendCount >> 8);
|
||||
data.push_back(sendCount);
|
||||
data.push_back(0x01); // general data tag
|
||||
data.push_back(0x04); // teleop enabled
|
||||
data.push_back(0x10); // normal data request
|
||||
data.push_back(0x00); // red 1 station
|
||||
}
|
||||
|
||||
void MockDS::Start() {
|
||||
if (m_active) {
|
||||
return;
|
||||
}
|
||||
m_active = true;
|
||||
m_thread = std::thread([&]() {
|
||||
wpi::Logger logger(LoggerFunc);
|
||||
wpi::UDPClient client(logger);
|
||||
client.start();
|
||||
auto timeout_time = hal::fpga_clock::now();
|
||||
int initCount = 0;
|
||||
uint16_t sendCount = 0;
|
||||
wpi::SmallVector<uint8_t, 8> data;
|
||||
while (m_active) {
|
||||
// Keep 20ms intervals, and increase time to next interval
|
||||
auto current = hal::fpga_clock::now();
|
||||
while (timeout_time <= current) {
|
||||
timeout_time += std::chrono::milliseconds(20);
|
||||
}
|
||||
std::this_thread::sleep_until(timeout_time);
|
||||
generateEnabledDsPacket(data, sendCount++);
|
||||
// ~10 disabled packets are required to make the robot actually enable
|
||||
// 1 is definitely not enough.
|
||||
if (initCount < 10) {
|
||||
initCount++;
|
||||
data[3] = 0;
|
||||
}
|
||||
client.send(data, "127.0.0.1", 1110);
|
||||
}
|
||||
client.shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
void MockDS::Stop() {
|
||||
m_active = false;
|
||||
if (m_thread.joinable()) {
|
||||
m_thread.join();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
class MockDS {
|
||||
public:
|
||||
MockDS() = default;
|
||||
~MockDS() { Stop(); }
|
||||
MockDS(const MockDS& other) = delete;
|
||||
MockDS& operator=(const MockDS& other) = delete;
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
std::thread m_thread;
|
||||
std::atomic_bool m_active{false};
|
||||
};
|
||||
5
crossConnIntegrationTests/src/main/native/dt/Main.cpp
Normal file
5
crossConnIntegrationTests/src/main/native/dt/Main.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// 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.
|
||||
|
||||
int main() {}
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
namespace hlt {
|
||||
|
||||
constexpr static std::array<std::pair<int, int>, 22> DIOCrossConnects{
|
||||
std::pair{20, 25},
|
||||
std::pair{19, 24},
|
||||
std::pair{17, 13},
|
||||
std::pair{16, 12},
|
||||
std::pair{15, 11},
|
||||
std::pair{14, 10},
|
||||
std::pair{26, 2},
|
||||
std::pair{27, 1},
|
||||
std::pair{28, 0},
|
||||
std::pair{29, 3},
|
||||
std::pair{30, 4},
|
||||
|
||||
// Opposite direction
|
||||
std::pair{25, 20},
|
||||
std::pair{24, 19},
|
||||
std::pair{13, 17},
|
||||
std::pair{12, 16},
|
||||
std::pair{11, 15},
|
||||
std::pair{10, 14},
|
||||
std::pair{2, 26},
|
||||
std::pair{1, 27},
|
||||
std::pair{0, 28},
|
||||
std::pair{3, 29},
|
||||
std::pair{4, 30},
|
||||
};
|
||||
|
||||
// PWM on left, DIO on right
|
||||
constexpr static std::array<std::pair<int, int>, 2> PWMCrossConnects{
|
||||
std::pair{0, 18},
|
||||
std::pair{16, 25},
|
||||
};
|
||||
|
||||
// FWD only, relay on left
|
||||
constexpr static std::array<std::pair<int, int>, 2> RelayAnalogCrossConnects{
|
||||
std::pair{2, 0}, std::pair{3, 1}};
|
||||
|
||||
struct RelayCross {
|
||||
int Relay;
|
||||
int FwdDio;
|
||||
int RevDio;
|
||||
};
|
||||
|
||||
constexpr static std::array<RelayCross, 1> RelayCrossConnects{
|
||||
RelayCross{0, 23, 22}};
|
||||
|
||||
// input on left
|
||||
constexpr static std::array<std::pair<int, int>, 2> AnalogCrossConnects{
|
||||
std::pair{2, 0}, std::pair{4, 1}};
|
||||
|
||||
} // namespace hlt
|
||||
@@ -0,0 +1,201 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <hal/DMA.h>
|
||||
#include <hal/DutyCycle.h>
|
||||
#include <hal/HAL.h>
|
||||
|
||||
namespace hlt {
|
||||
|
||||
struct InterruptHandle {
|
||||
public:
|
||||
explicit InterruptHandle(int32_t* status) {
|
||||
handle = HAL_InitializeInterrupts(status);
|
||||
}
|
||||
InterruptHandle(const InterruptHandle&) = delete;
|
||||
InterruptHandle operator=(const InterruptHandle&) = delete;
|
||||
|
||||
InterruptHandle(InterruptHandle&&) = default;
|
||||
InterruptHandle& operator=(InterruptHandle&&) = default;
|
||||
|
||||
~InterruptHandle() { HAL_CleanInterrupts(handle); }
|
||||
|
||||
operator HAL_InterruptHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_InterruptHandle handle = 0;
|
||||
};
|
||||
|
||||
struct DMAHandle {
|
||||
public:
|
||||
explicit DMAHandle(int32_t* status) { handle = HAL_InitializeDMA(status); }
|
||||
DMAHandle(const DMAHandle&) = delete;
|
||||
DMAHandle operator=(const DMAHandle&) = delete;
|
||||
|
||||
DMAHandle(DMAHandle&&) = default;
|
||||
DMAHandle& operator=(DMAHandle&&) = default;
|
||||
|
||||
~DMAHandle() { HAL_FreeDMA(handle); }
|
||||
|
||||
operator HAL_DMAHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_DMAHandle handle = 0;
|
||||
};
|
||||
|
||||
struct AnalogInputHandle {
|
||||
public:
|
||||
AnalogInputHandle(int32_t port, int32_t* status) {
|
||||
handle = HAL_InitializeAnalogInputPort(HAL_GetPort(port), nullptr, status);
|
||||
}
|
||||
AnalogInputHandle(const AnalogInputHandle&) = delete;
|
||||
AnalogInputHandle operator=(const AnalogInputHandle&) = delete;
|
||||
|
||||
AnalogInputHandle(AnalogInputHandle&&) = default;
|
||||
AnalogInputHandle& operator=(AnalogInputHandle&&) = default;
|
||||
|
||||
~AnalogInputHandle() { HAL_FreeAnalogInputPort(handle); }
|
||||
|
||||
operator HAL_AnalogInputHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_AnalogInputHandle handle = 0;
|
||||
};
|
||||
|
||||
struct AnalogOutputHandle {
|
||||
public:
|
||||
AnalogOutputHandle(int32_t port, int32_t* status) {
|
||||
handle = HAL_InitializeAnalogOutputPort(HAL_GetPort(port), nullptr, status);
|
||||
}
|
||||
AnalogOutputHandle(const AnalogOutputHandle&) = delete;
|
||||
AnalogOutputHandle operator=(const AnalogOutputHandle&) = delete;
|
||||
|
||||
AnalogOutputHandle(AnalogOutputHandle&&) = default;
|
||||
AnalogOutputHandle& operator=(AnalogOutputHandle&&) = default;
|
||||
|
||||
~AnalogOutputHandle() { HAL_FreeAnalogOutputPort(handle); }
|
||||
|
||||
operator HAL_AnalogOutputHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_AnalogOutputHandle handle = 0;
|
||||
};
|
||||
|
||||
struct AnalogTriggerHandle {
|
||||
public:
|
||||
explicit AnalogTriggerHandle(HAL_AnalogInputHandle port, int32_t* status) {
|
||||
handle = HAL_InitializeAnalogTrigger(port, status);
|
||||
}
|
||||
AnalogTriggerHandle(const AnalogTriggerHandle&) = delete;
|
||||
AnalogTriggerHandle operator=(const AnalogTriggerHandle&) = delete;
|
||||
|
||||
AnalogTriggerHandle(AnalogTriggerHandle&&) = default;
|
||||
AnalogTriggerHandle& operator=(AnalogTriggerHandle&&) = default;
|
||||
|
||||
~AnalogTriggerHandle() {
|
||||
int32_t status = 0;
|
||||
HAL_CleanAnalogTrigger(handle, &status);
|
||||
}
|
||||
|
||||
operator HAL_AnalogTriggerHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_AnalogTriggerHandle handle = 0;
|
||||
};
|
||||
|
||||
struct DutyCycleHandle {
|
||||
public:
|
||||
DutyCycleHandle(HAL_DigitalHandle port, int32_t* status) {
|
||||
handle = HAL_InitializeDutyCycle(
|
||||
port, HAL_AnalogTriggerType::HAL_Trigger_kInWindow, status);
|
||||
}
|
||||
DutyCycleHandle(const DutyCycleHandle&) = delete;
|
||||
DutyCycleHandle operator=(const DutyCycleHandle&) = delete;
|
||||
|
||||
DutyCycleHandle(DutyCycleHandle&&) = default;
|
||||
DutyCycleHandle& operator=(DutyCycleHandle&&) = default;
|
||||
|
||||
~DutyCycleHandle() { HAL_FreeDutyCycle(handle); }
|
||||
|
||||
operator HAL_DutyCycleHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_DutyCycleHandle handle = 0;
|
||||
};
|
||||
|
||||
struct DIOHandle {
|
||||
public:
|
||||
DIOHandle() {}
|
||||
DIOHandle(const DIOHandle&) = delete;
|
||||
DIOHandle operator=(const DIOHandle&) = delete;
|
||||
|
||||
DIOHandle(DIOHandle&&) = default;
|
||||
DIOHandle& operator=(DIOHandle&&) = default;
|
||||
|
||||
DIOHandle(int32_t port, HAL_Bool input, int32_t* status) {
|
||||
handle = HAL_InitializeDIOPort(HAL_GetPort(port), input, nullptr, status);
|
||||
}
|
||||
|
||||
~DIOHandle() { HAL_FreeDIOPort(handle); }
|
||||
|
||||
operator HAL_DigitalHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_DigitalHandle handle = 0;
|
||||
};
|
||||
|
||||
struct PWMHandle {
|
||||
public:
|
||||
PWMHandle() {}
|
||||
PWMHandle(const PWMHandle&) = delete;
|
||||
PWMHandle operator=(const PWMHandle&) = delete;
|
||||
|
||||
PWMHandle(PWMHandle&&) = default;
|
||||
PWMHandle& operator=(PWMHandle&&) = default;
|
||||
|
||||
PWMHandle(int32_t port, int32_t* status) {
|
||||
handle = HAL_InitializePWMPort(HAL_GetPort(port), nullptr, status);
|
||||
}
|
||||
|
||||
~PWMHandle() {
|
||||
int32_t status = 0;
|
||||
HAL_FreePWMPort(handle, &status);
|
||||
}
|
||||
|
||||
operator HAL_DigitalHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_DigitalHandle handle = 0;
|
||||
};
|
||||
|
||||
struct RelayHandle {
|
||||
public:
|
||||
RelayHandle(int32_t port, HAL_Bool fwd, int32_t* status) {
|
||||
handle = HAL_InitializeRelayPort(HAL_GetPort(port), fwd, nullptr, status);
|
||||
}
|
||||
RelayHandle(const RelayHandle&) = delete;
|
||||
RelayHandle operator=(const RelayHandle&) = delete;
|
||||
|
||||
RelayHandle(RelayHandle&&) = default;
|
||||
RelayHandle& operator=(RelayHandle&&) = default;
|
||||
|
||||
~RelayHandle() { HAL_FreeRelayPort(handle); }
|
||||
|
||||
operator HAL_RelayHandle() const { return handle; }
|
||||
|
||||
private:
|
||||
HAL_RelayHandle handle = 0;
|
||||
};
|
||||
|
||||
#define ASSERT_LAST_ERROR_STATUS(status, x) \
|
||||
do { \
|
||||
ASSERT_EQ(status, HAL_USE_LAST_ERROR); \
|
||||
const char* lastErrorMessageInMacro = HAL_GetLastError(&status); \
|
||||
static_cast<void>(lastErrorMessageInMacro); \
|
||||
ASSERT_EQ(status, x); \
|
||||
} while (0)
|
||||
|
||||
} // namespace hlt
|
||||
@@ -31,8 +31,10 @@ repoRootNameOverride {
|
||||
}
|
||||
|
||||
includeOtherLibs {
|
||||
^fmt/
|
||||
^opencv2/
|
||||
^support/
|
||||
^tcpsockets/
|
||||
^wpi/
|
||||
^wpinet/
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ target_include_directories(cscore PUBLIC
|
||||
$<INSTALL_INTERFACE:${include_dest}/cscore>)
|
||||
target_include_directories(cscore PRIVATE src/main/native/cpp)
|
||||
wpilib_target_warnings(cscore)
|
||||
target_link_libraries(cscore PUBLIC wpiutil ${OpenCV_LIBS})
|
||||
target_link_libraries(cscore PUBLIC wpinet wpiutil ${OpenCV_LIBS})
|
||||
|
||||
set_property(TARGET cscore PROPERTY FOLDER "libraries")
|
||||
|
||||
@@ -46,8 +46,8 @@ else()
|
||||
set (cscore_config_dir share/cscore)
|
||||
endif()
|
||||
|
||||
configure_file(cscore-config.cmake.in ${CMAKE_BINARY_DIR}/cscore-config.cmake )
|
||||
install(FILES ${CMAKE_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
|
||||
configure_file(cscore-config.cmake.in ${WPILIB_BINARY_DIR}/cscore-config.cmake )
|
||||
install(FILES ${WPILIB_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
|
||||
install(EXPORT cscore DESTINATION ${cscore_config_dir})
|
||||
|
||||
SUBDIR_LIST(cscore_examples "${CMAKE_CURRENT_SOURCE_DIR}/examples")
|
||||
@@ -79,7 +79,7 @@ if (WITH_JAVA)
|
||||
find_package(Java REQUIRED)
|
||||
find_package(JNI REQUIRED)
|
||||
include(UseJava)
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
|
||||
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
|
||||
|
||||
#find java files, copy them locally
|
||||
|
||||
@@ -87,11 +87,11 @@ if (WITH_JAVA)
|
||||
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
|
||||
endif()
|
||||
|
||||
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 NO_DEFAULT_PATH)
|
||||
find_file(OPENCV_JNI_FILE NAMES libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
|
||||
libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dylib
|
||||
opencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib NO_DEFAULT_PATH)
|
||||
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib ${OpenCV_INSTALL_PATH}/lib/jni NO_DEFAULT_PATH)
|
||||
|
||||
file(GLOB
|
||||
cscore_jni_src src/main/native/cpp/jni/CameraServerJNI.cpp)
|
||||
|
||||
@@ -23,8 +23,8 @@ model {
|
||||
enableCheckTask true
|
||||
javaCompileTasks << compileJava
|
||||
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.roborio)
|
||||
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.raspbian)
|
||||
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.aarch64bionic)
|
||||
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm32)
|
||||
jniCrossCompileOptions << JniCrossCompileOptions(nativeUtils.wpi.platforms.linuxarm64)
|
||||
|
||||
sources {
|
||||
cpp {
|
||||
@@ -45,6 +45,7 @@ model {
|
||||
return
|
||||
}
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
|
||||
|
||||
if (it.targetPlatform.operatingSystem.linux) {
|
||||
it.linker.args '-Wl,--version-script=' + file('src/main/native/LinuxSymbolScript.txt')
|
||||
@@ -55,17 +56,26 @@ model {
|
||||
}
|
||||
}
|
||||
}
|
||||
binaries {
|
||||
all {
|
||||
if (!it.buildable || !(it instanceof NativeBinarySpec)) {
|
||||
return
|
||||
}
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ext {
|
||||
sharedCvConfigs = [cscore : [],
|
||||
cscoreBase: [],
|
||||
cscoreDev : [],
|
||||
cscoreTest: [],
|
||||
cscoreJNIShared: []]
|
||||
cscoreBase: [],
|
||||
cscoreDev : [],
|
||||
cscoreTest: [],
|
||||
cscoreJNIShared: []]
|
||||
staticCvConfigs = [cscoreJNI: [],
|
||||
cscoreJNICvStatic: []]
|
||||
cscoreJNICvStatic: []]
|
||||
useJava = true
|
||||
useCpp = true
|
||||
cvStaticBuild = true
|
||||
@@ -127,43 +137,42 @@ def examplesMap = [:];
|
||||
|
||||
File examplesTree = file("$projectDir/examples")
|
||||
examplesTree.list(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File current, String name) {
|
||||
return new File(current, name).isDirectory();
|
||||
}
|
||||
}).each {
|
||||
sharedCvConfigs.put(it, [])
|
||||
examplesMap.put(it, [])
|
||||
}
|
||||
@Override
|
||||
public boolean accept(File current, String name) {
|
||||
return new File(current, name).isDirectory();
|
||||
}
|
||||
}).each {
|
||||
sharedCvConfigs.put(it, [])
|
||||
examplesMap.put(it, [])
|
||||
}
|
||||
|
||||
apply from: "${rootDir}/shared/opencv.gradle"
|
||||
|
||||
Action<List<String>> symbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
} as Action<List<String>>;
|
||||
|
||||
nativeUtils.exportsConfigs {
|
||||
cscore {
|
||||
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
|
||||
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
|
||||
x64ExcludeSymbols = [
|
||||
'_CT??_R0?AV_System_error',
|
||||
'_CT??_R0?AVexception',
|
||||
'_CT??_R0?AVfailure',
|
||||
'_CT??_R0?AVruntime_error',
|
||||
'_CT??_R0?AVsystem_error',
|
||||
'_CTA5?AVfailure',
|
||||
'_TI5?AVfailure',
|
||||
'_CT??_R0?AVout_of_range',
|
||||
'_CTA3?AVout_of_range',
|
||||
'_TI3?AVout_of_range',
|
||||
'_CT??_R0?AVbad_cast'
|
||||
]
|
||||
}
|
||||
cscoreJNI {
|
||||
x86SymbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
}
|
||||
x64SymbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
}
|
||||
x64SymbolFilter = symbolFilter
|
||||
}
|
||||
cscoreJNICvStatic {
|
||||
x86SymbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
}
|
||||
x64SymbolFilter = { symbols ->
|
||||
symbols.removeIf({ !it.startsWith('CS_') })
|
||||
}
|
||||
x64SymbolFilter = symbolFilter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,15 +180,16 @@ model {
|
||||
components {
|
||||
examplesMap.each { key, value ->
|
||||
if (key == "usbviewer") {
|
||||
if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
|
||||
if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxarm32') && !project.hasProperty('onlylinuxarm64')) {
|
||||
"${key}"(NativeExecutableSpec) {
|
||||
targetBuildTypes 'debug'
|
||||
binaries.all {
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
|
||||
lib project: ':wpigui', library: 'wpigui', linkage: 'static'
|
||||
lib library: 'cscore', linkage: 'shared'
|
||||
nativeUtils.useRequiredLibrary(it, 'imgui_static')
|
||||
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) {
|
||||
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm32 || it.targetPlatform.name == nativeUtils.wpi.platforms.linuxarm64) {
|
||||
it.buildable = false
|
||||
return
|
||||
}
|
||||
@@ -206,6 +216,7 @@ model {
|
||||
targetBuildTypes 'debug'
|
||||
binaries.all {
|
||||
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
|
||||
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
|
||||
lib library: 'cscore', linkage: 'shared'
|
||||
}
|
||||
sources {
|
||||
|
||||
@@ -1,84 +1,78 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <wpi/SmallString.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main() {
|
||||
CS_Status status = 0;
|
||||
wpi::SmallString<64> buf;
|
||||
|
||||
for (const auto& caminfo : cs::EnumerateUsbCameras(&status)) {
|
||||
wpi::outs() << caminfo.dev << ": " << caminfo.path << " (" << caminfo.name
|
||||
<< ")\n";
|
||||
fmt::print("{}: {} ({})\n", caminfo.dev, caminfo.path, caminfo.name);
|
||||
if (!caminfo.otherPaths.empty()) {
|
||||
wpi::outs() << "Other device paths:\n";
|
||||
for (auto&& path : caminfo.otherPaths)
|
||||
wpi::outs() << " " << path << '\n';
|
||||
std::puts("Other device paths:");
|
||||
for (auto&& path : caminfo.otherPaths) {
|
||||
fmt::print(" {}\n", path);
|
||||
}
|
||||
}
|
||||
|
||||
cs::UsbCamera camera{"usbcam", caminfo.dev};
|
||||
|
||||
wpi::outs() << "Properties:\n";
|
||||
std::puts("Properties:");
|
||||
for (const auto& prop : camera.EnumerateProperties()) {
|
||||
wpi::outs() << " " << prop.GetName();
|
||||
fmt::print(" {}", prop.GetName());
|
||||
switch (prop.GetKind()) {
|
||||
case cs::VideoProperty::kBoolean:
|
||||
wpi::outs() << " (bool): "
|
||||
<< "value=" << prop.Get()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (bool): value={} default={}", prop.Get(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kInteger:
|
||||
wpi::outs() << " (int): "
|
||||
<< "value=" << prop.Get() << " min=" << prop.GetMin()
|
||||
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (int): value={} min={} max={} step={} default={}",
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kString:
|
||||
wpi::outs() << " (string): " << prop.GetString(buf);
|
||||
fmt::print(" (string): {}", prop.GetString());
|
||||
break;
|
||||
case cs::VideoProperty::kEnum: {
|
||||
wpi::outs() << " (enum): "
|
||||
<< "value=" << prop.Get();
|
||||
fmt::print(" (enum): value={}", prop.Get());
|
||||
auto choices = prop.GetChoices();
|
||||
for (size_t i = 0; i < choices.size(); ++i) {
|
||||
if (choices[i].empty()) continue;
|
||||
wpi::outs() << "\n " << i << ": " << choices[i];
|
||||
if (!choices[i].empty()) {
|
||||
fmt::print("\n {}: {}", i, choices[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wpi::outs() << '\n';
|
||||
std::fputc('\n', stdout);
|
||||
}
|
||||
|
||||
wpi::outs() << "Video Modes:\n";
|
||||
std::puts("Video Modes:");
|
||||
for (const auto& mode : camera.EnumerateVideoModes()) {
|
||||
wpi::outs() << " PixelFormat:";
|
||||
const char* pixelFormat;
|
||||
switch (mode.pixelFormat) {
|
||||
case cs::VideoMode::kMJPEG:
|
||||
wpi::outs() << "MJPEG";
|
||||
pixelFormat = "MJPEG";
|
||||
break;
|
||||
case cs::VideoMode::kYUYV:
|
||||
wpi::outs() << "YUYV";
|
||||
pixelFormat = "YUYV";
|
||||
break;
|
||||
case cs::VideoMode::kRGB565:
|
||||
wpi::outs() << "RGB565";
|
||||
pixelFormat = "RGB565";
|
||||
break;
|
||||
default:
|
||||
wpi::outs() << "Unknown";
|
||||
pixelFormat = "Unknown";
|
||||
break;
|
||||
}
|
||||
wpi::outs() << " Width:" << mode.width;
|
||||
wpi::outs() << " Height:" << mode.height;
|
||||
wpi::outs() << " FPS:" << mode.fps << '\n';
|
||||
fmt::print(" PixelFormat:{} Width:{} Height:{} FPS:{}\n", pixelFormat,
|
||||
mode.width, mode.height, mode.fps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
#include "cscore.h"
|
||||
@@ -27,11 +24,11 @@ int main() {
|
||||
for (;;) {
|
||||
uint64_t time = cvsink.GrabFrame(test);
|
||||
if (time == 0) {
|
||||
std::cout << "error: " << cvsink.GetError() << std::endl;
|
||||
fmt::print("error: {}\n", cvsink.GetError());
|
||||
continue;
|
||||
}
|
||||
std::cout << "got frame at time " << time << " size " << test.size()
|
||||
<< std::endl;
|
||||
fmt::print("got frame at time {} size ({}, {})\n", time, test.size().width,
|
||||
test.size().height);
|
||||
cv::flip(test, flip, 0);
|
||||
cvsource.PutFrame(flip);
|
||||
}
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <chrono>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
#include <wpi/SmallString.h>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <fmt/format.h>
|
||||
#include <wpi/StringExtras.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
wpi::errs() << "Usage: settings camera [prop val] ... -- [prop val]...\n";
|
||||
wpi::errs() << " Example: settings 1 brightness 30 raw_contrast 10\n";
|
||||
std::fputs("Usage: settings camera [prop val] ... -- [prop val]...\n",
|
||||
stderr);
|
||||
std::fputs(" Example: settings 1 brightness 30 raw_contrast 10\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int id;
|
||||
if (wpi::StringRef{argv[1]}.getAsInteger(10, id)) {
|
||||
wpi::errs() << "Expected number for camera\n";
|
||||
if (auto v = wpi::parse_integer<int>(argv[1], 10)) {
|
||||
id = v.value();
|
||||
} else {
|
||||
std::fputs("Expected number for camera\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -30,75 +31,75 @@ int main(int argc, char** argv) {
|
||||
|
||||
// Set prior to connect
|
||||
int arg = 2;
|
||||
wpi::StringRef propName;
|
||||
for (; arg < argc && wpi::StringRef{argv[arg]} != "--"; ++arg) {
|
||||
std::string_view propName;
|
||||
for (; arg < argc && std::string_view{argv[arg]} != "--"; ++arg) {
|
||||
if (propName.empty()) {
|
||||
propName = argv[arg];
|
||||
} else {
|
||||
wpi::StringRef propVal{argv[arg]};
|
||||
int intVal;
|
||||
if (propVal.getAsInteger(10, intVal))
|
||||
std::string_view propVal{argv[arg]};
|
||||
if (auto v = wpi::parse_integer<int>(propVal, 10)) {
|
||||
camera.GetProperty(propName).Set(v.value());
|
||||
} else {
|
||||
camera.GetProperty(propName).SetString(propVal);
|
||||
else
|
||||
camera.GetProperty(propName).Set(intVal);
|
||||
propName = wpi::StringRef{};
|
||||
}
|
||||
propName = {};
|
||||
}
|
||||
}
|
||||
if (arg < argc && wpi::StringRef{argv[arg]} == "--") ++arg;
|
||||
if (arg < argc && std::string_view{argv[arg]} == "--") {
|
||||
++arg;
|
||||
}
|
||||
|
||||
// Wait to connect
|
||||
while (!camera.IsConnected())
|
||||
while (!camera.IsConnected()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
|
||||
// Set rest
|
||||
propName = wpi::StringRef{};
|
||||
propName = {};
|
||||
for (; arg < argc; ++arg) {
|
||||
if (propName.empty()) {
|
||||
propName = argv[arg];
|
||||
} else {
|
||||
wpi::StringRef propVal{argv[arg]};
|
||||
int intVal;
|
||||
if (propVal.getAsInteger(10, intVal))
|
||||
std::string_view propVal{argv[arg]};
|
||||
if (auto v = wpi::parse_integer<int>(propVal, 10)) {
|
||||
camera.GetProperty(propName).Set(v.value());
|
||||
} else {
|
||||
camera.GetProperty(propName).SetString(propVal);
|
||||
else
|
||||
camera.GetProperty(propName).Set(intVal);
|
||||
propName = wpi::StringRef{};
|
||||
}
|
||||
propName = {};
|
||||
}
|
||||
}
|
||||
|
||||
// Print settings
|
||||
wpi::SmallString<64> buf;
|
||||
wpi::outs() << "Properties:\n";
|
||||
std::puts("Properties:");
|
||||
for (const auto& prop : camera.EnumerateProperties()) {
|
||||
wpi::outs() << " " << prop.GetName();
|
||||
fmt::print(" {}", prop.GetName());
|
||||
switch (prop.GetKind()) {
|
||||
case cs::VideoProperty::kBoolean:
|
||||
wpi::outs() << " (bool): "
|
||||
<< "value=" << prop.Get()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (bool): value={} default={}", prop.Get(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kInteger:
|
||||
wpi::outs() << " (int): "
|
||||
<< "value=" << prop.Get() << " min=" << prop.GetMin()
|
||||
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
|
||||
<< " default=" << prop.GetDefault();
|
||||
fmt::print(" (int): value={} min={} max={} step={} default={}",
|
||||
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
|
||||
prop.GetDefault());
|
||||
break;
|
||||
case cs::VideoProperty::kString:
|
||||
wpi::outs() << " (string): " << prop.GetString(buf);
|
||||
fmt::print(" (string): {}", prop.GetString());
|
||||
break;
|
||||
case cs::VideoProperty::kEnum: {
|
||||
wpi::outs() << " (enum): "
|
||||
<< "value=" << prop.Get();
|
||||
fmt::print(" (enum): value={}", prop.Get());
|
||||
auto choices = prop.GetChoices();
|
||||
for (size_t i = 0; i < choices.size(); ++i) {
|
||||
if (choices[i].empty()) continue;
|
||||
wpi::outs() << "\n " << i << ": " << choices[i];
|
||||
if (!choices[i].empty()) {
|
||||
fmt::print("\n {}: {}", i, choices[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wpi::outs() << '\n';
|
||||
std::fputc('\n', stdout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
// 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 <fmt/core.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
|
||||
#include "cscore.h"
|
||||
@@ -29,11 +24,11 @@ int main() {
|
||||
for (;;) {
|
||||
uint64_t time = cvsink.GrabFrame(test);
|
||||
if (time == 0) {
|
||||
std::cout << "error: " << cvsink.GetError() << std::endl;
|
||||
fmt::print("error: {}\n", cvsink.GetError());
|
||||
continue;
|
||||
}
|
||||
std::cout << "got frame at time " << time << " size " << test.size()
|
||||
<< std::endl;
|
||||
fmt::print("got frame at time {} size ({}, {})\n", time, test.size().width,
|
||||
test.size().height);
|
||||
cv::flip(test, flip, 0);
|
||||
cvsource.PutFrame(flip);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <cstdio>
|
||||
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main() {
|
||||
wpi::outs() << "hostname: " << cs::GetHostname() << '\n';
|
||||
wpi::outs() << "IPv4 network addresses:\n";
|
||||
for (const auto& addr : cs::GetNetworkInterfaces())
|
||||
wpi::outs() << " " << addr << '\n';
|
||||
fmt::print("hostname: {}\n", cs::GetHostname());
|
||||
std::puts("IPv4 network addresses:");
|
||||
for (const auto& addr : cs::GetNetworkInterfaces()) {
|
||||
fmt::print(" {}\n", addr);
|
||||
}
|
||||
cs::UsbCamera camera{"usbcam", 0};
|
||||
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
|
||||
cs::MjpegServer mjpegServer{"httpserver", 8081};
|
||||
@@ -24,9 +22,8 @@ int main() {
|
||||
CS_Status status = 0;
|
||||
cs::AddListener(
|
||||
[&](const cs::RawEvent& event) {
|
||||
wpi::outs() << "FPS=" << camera.GetActualFPS()
|
||||
<< " MBPS=" << (camera.GetActualDataRate() / 1000000.0)
|
||||
<< '\n';
|
||||
fmt::print("FPS={} MBPS={}\n", camera.GetActualFPS(),
|
||||
(camera.GetActualDataRate() / 1000000.0));
|
||||
},
|
||||
cs::RawEvent::kTelemetryUpdated, false, &status);
|
||||
cs::SetTelemetryPeriod(1.0);
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2020 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <atomic>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <wpi/raw_ostream.h>
|
||||
#include <wpi/spinlock.h>
|
||||
#include <wpigui.h>
|
||||
|
||||
@@ -41,7 +39,7 @@ int main() {
|
||||
// get frame from camera
|
||||
uint64_t time = cvsink.GrabFrame(frame);
|
||||
if (time == 0) {
|
||||
wpi::outs() << "error: " << cvsink.GetError() << '\n';
|
||||
fmt::print("error: {}\n", cvsink.GetError());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -53,7 +51,9 @@ int main() {
|
||||
} else {
|
||||
{
|
||||
std::scoped_lock lock(sharedFreeListMutex);
|
||||
for (auto mat : sharedFreeList) sourceFreeList.emplace_back(mat);
|
||||
for (auto mat : sharedFreeList) {
|
||||
sourceFreeList.emplace_back(mat);
|
||||
}
|
||||
sharedFreeList.clear();
|
||||
}
|
||||
if (!sourceFreeList.empty()) {
|
||||
@@ -71,7 +71,9 @@ int main() {
|
||||
auto prev = latestFrame.exchange(out);
|
||||
|
||||
// put prev on free list
|
||||
if (prev) sourceFreeList.emplace_back(prev);
|
||||
if (prev) {
|
||||
sourceFreeList.emplace_back(prev);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.cscore;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import edu.wpi.cscore.VideoMode.PixelFormat;
|
||||
import edu.wpi.cscore.raw.RawFrame;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public class RawCVMatSink extends ImageSink {
|
||||
RawFrame frame = new RawFrame();
|
||||
@@ -27,26 +22,25 @@ public class RawCVMatSink extends ImageSink {
|
||||
private int getCVFormat(PixelFormat pixelFormat) {
|
||||
int type = 0;
|
||||
switch (pixelFormat) {
|
||||
case kYUYV:
|
||||
case kRGB565:
|
||||
type = CvType.CV_8UC2;
|
||||
break;
|
||||
case kBGR:
|
||||
type = CvType.CV_8UC3;
|
||||
break;
|
||||
case kGray:
|
||||
case kMJPEG:
|
||||
default:
|
||||
type = CvType.CV_8UC1;
|
||||
break;
|
||||
case kYUYV:
|
||||
case kRGB565:
|
||||
type = CvType.CV_8UC2;
|
||||
break;
|
||||
case kBGR:
|
||||
type = CvType.CV_8UC3;
|
||||
break;
|
||||
case kGray:
|
||||
case kMJPEG:
|
||||
default:
|
||||
type = CvType.CV_8UC1;
|
||||
break;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
* WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
* Create a sink for accepting OpenCV images. WaitForFrame() must be called on the created sink to
|
||||
* get each new image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
@@ -55,24 +49,21 @@ public class RawCVMatSink extends ImageSink {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after 0.225 seconds.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
* Wait for the next frame and get the image. Times out (returning 0) after 0.225 seconds. The
|
||||
* provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message)
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error message)
|
||||
*/
|
||||
public long grabFrame(Mat image) {
|
||||
return grabFrame(image, 0.225);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
* Wait for the next frame and get the image. Times out (returning 0) after timeout seconds. The
|
||||
* provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in 1 us increments.
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
|
||||
* is in 1 us increments.
|
||||
*/
|
||||
public long grabFrame(Mat image, double timeout) {
|
||||
frame.setWidth(0);
|
||||
@@ -83,12 +74,20 @@ public class RawCVMatSink extends ImageSink {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (frame.getDataByteBuffer() != origByteBuffer || width != frame.getWidth() || height != frame.getHeight() || pixelFormat != frame.getPixelFormat()) {
|
||||
if (frame.getDataByteBuffer() != origByteBuffer
|
||||
|| width != frame.getWidth()
|
||||
|| height != frame.getHeight()
|
||||
|| pixelFormat != frame.getPixelFormat()) {
|
||||
origByteBuffer = frame.getDataByteBuffer();
|
||||
height = frame.getHeight();
|
||||
width = frame.getWidth();
|
||||
pixelFormat = frame.getPixelFormat();
|
||||
tmpMat = new Mat(frame.getHeight(), frame.getWidth(), getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)), origByteBuffer);
|
||||
tmpMat =
|
||||
new Mat(
|
||||
frame.getHeight(),
|
||||
frame.getWidth(),
|
||||
getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)),
|
||||
origByteBuffer);
|
||||
}
|
||||
tmpMat.copyTo(image);
|
||||
return rv;
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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.cscore;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
import edu.wpi.cscore.VideoMode.PixelFormat;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
public class RawCVMatSource extends ImageSource {
|
||||
/**
|
||||
@@ -19,11 +15,9 @@ public class RawCVMatSource extends ImageSource {
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
public RawCVMatSource(String name, VideoMode mode) {
|
||||
super(CameraServerJNI.createRawSource(name,
|
||||
mode.pixelFormat.getValue(),
|
||||
mode.width,
|
||||
mode.height,
|
||||
mode.fps));
|
||||
super(
|
||||
CameraServerJNI.createRawSource(
|
||||
name, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,16 +29,17 @@ public class RawCVMatSource extends ImageSource {
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
public RawCVMatSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
public RawCVMatSource(
|
||||
String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerJNI.createRawSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* Mat.convertTo() and/or cvtColor() to convert it first.
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images are supported. If the
|
||||
* format, depth or channel order is different, use Mat.convertTo() and/or cvtColor() to convert
|
||||
* it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
@@ -54,6 +49,12 @@ public class RawCVMatSource extends ImageSource {
|
||||
throw new VideoException("Unsupported Image Type");
|
||||
}
|
||||
int imgType = channels == 1 ? PixelFormat.kGray.getValue() : PixelFormat.kBGR.getValue();
|
||||
CameraServerJNI.putRawSourceFrame(m_handle, image.dataAddr(), image.width(), image.height(), imgType, (int)image.total() * channels);
|
||||
CameraServerJNI.putRawSourceFrame(
|
||||
m_handle,
|
||||
image.dataAddr(),
|
||||
image.width(),
|
||||
image.height(),
|
||||
imgType,
|
||||
(int) image.total() * channels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import edu.wpi.first.wpiutil.RuntimeDetector;
|
||||
|
||||
public final class DevMain {
|
||||
/**
|
||||
* Main method.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello World!");
|
||||
System.out.println(RuntimeDetector.getPlatformPath());
|
||||
System.out.println(CameraServerJNI.getHostname());
|
||||
}
|
||||
|
||||
private DevMain() {
|
||||
}
|
||||
}
|
||||
18
cscore/src/dev/java/edu/wpi/first/cscore/DevMain.java
Normal file
18
cscore/src/dev/java/edu/wpi/first/cscore/DevMain.java
Normal file
@@ -0,0 +1,18 @@
|
||||
// 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.cscore;
|
||||
|
||||
import edu.wpi.first.util.RuntimeDetector;
|
||||
|
||||
public final class DevMain {
|
||||
/** Main method. */
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello World!");
|
||||
System.out.println(RuntimeDetector.getPlatformPath());
|
||||
System.out.println(CameraServerJNI.getHostname());
|
||||
}
|
||||
|
||||
private DevMain() {}
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
// 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 <iostream>
|
||||
#include <fmt/core.h>
|
||||
|
||||
#include "cscore.h"
|
||||
|
||||
int main() { std::cout << cs::GetHostname() << std::endl; }
|
||||
int main() {
|
||||
fmt::print("{}\n", cs::GetHostname());
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
/**
|
||||
* A source that represents an Axis IP camera.
|
||||
*/
|
||||
public class AxisCamera extends HttpCamera {
|
||||
private static String hostToUrl(String host) {
|
||||
return "http://" + host + "/mjpg/video.mjpg";
|
||||
}
|
||||
|
||||
private static String[] hostToUrl(String[] hosts) {
|
||||
String[] urls = new String[hosts.length];
|
||||
for (int i = 0; i < hosts.length; i++) {
|
||||
urls[i] = hostToUrl(hosts[i]);
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
|
||||
*/
|
||||
public AxisCamera(String name, String host) {
|
||||
super(name, hostToUrl(host), HttpCameraKind.kAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source for an Axis IP camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param hosts Array of Camera host IPs/DNS names
|
||||
*/
|
||||
public AxisCamera(String name, String[] hosts) {
|
||||
super(name, hostToUrl(hosts), HttpCameraKind.kAxis);
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.opencv.core.Core;
|
||||
|
||||
import edu.wpi.first.wpiutil.RuntimeLoader;
|
||||
|
||||
public class CameraServerCvJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<Core> loader = null;
|
||||
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
String opencvName = Core.NATIVE_LIBRARY_NAME;
|
||||
if (Helper.getExtractOnStaticLoad()) {
|
||||
try {
|
||||
CameraServerJNI.forceLoad();
|
||||
loader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
|
||||
loader.loadLibraryHashed();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
libraryLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force load the library.
|
||||
*/
|
||||
public static synchronized void forceLoad() throws IOException {
|
||||
if (libraryLoaded) {
|
||||
return;
|
||||
}
|
||||
CameraServerJNI.forceLoad();
|
||||
loader = new RuntimeLoader<>(Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
|
||||
loader.loadLibrary();
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
public static native int createCvSource(String name, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
public static native void putSourceFrame(int source, long imageNativeObj);
|
||||
|
||||
public static native int createCvSink(String name);
|
||||
//public static native int createCvSinkCallback(String name,
|
||||
// void (*processFrame)(long time));
|
||||
|
||||
public static native long grabSinkFrame(int sink, long imageNativeObj);
|
||||
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import edu.wpi.cscore.raw.RawFrame;
|
||||
import edu.wpi.first.wpiutil.RuntimeLoader;
|
||||
|
||||
public class CameraServerJNI {
|
||||
static boolean libraryLoaded = false;
|
||||
|
||||
static RuntimeLoader<CameraServerJNI> loader = null;
|
||||
|
||||
public static class Helper {
|
||||
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
|
||||
|
||||
public static boolean getExtractOnStaticLoad() {
|
||||
return extractOnStaticLoad.get();
|
||||
}
|
||||
|
||||
public static void setExtractOnStaticLoad(boolean load) {
|
||||
extractOnStaticLoad.set(load);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
if (Helper.getExtractOnStaticLoad()) {
|
||||
try {
|
||||
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
|
||||
loader.loadLibrary();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
libraryLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force load the library.
|
||||
*/
|
||||
public static synchronized void forceLoad() throws IOException {
|
||||
if (libraryLoaded) {
|
||||
return;
|
||||
}
|
||||
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
|
||||
loader.loadLibrary();
|
||||
libraryLoaded = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Property Functions
|
||||
//
|
||||
public static native int getPropertyKind(int property);
|
||||
public static native String getPropertyName(int property);
|
||||
public static native int getProperty(int property);
|
||||
public static native void setProperty(int property, int value);
|
||||
public static native int getPropertyMin(int property);
|
||||
public static native int getPropertyMax(int property);
|
||||
public static native int getPropertyStep(int property);
|
||||
public static native int getPropertyDefault(int property);
|
||||
public static native String getStringProperty(int property);
|
||||
public static native void setStringProperty(int property, String value);
|
||||
public static native String[] getEnumPropertyChoices(int property);
|
||||
|
||||
//
|
||||
// Source Creation Functions
|
||||
//
|
||||
public static native int createUsbCameraDev(String name, int dev);
|
||||
public static native int createUsbCameraPath(String name, String path);
|
||||
public static native int createHttpCamera(String name, String url, int kind);
|
||||
public static native int createHttpCameraMulti(String name, String[] urls, int kind);
|
||||
public static native int createRawSource(String name, int pixelFormat, int width, int height, int fps);
|
||||
|
||||
//
|
||||
// Source Functions
|
||||
//
|
||||
public static native int getSourceKind(int source);
|
||||
public static native String getSourceName(int source);
|
||||
public static native String getSourceDescription(int source);
|
||||
public static native long getSourceLastFrameTime(int source);
|
||||
public static native void setSourceConnectionStrategy(int source, int strategy);
|
||||
public static native boolean isSourceConnected(int source);
|
||||
public static native boolean isSourceEnabled(int source);
|
||||
public static native int getSourceProperty(int source, String name);
|
||||
public static native int[] enumerateSourceProperties(int source);
|
||||
public static native VideoMode getSourceVideoMode(int source);
|
||||
public static native boolean setSourceVideoMode(int source, int pixelFormat, int width, int height, int fps);
|
||||
public static native boolean setSourcePixelFormat(int source, int pixelFormat);
|
||||
public static native boolean setSourceResolution(int source, int width, int height);
|
||||
public static native boolean setSourceFPS(int source, int fps);
|
||||
public static native boolean setSourceConfigJson(int source, String config);
|
||||
public static native String getSourceConfigJson(int source);
|
||||
public static native VideoMode[] enumerateSourceVideoModes(int source);
|
||||
public static native int[] enumerateSourceSinks(int source);
|
||||
public static native int copySource(int source);
|
||||
public static native void releaseSource(int source);
|
||||
|
||||
//
|
||||
// Camera Source Common Property Fuctions
|
||||
//
|
||||
public static native void setCameraBrightness(int source, int brightness);
|
||||
public static native int getCameraBrightness(int source);
|
||||
public static native void setCameraWhiteBalanceAuto(int source);
|
||||
public static native void setCameraWhiteBalanceHoldCurrent(int source);
|
||||
public static native void setCameraWhiteBalanceManual(int source, int value);
|
||||
public static native void setCameraExposureAuto(int source);
|
||||
public static native void setCameraExposureHoldCurrent(int source);
|
||||
public static native void setCameraExposureManual(int source, int value);
|
||||
|
||||
//
|
||||
// UsbCamera Source Functions
|
||||
//
|
||||
public static native void setUsbCameraPath(int source, String path);
|
||||
public static native String getUsbCameraPath(int source);
|
||||
public static native UsbCameraInfo getUsbCameraInfo(int source);
|
||||
|
||||
//
|
||||
// HttpCamera Source Functions
|
||||
//
|
||||
public static native int getHttpCameraKind(int source);
|
||||
public static native void setHttpCameraUrls(int source, String[] urls);
|
||||
public static native String[] getHttpCameraUrls(int source);
|
||||
|
||||
//
|
||||
// Image Source Functions
|
||||
//
|
||||
public static native void putRawSourceFrameBB(int source, ByteBuffer data, int width, int height, int pixelFormat, int totalData);
|
||||
public static native void putRawSourceFrame(int source, long data, int width, int height, int pixelFormat, int totalData);
|
||||
public static void putRawSourceFrame(int source, RawFrame raw) {
|
||||
putRawSourceFrame(source, raw.getDataPtr(), raw.getWidth(), raw.getHeight(), raw.getPixelFormat(), raw.getTotalData());
|
||||
}
|
||||
public static native void notifySourceError(int source, String msg);
|
||||
public static native void setSourceConnected(int source, boolean connected);
|
||||
public static native void setSourceDescription(int source, String description);
|
||||
public static native int createSourceProperty(int source, String name, int kind, int minimum, int maximum, int step, int defaultValue, int value);
|
||||
public static native void setSourceEnumPropertyChoices(int source, int property, String[] choices);
|
||||
|
||||
//
|
||||
// Sink Creation Functions
|
||||
//
|
||||
public static native int createMjpegServer(String name, String listenAddress, int port);
|
||||
|
||||
public static native int createRawSink(String name);
|
||||
|
||||
//
|
||||
// Sink Functions
|
||||
//
|
||||
public static native int getSinkKind(int sink);
|
||||
public static native String getSinkName(int sink);
|
||||
public static native String getSinkDescription(int sink);
|
||||
public static native int getSinkProperty(int sink, String name);
|
||||
public static native int[] enumerateSinkProperties(int sink);
|
||||
public static native boolean setSinkConfigJson(int sink, String config);
|
||||
public static native String getSinkConfigJson(int sink);
|
||||
public static native void setSinkSource(int sink, int source);
|
||||
public static native int getSinkSourceProperty(int sink, String name);
|
||||
public static native int getSinkSource(int sink);
|
||||
public static native int copySink(int sink);
|
||||
public static native void releaseSink(int sink);
|
||||
|
||||
//
|
||||
// MjpegServer Sink Functions
|
||||
//
|
||||
public static native String getMjpegServerListenAddress(int sink);
|
||||
public static native int getMjpegServerPort(int sink);
|
||||
|
||||
//
|
||||
// Image Sink Functions
|
||||
//
|
||||
public static native void setSinkDescription(int sink, String description);
|
||||
|
||||
private static native long grabRawSinkFrameImpl(int sink, RawFrame rawFrame, long rawFramePtr, ByteBuffer byteBuffer, int width, int height, int pixelFormat);
|
||||
private static native long grabRawSinkFrameTimeoutImpl(int sink, RawFrame rawFrame, long rawFramePtr, ByteBuffer byteBuffer, int width, int height, int pixelFormat, double timeout);
|
||||
|
||||
public static long grabSinkFrame(int sink, RawFrame rawFrame) {
|
||||
return grabRawSinkFrameImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat());
|
||||
}
|
||||
public static long grabSinkFrameTimeout(int sink, RawFrame rawFrame, double timeout) {
|
||||
return grabRawSinkFrameTimeoutImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat(), timeout);
|
||||
}
|
||||
public static native String getSinkError(int sink);
|
||||
public static native void setSinkEnabled(int sink, boolean enabled);
|
||||
|
||||
//
|
||||
// Listener Functions
|
||||
//
|
||||
public static native int addListener(Consumer<VideoEvent> listener,
|
||||
int eventMask, boolean immediateNotify);
|
||||
|
||||
public static native void removeListener(int handle);
|
||||
|
||||
//
|
||||
// Telemetry Functions
|
||||
//
|
||||
public enum TelemetryKind {
|
||||
kSourceBytesReceived(1),
|
||||
kSourceFramesReceived(2);
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private final int value;
|
||||
|
||||
TelemetryKind(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
public static native void setTelemetryPeriod(double seconds);
|
||||
public static native double getTelemetryElapsedTime();
|
||||
public static native long getTelemetryValue(int handle, int kind);
|
||||
public static long getTelemetryValue(int handle, TelemetryKind kind) {
|
||||
return getTelemetryValue(handle, kind.getValue());
|
||||
}
|
||||
public static native double getTelemetryAverageValue(int handle, int kind);
|
||||
public static double getTelemetryAverageValue(int handle, TelemetryKind kind) {
|
||||
return getTelemetryAverageValue(handle, kind.getValue());
|
||||
}
|
||||
|
||||
//
|
||||
// Logging Functions
|
||||
//
|
||||
@FunctionalInterface
|
||||
public interface LoggerFunction {
|
||||
void apply(int level, String file, int line, String msg);
|
||||
}
|
||||
public static native void setLogger(LoggerFunction func, int minLevel);
|
||||
|
||||
//
|
||||
// Utility Functions
|
||||
//
|
||||
public static native UsbCameraInfo[] enumerateUsbCameras();
|
||||
|
||||
public static native int[] enumerateSources();
|
||||
|
||||
public static native int[] enumerateSinks();
|
||||
|
||||
public static native String getHostname();
|
||||
|
||||
public static native String[] getNetworkInterfaces();
|
||||
|
||||
public static native long allocateRawFrame();
|
||||
|
||||
public static native void freeRawFrame(long frame);
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
* A sink for user code to accept video frames as OpenCV images.
|
||||
* These sinks require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, see the documentation how to build your own
|
||||
* with RawSink.
|
||||
*/
|
||||
public class CvSink extends ImageSink {
|
||||
/**
|
||||
* Create a sink for accepting OpenCV images.
|
||||
* WaitForFrame() must be called on the created sink to get each new
|
||||
* image.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
*/
|
||||
public CvSink(String name) {
|
||||
super(CameraServerCvJNI.createCvSink(name));
|
||||
}
|
||||
|
||||
/// Create a sink for accepting OpenCV images in a separate thread.
|
||||
/// A thread will be created that calls WaitForFrame() and calls the
|
||||
/// processFrame() callback each time a new frame arrives.
|
||||
/// @param name Source name (arbitrary unique identifier)
|
||||
/// @param processFrame Frame processing function; will be called with a
|
||||
/// time=0 if an error occurred. processFrame should call GetImage()
|
||||
/// or GetError() as needed, but should not call (except in very
|
||||
/// unusual circumstances) WaitForImage().
|
||||
//public CvSink(wpi::StringRef name,
|
||||
// std::function<void(uint64_t time)> processFrame) {
|
||||
// super(CameraServerJNI.createCvSinkCallback(name, processFrame));
|
||||
//}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after 0.225 seconds.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message)
|
||||
*/
|
||||
public long grabFrame(Mat image) {
|
||||
return grabFrame(image, 0.225);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image.
|
||||
* Times out (returning 0) after timeout seconds.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in 1 us increments.
|
||||
*/
|
||||
public long grabFrame(Mat image, double timeout) {
|
||||
return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the next frame and get the image. May block forever.
|
||||
* The provided image will have three 3-bit channels stored in BGR order.
|
||||
*
|
||||
* @return Frame time, or 0 on error (call GetError() to obtain the error
|
||||
* message); the frame time is in 1 us increments.
|
||||
*/
|
||||
public long grabFrameNoTimeout(Mat image) {
|
||||
return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
/**
|
||||
* A source that represents a video camera.
|
||||
* These sources require the WPILib OpenCV builds.
|
||||
* For an alternate OpenCV, see the documentation how to build your own
|
||||
* with RawSource.
|
||||
*/
|
||||
public class CvSource extends ImageSource {
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param mode Video mode being generated
|
||||
*/
|
||||
public CvSource(String name, VideoMode mode) {
|
||||
super(CameraServerCvJNI.createCvSource(name,
|
||||
mode.pixelFormat.getValue(),
|
||||
mode.width,
|
||||
mode.height,
|
||||
mode.fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an OpenCV source.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param pixelFormat Pixel format
|
||||
* @param width width
|
||||
* @param height height
|
||||
* @param fps fps
|
||||
*/
|
||||
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
|
||||
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put an OpenCV image and notify sinks.
|
||||
*
|
||||
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
|
||||
* are supported. If the format, depth or channel order is different, use
|
||||
* Mat.convertTo() and/or cvtColor() to convert it first.
|
||||
*
|
||||
* @param image OpenCV image
|
||||
*/
|
||||
public void putFrame(Mat image) {
|
||||
CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
/**
|
||||
* A source that represents a MJPEG-over-HTTP (IP) camera.
|
||||
*/
|
||||
public class HttpCamera extends VideoCamera {
|
||||
public enum HttpCameraKind {
|
||||
kUnknown(0), kMJPGStreamer(1), kCSCore(2), kAxis(3);
|
||||
|
||||
@SuppressWarnings("MemberName")
|
||||
private final int value;
|
||||
|
||||
HttpCameraKind(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from the numerical representation of kind to an enum type.
|
||||
*
|
||||
* @param kind The numerical representation of kind
|
||||
* @return The kind
|
||||
*/
|
||||
public static HttpCameraKind getHttpCameraKindFromInt(int kind) {
|
||||
switch (kind) {
|
||||
case 1: return HttpCameraKind.kMJPGStreamer;
|
||||
case 2: return HttpCameraKind.kCSCore;
|
||||
case 3: return HttpCameraKind.kAxis;
|
||||
default: return HttpCameraKind.kUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source for a MJPEG-over-HTTP (IP) camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
|
||||
*/
|
||||
public HttpCamera(String name, String url) {
|
||||
super(CameraServerJNI.createHttpCamera(name, url, HttpCameraKind.kUnknown.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source for a MJPEG-over-HTTP (IP) camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg")
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
public HttpCamera(String name, String url, HttpCameraKind kind) {
|
||||
super(CameraServerJNI.createHttpCamera(name, url, kind.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source for a MJPEG-over-HTTP (IP) camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param urls Array of Camera URLs
|
||||
*/
|
||||
public HttpCamera(String name, String[] urls) {
|
||||
super(CameraServerJNI.createHttpCameraMulti(name, urls, HttpCameraKind.kUnknown.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a source for a MJPEG-over-HTTP (IP) camera.
|
||||
*
|
||||
* @param name Source name (arbitrary unique identifier)
|
||||
* @param urls Array of Camera URLs
|
||||
* @param kind Camera kind (e.g. kAxis)
|
||||
*/
|
||||
public HttpCamera(String name, String[] urls, HttpCameraKind kind) {
|
||||
super(CameraServerJNI.createHttpCameraMulti(name, urls, kind.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the kind of HTTP camera.
|
||||
*
|
||||
* <p>Autodetection can result in returning a different value than the camera
|
||||
* was created with.
|
||||
*/
|
||||
public HttpCameraKind getHttpCameraKind() {
|
||||
return getHttpCameraKindFromInt(CameraServerJNI.getHttpCameraKind(m_handle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the URLs used to connect to the camera.
|
||||
*/
|
||||
public void setUrls(String[] urls) {
|
||||
CameraServerJNI.setHttpCameraUrls(m_handle, urls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URLs used to connect to the camera.
|
||||
*/
|
||||
public String[] getUrls() {
|
||||
return CameraServerJNI.getHttpCameraUrls(m_handle);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
public abstract class ImageSink extends VideoSink {
|
||||
protected ImageSink(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sink description.
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
CameraServerJNI.setSinkDescription(m_handle, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error string. Call this if WaitForFrame() returns 0 to determine
|
||||
* what the error is.
|
||||
*/
|
||||
public String getError() {
|
||||
return CameraServerJNI.getSinkError(m_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable getting new frames.
|
||||
* Disabling will cause processFrame (for callback-based CvSinks) to not
|
||||
* be called and WaitForFrame() to not return. This can be used to save
|
||||
* processor resources when frames are not needed.
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
CameraServerJNI.setSinkEnabled(m_handle, enabled);
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
|
||||
/* Open Source Software - may be modified and shared by FRC teams. The code */
|
||||
/* must be accompanied by the FIRST BSD license file in the root directory of */
|
||||
/* the project. */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
package edu.wpi.cscore;
|
||||
|
||||
public abstract class ImageSource extends VideoSource {
|
||||
protected ImageSource(int handle) {
|
||||
super(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signal sinks that an error has occurred. This should be called instead
|
||||
* of NotifyFrame when an error occurs.
|
||||
*/
|
||||
public void notifyError(String msg) {
|
||||
CameraServerJNI.notifySourceError(m_handle, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source connection status. Defaults to true.
|
||||
*
|
||||
* @param connected True for connected, false for disconnected
|
||||
*/
|
||||
public void setConnected(boolean connected) {
|
||||
CameraServerJNI.setSourceConnected(m_handle, connected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source description.
|
||||
*
|
||||
* @param description Description
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
CameraServerJNI.setSourceDescription(m_handle, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param kind Property kind
|
||||
* @param minimum Minimum value
|
||||
* @param maximum Maximum value
|
||||
* @param step Step value
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createProperty(String name,
|
||||
VideoProperty.Kind kind,
|
||||
int minimum,
|
||||
int maximum,
|
||||
int step,
|
||||
int defaultValue,
|
||||
int value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
kind.getValue(),
|
||||
minimum,
|
||||
maximum,
|
||||
step,
|
||||
defaultValue,
|
||||
value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an integer property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param minimum Minimum value
|
||||
* @param maximum Maximum value
|
||||
* @param step Step value
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createIntegerProperty(String name,
|
||||
int minimum,
|
||||
int maximum,
|
||||
int step,
|
||||
int defaultValue,
|
||||
int value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kInteger.getValue(),
|
||||
minimum,
|
||||
maximum,
|
||||
step,
|
||||
defaultValue,
|
||||
value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a boolean property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param defaultValue Default value
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createBooleanProperty(String name, boolean defaultValue, boolean value) {
|
||||
return new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kBoolean.getValue(),
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
defaultValue ? 1 : 0,
|
||||
value ? 1 : 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string property.
|
||||
*
|
||||
* @param name Property name
|
||||
* @param value Current value
|
||||
* @return Property
|
||||
*/
|
||||
public VideoProperty createStringProperty(String name, String value) {
|
||||
VideoProperty prop = new VideoProperty(
|
||||
CameraServerJNI.createSourceProperty(m_handle,
|
||||
name,
|
||||
VideoProperty.Kind.kString.getValue(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0));
|
||||
prop.setString(value);
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
*
|
||||
* @param property Property
|
||||
* @param choices Choices
|
||||
*/
|
||||
public void setEnumPropertyChoices(VideoProperty property, String[] choices) {
|
||||
CameraServerJNI.setSourceEnumPropertyChoices(m_handle, property.m_handle, choices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure enum property choices.
|
||||
*
|
||||
* @param property Property
|
||||
* @param choices Choices
|
||||
* @deprecated Use {@code setEnumPropertyChoices} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("MethodName")
|
||||
public void SetEnumPropertyChoices(VideoProperty property, String[] choices) {
|
||||
setEnumPropertyChoices(property, choices);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user