Compare commits

...

196 Commits

Author SHA1 Message Date
truher
8b6df88783 [wpilibj] Tachometer.getFrequency(): Fix bug (#4281)
Now it returns 1/period (like Tachometer.cpp); before it just returned period.
2022-06-01 10:13:19 -07:00
Tyler Veness
345cff08c0 [wpiutil] Make wpi::array constexpr (#4278) 2022-05-31 20:21:29 -07:00
Tyler Veness
57428112ac [wpimath] Upgrade to Drake v1.3.0 (#4279) 2022-05-31 20:20:01 -07:00
Thad House
a18d4ff154 [build] Fix tools not being copied when built with -Ponly* (#4276) 2022-05-29 22:09:00 -07:00
Peter Johnson
d1cd07b9f3 [wpigui] Add OpenURL (#4273)
This function opens a URL using the default browser.
2022-05-29 18:45:39 -07:00
Peter Johnson
e67f8e917a [glass] Use glfwSetKeyCallback for Enter key remap (#4275)
The imgui internals methods break with imgui >= 0.87.
2022-05-29 18:44:52 -07:00
Tyler Veness
be2fedfe50 [wpimath] Add stdexcept include for std::invalid_argument (IWYU) (#4274) 2022-05-29 15:33:19 -07:00
Peter Johnson
7ad2be172e [build] Update native-utils to 2023.0.1 (#4272)
Also remove x86 build bits.
2022-05-28 11:12:59 -07:00
Peter Johnson
abc605c9c9 [ci] Update workflows to 20.04 base image (#4271) 2022-05-27 23:33:33 -07:00
PJ Reiniger
3e94805220 [wpiutil] Reduce llvm collections patches (#4268) 2022-05-27 13:41:28 -07:00
Tyler Veness
db2e1d170e [upstream_utils] Document how to update thirdparty libraries (#4253)
Also, add a CI job to ensure the sources in the repo are consistent with
the update scripts.
2022-05-26 09:02:32 -07:00
Tyler Veness
96ebdcaf16 [wpimath] Remove unused Eigen AutoDiff module (#4267)
Drake's tests used to include it, but it's commented out since it's not
used.
2022-05-26 09:01:45 -07:00
PJ Reiniger
553b2a3b12 [upstream_utils] Fix stackwalker (#4265) 2022-05-24 21:51:32 -07:00
Tyler Veness
3e13ef42eb [wpilibc] Add missing std::array #include (include-what-you-use) (#4266) 2022-05-24 21:49:22 -07:00
Tyler Veness
d651a1fcec Fix internal deprecation warnings (#4257)
This allows us to error out on deprecation warnings for thirdparty
libraries and standard library features.

Co-authored-by: Starlight220 <53231611+Starlight220@users.noreply.github.com>
2022-05-24 13:56:48 -07:00
ohowe
b193b318c1 [commands] Add unless() decorator (#4244) 2022-05-24 09:22:19 -07:00
bovlb
ef3714223b [commands] Remove docs reference to obsolete interrupted() method (NFC) (#4262) 2022-05-24 09:19:38 -07:00
Dalton Smith
3d8dbbbac3 [readme] Add quickstart (#4225) 2022-05-22 20:19:50 -07:00
Peter Johnson
013efdde25 [wpinet] Wrap a number of newer libuv features (#4260) 2022-05-22 20:18:23 -07:00
Starlight220
816aa4e465 [wpilib] Add Pneumatics sim classes (#4033) 2022-05-22 07:21:40 -07:00
Tyler Veness
046c2c8972 [wpilibc] Rename SpeedControllerGroupTest.cpp (#4258)
Also move motor controller test files into motorcontrol folder to match
Java.
2022-05-21 16:20:26 -07:00
Tyler Veness
d80e9cdf64 [upstream_utils] Use shallow clones for thirdparty repos (#4255)
This makes update_llvm.py in particular much faster because the full
repo requires fetching 2 GB.
2022-05-20 18:59:33 -07:00
Tyler Veness
7576136b4a [upstream_utils] Make update_llvm.py executable (#4254) 2022-05-20 17:16:19 -07:00
PJ Reiniger
c3b223ce60 [wpiutil] Vendor llvm and update to 13.0.0 (#4224) 2022-05-20 15:59:53 -07:00
Tyler Veness
5aa67f56e6 [wpimath] Clean up math comments (#4252) 2022-05-20 15:16:56 -07:00
Tyler Veness
fff4d1f44e [wpimath] Extend Eigen warning suppression to GCC 12 (#4251)
It originally only applied to GCC 11. The CMake build passed without
this change, but not the Gradle build.
2022-05-19 18:50:29 -07:00
Tyler Veness
0d9956273c [wpimath] Add CoordinateSystem.convert() translation and rotation overloads (#4227) 2022-05-18 20:41:15 -07:00
Tyler Veness
3fada4e0b4 [wpinet] Update to libuv 1.44.1 (#4232) 2022-05-18 20:40:27 -07:00
Tyler Veness
65b23ac45e [wpilibc] Fix return value of DriverStation::GetJoystickAxisType() (#4230)
It was returning a pointer to the axis type array cast to a bool (always
1) instead of returning the desired axis type.
2022-05-18 14:36:11 -07:00
Tyler Veness
4ac34c0141 [upstream_utils] Cleanup update_libuv.py (#4249) 2022-05-18 14:34:34 -07:00
Tyler Veness
8bd614bb1e [upstream_utils] Use "git am" instead of "git apply" for patches (#4248)
This creates actual commits in the thirdparty repo, which makes rebasing
them onto new versions much easier.
2022-05-18 12:23:15 -07:00
Tyler Veness
4253d6d5f0 [upstream_utils] Apply "git am" patches individually (#4250)
Also, giving am_patches() zero patches isn't an error. The function will
just be a no-op.
2022-05-18 12:22:31 -07:00
Tyler Veness
6a4752dcdc Fix GCC 12.1 warning false positives (#4246) 2022-05-18 12:22:10 -07:00
Tyler Veness
5876b40f08 [wpimath] Memoize CoordinateSystem and CoordinateAxis statics (#4241) 2022-05-18 10:47:46 -07:00
Tyler Veness
5983434a70 [cameraserver] Replace IterativeRobot in comment sample code with TimedRobot (#4238) 2022-05-15 20:47:50 -07:00
Max Gordon
a3d44a1e69 [wpimath] Add Translation2d.getAngle() (#4217)
Co-authored-by: Max Gordon <tonald.drump2.0@gamil.com>
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2022-05-14 21:22:00 -07:00
Tyler Veness
d364bbd5a7 [upstream_utils] Give vendor update scripts execute permissions (#4226) 2022-05-14 15:31:51 -07:00
Tyler Veness
f341e1b2be [wpimath] Document standard coordinate systems better (NFC) (#4228) 2022-05-14 15:31:06 -07:00
Peter Johnson
9af389b200 [wpinet] AddrToName: Initialize name (#4229) 2022-05-14 06:55:22 -07:00
Austin Shalit
2ae4adf2d7 [ci] Add wpiformat command to PRs (#4223) 2022-05-11 22:06:11 -07:00
sciencewhiz
178b2a1e88 Contributing.md: Correct version of clang-format used (#4222) 2022-05-10 23:48:08 -07:00
PJ Reiniger
18db343cdc [wpiutil, wpinet] Vendor libuv, stack walker (#4219) 2022-05-08 22:21:54 -07:00
Austin Shalit
f0c821282a [build] Use artifactory mirror (#4220) 2022-05-08 13:59:58 -07:00
Peter Johnson
d673ead481 [wpinet] Move network portions of wpiutil into new wpinet library (#4077) 2022-05-07 10:54:14 -07:00
Tyler Veness
b33715db15 [wpimath] Add CoordinateSystem class (#4214) 2022-05-07 10:25:19 -07:00
Dustin Spicuzza
99424ad562 [sim] Allow creating a PWMSim object from a PWMMotorController (#4039) 2022-05-06 08:44:59 -07:00
Tommy Beadle
dc6f641fd2 [wpimath] PIDController: Reset position and velocity error when reset() is called. (#4064)
In addition to m_prevError and m_totalError, m_positionError and
m_velocityError need to be reset to 0 when reset() is called.
Otherwise, the next time calculate() is called, the old values will be
used as the previous error, but this is inaccurate since the caller
wanted to reset the state of the PID controller.
2022-05-06 08:44:08 -07:00
Tyler Veness
f20a20f3f1 [wpimath] Add 3D geometry classes (#4175)
Also clean up 2D geometry documentation.
2022-05-06 08:41:23 -07:00
Kaitlyn Kenwell
708a4bc3bc [wpimath] Conserve previously calculated swerve module angles when updating states for stationary ChassisSpeeds (#4208)
* Calculated swerve module states now stored in a member variable
* If ChassisSpeeds(0, 0, 0) is converted to module speeds, the
previously calculated module angle will be conserved, with forward speed
set to 0
* New tests added
2022-05-06 08:38:20 -07:00
chen perach
ef7ed21a9d [wpimath] Improve accuracy of ComputerVisionUtil.calculateDistanceToTarget() (#4215) 2022-05-06 08:36:58 -07:00
Tyler Veness
b1abf455c1 [wpimath] LTVUnicycleController: Use LUT, provide default hyperparameters (#4213) 2022-05-04 22:04:08 -07:00
Tyler Veness
d5456cf278 [wpimath] LTVDifferentialDriveController: Remove unused variable (#4212) 2022-05-04 22:03:15 -07:00
Tyler Veness
99343d40ba [command] Remove old command-based framework (#4211) 2022-05-04 22:02:53 -07:00
Tyler Veness
ee03a7ad3b Remove most 2022 deprecations (#4205)
Excludes "old" commands and SimDevice functions.
2022-05-04 20:37:27 -07:00
Tyler Veness
ce1a7d698a [wpimath] Refactor WheelVoltages inner class to a separate file (#4203) 2022-05-01 11:01:20 -07:00
Tyler Veness
87bf70fa8e [wpimath] Add LTV controllers (#4094)
This adds a unicycle controller that's a drop-in replacement for Ramsete
and a differential drive controller that controls the full pose and
outputs voltages. The main benefit is LQR-like tuning knobs using a
system model.
2022-04-30 22:54:22 -07:00
Tyler Veness
ebd2a303bf [wpimath] Remove deprecated MakeMatrix() function (#4202) 2022-04-30 22:52:05 -07:00
Peter Johnson
e28776d361 [wpimath] LinearSystemLoop: Add extern templates for common cases 2022-04-30 20:38:55 -07:00
Peter Johnson
dac1429aa9 [wpimath] LQR: Use extern template instead of Impl class 2022-04-30 20:38:55 -07:00
Peter Johnson
e767605e94 [wpimath] Add typedefs for common types
This makes complex code significantly easier to read.

frc::Vectord<Size> = Eigen::Vector<double, Size>
frc::Matrixd<Rows, Cols> = Eigen::Matrix<double, Rows, Cols>
2022-04-30 20:38:55 -07:00
Peter Johnson
97c493241f [wpimath] UnscentedKalmanFilter: Move implementation out-of-line 2022-04-30 20:38:55 -07:00
Peter Johnson
8ea90d8bc9 [wpimath] ExtendedKalmanFilter: Move implementation out-of-line 2022-04-30 20:38:55 -07:00
Peter Johnson
ae7b1851ec [wpimath] KalmanFilter: Use extern template instead of Impl class 2022-04-30 20:38:55 -07:00
Peter Johnson
e3d62c22d3 [wpimath] Add extern templates for common cases
This helps reduce compile times and memory usage.
2022-04-30 20:38:55 -07:00
Peter Johnson
7200c4951d [wpiutil] SymbolExports: Add WPILIB_IMPORTS for dllimport 2022-04-30 20:38:55 -07:00
Peter Johnson
84056c9347 [wpiutil] SymbolExports: Add EXPORT_TEMPLATE_DECLARE/DEFINE 2022-04-30 20:38:55 -07:00
Oblarg
09cf6eeecb [wpimath] ApplyDeadband: add a scale param (#3865)
Also templates it in C++ so it can work with both doubles and units.
2022-04-30 20:29:48 -07:00
Austin Shalit
03230fc842 [build,ci] Enable artifactory build cache (#4200) 2022-04-30 20:27:23 -07:00
Jason Daming
63cf3aaa3f [examples] Don't square ArcadeDrive inputs in auto (#4201) 2022-04-30 20:19:32 -07:00
Starlight220
18ff694f02 [wpimath] Add Rotation2d.fromRadians factory (#4178) 2022-04-30 00:19:29 -07:00
Tyler Veness
4f79ceedd9 [wpilibc] Add missing #include (#4198) 2022-04-30 00:07:37 -07:00
Starlight220
f7ca72fb41 [command] Rename PerpetualCommand to EndlessCommand (#4177) 2022-04-28 09:38:38 -07:00
bovlb
a06b3f0307 [hal] Correct documentation on updateNotifierAlarm (#4156)
The previous documentation suggested that `triggerTime` is the interval until the next alarm, but the implementation is that it is the absolute alarm time.
2022-04-26 21:53:30 -07:00
Tyler Veness
d926dd1610 [wpimath] Fix pose estimator performance (#4111)
Fixes #4087.
2022-04-26 18:43:59 -07:00
ysthakur
51bc893bc5 [wpiutil] CircularBuffer: Change Java package-private methods to public (#4181)
The `size`, `getFirst`, `getLast`, and `resize` methods were all package-private.

Also make `size` return an `int` instead of a `double`.
2022-04-25 14:58:12 -07:00
Tyler Veness
fbe761f7f6 [build] Increase Gradle JVM heap size (#4172)
wpimath artifact publishing was running out of heap
2022-04-24 23:13:57 -07:00
Tyler Veness
5ebe911933 [wpimath] Add DifferentialDriveAccelerationLimiter (#4091) 2022-04-24 07:21:40 -07:00
Tyler Veness
3919250da2 [wpilibj] Remove finalizers (#4158)
They were deprecated for removal in Java 18 because they're error-prone.
Prefer AutoCloseable and Cleaner instead.

https://openjdk.java.net/jeps/421
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/ref/Cleaner.html
2022-04-24 07:21:08 -07:00
ohowe
b3aee28388 [commands] Allow BooleanSupplier for Trigger operations (#4103) 2022-04-24 07:20:46 -07:00
Tyler Veness
9d20ab3024 [wpilib] Allow disabling ElevatorSim gravity (#4145)
Closes #4144.
2022-04-24 07:19:18 -07:00
Peter Johnson
aaa69f6717 [ci] Remove 32-bit Windows builds (#4078) 2022-04-24 07:18:49 -07:00
Tyler Veness
355a11a414 Update Java linters and fix new PMD errors (#4157)
PMD requires that variables only initialized in the constructor be
final. The compiler errors if those final variables aren't guaranteed to
be initialized, so extra else branches were added to ensure that.

PMD also requires that classes with only private constructors be final.
The equivalent C++ classes were finalized as well, except for
TimeInterpolatableBuffer because it doesn't expose factory functions.
2022-04-24 07:18:05 -07:00
Jason Daming
ffc69d406c [examples] Reduce suggested acceleration in Ramsete example (#4171)
This value mirrors the update to the documentation in wpilibsuite/frc-docs#1792.
2022-04-19 17:10:11 -07:00
camaj
922d50079a [wpimath] Units: fix comment in degreesToRotations (NFC) (#4159) 2022-04-13 22:32:55 -07:00
Jonah Snider
dd163b62ae [wpimath] Rotation2d: Add factory method that uses rotations (#4166)
Rotation2d.fromRotations(1).equals(new Rotation2d(2 * Math.PI)); // true

Also adds a member method to get the value of the Rotation2d in rotations.
2022-04-13 22:31:43 -07:00
Tyler Veness
bd80e220b9 [ci] Upgrade CMake actions (#4161) 2022-04-12 19:00:00 -07:00
Tyler Veness
aef4b16d4c [wpimath] Remove unnecessary NOLINT in LinearPlantInversionFeedforward (NFC) (#4155) 2022-04-08 21:31:42 -07:00
Spud
975171609e [wpilib] Compressor: Rename enabled to isEnabled (#4147)
This is a less confusing name, as enabled() can imply it enables the compressor.
2022-04-08 21:31:08 -07:00
Tyler Veness
5bf46a9093 [wpimath] Add ComputerVisionUtil (#4124)
Closes #4108.
2022-04-08 21:20:53 -07:00
ohowe
f27a1f9bfb [commands] Fix JoystickButton.getAsBoolean (#4131)
This previously always returned false; the get method it inherited was not used in the getAsBoolean defined in the Trigger class. The fix is to swap get() and getAsBoolean() implementations in the Trigger class.
2022-04-08 21:20:23 -07:00
Excalibur FRC | 6738
1b26e2d5da [commands] Add RepeatCommand (#4009)
Co-authored-by: Starlight220 <53231611+Starlight220@users.noreply.github.com>
2022-04-07 22:02:08 -07:00
apple
88222daa3d [hal] Fix misspelling in AnalogInput/Output docs (NFC) (#4153)
value -> valid
(NFC)
2022-04-07 21:57:01 -07:00
Tyler Veness
81c5b41ce1 [wpilibj] Document MechanismLigament2d angle unit (NFC) (#4142) 2022-03-31 00:29:44 -07:00
Peter Johnson
9650e6733e [wpiutil] DataLog: Document finish and thread safety (NFC) (#4140) 2022-03-29 12:28:59 -07:00
Tyler Veness
c8905ec29a [wpimath] Remove ImplicitModelFollower dt argument (#4119)
The math works just fine without model discretization.
2022-03-29 11:29:06 -07:00
Tyler Veness
b4620f01f9 [wpimath] Fix Rotation2d interpolation in Java (#4125)
Fixes #4112.
2022-03-29 08:42:43 -07:00
Tyler Veness
2e462a19d3 [wpimath] Constexprify units unary operators (#4138)
Fixes #4137.
2022-03-29 08:42:08 -07:00
Peter Johnson
069f932e59 [build] Fix gl3w cmake build (#4139) 2022-03-28 22:31:51 -07:00
Tyler Veness
126e3de91a [wpilibc] Remove unused SetPriority() call from Ultrasonic (#4123) 2022-03-24 07:24:12 -07:00
Tyler Veness
ba0dccaae4 [wpimath] Fix reference to Rotation2d.fromRadians() (#4118)
Rotation2d.fromRadians() doesn't exist. The constructor should be used
instead.
2022-03-20 21:57:03 -07:00
sciencewhiz
e1b6e5f212 [wpilib] Improve MotorSafety documentation (NFC) (#4120)
Remove OBE RobotDrive porting guide from MecanumDrive
2022-03-20 21:54:43 -07:00
Tyler Veness
8d79dc8738 [wpimath] Add ImplicitModelFollower (#4056) 2022-03-20 00:36:12 -07:00
Tyler Veness
78108c2aba [wpimath] Fix PIDController having incorrect error after calling SetSetpoint() (#4070) 2022-03-19 23:59:00 -07:00
Tyler Veness
cdafc723fb [examples] Remove unused LinearPlantInversionFeedforward includes (#4069) 2022-03-19 20:47:09 -07:00
Ashray._.g
0d70884dce [wpimath] Add InterpolatedTreeMap (#4073)
- Add InterpolatedTreeMap for Java from team 254's 2016 MIT licensed code
- Add InterpolatedMap for C++ from team 3512's code with @calcmogul (original author) permission

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2022-03-19 20:46:42 -07:00
Tyler Veness
765efa325e [wpimath] Remove redundant column index from vectors (#4116) 2022-03-19 20:44:14 -07:00
Tyler Veness
89ffcbbe41 [wpimath] Update TrapezoidProfile class name in comment (NFC) (#4107) 2022-03-19 20:41:53 -07:00
Tyler Veness
95ae23b0e7 [wpimath] Improve EKF numerical stability (#4093)
The Joseph form of the error covariance update equation is more
numerically stable when the Kalman gain isn't optimal. Numerical
instability and filter divergence can occur if the user goes long time
periods between updates and the error covariance becomes ill-conditioned
(the ratio between the largest and smallest eigenvalue gets too large).
2022-03-19 20:41:28 -07:00
Tyler Veness
d5cb6fed67 [wpimath] Support zero cost entries in MakeCostMatrix() (#4100)
The existing implementation will produce a cost of NaN if a tolerance of
infinity is entered, but the limit approaches zero. Being able to
specify that a state has no cost is useful, so this change adds support for
that.
2022-03-19 20:40:26 -07:00
Tyler Veness
d0fef18378 [wpimath] Remove redundant this. from ExtendedKalmanFilter.java (#4115) 2022-03-19 20:39:10 -07:00
Tyler Veness
d640c0f41f [wpimath] Fix pose estimator local measurement standard deviation docs (NFC) (#4113) 2022-03-19 20:38:32 -07:00
Dustin Spicuzza
a2fa5e3ff7 [wpilibc] BatterySim: Provide non-initializer list versions of Calculate (#4076) 2022-03-14 10:09:55 -07:00
sciencewhiz
a3eea9958e [hal] Add link to FRC CAN Spec (NFC) (#4086) 2022-03-14 10:07:44 -07:00
Tyler Veness
db27331d7b [wpilib] Update DifferentialDrive docs (NFC) (#4085)
Fixes #4084.
2022-03-14 10:07:06 -07:00
Peter Johnson
fdfb31f164 [dlt] Export boolean[] values (#4082) 2022-03-14 10:05:50 -07:00
Dustin Spicuzza
f93c3331b3 [wpigui] disable changing directory when initializing on MacOS (#4092)
- Seems to be intended for resource bundles in MacOS apps, which we don't use
2022-03-14 10:05:22 -07:00
Thad House
ab7ac4fbb9 [build] Fix various warnings in cmake builds (#4081) 2022-03-07 22:36:42 -08:00
Thad House
bc39a1a293 [wpilibc] Fix moved pneumatics objects not destructing properly (#4068) 2022-03-01 11:10:45 -08:00
Tyler Veness
2668130e70 [wpimath] Remove SwerveDrivePoseEstimator encoder reset warning (#4066)
SwerveDrivePoseEstimator uses velocities, so position resets aren't
needed.

Closes #4065.
2022-02-28 17:40:25 -08:00
Austin Shalit
d27ed3722b [ci] Set actions workflow concurrency (#4060)
This sets the workflow concurrency to 1 for all workflows. For PRs this means if you push an additional commit older jobs will be cancelled.

The documentation workflow already only runs on tags or merges to main. For this, we cancel previous runs if they are to the same destination (tag or main) but still prevent 2 jobs from running at once if they are spawned from different refs.
2022-02-27 20:13:58 -08:00
shueja-personal
dae18308c9 [wpimath] Minor fixes to Rotation2d docs (NFC) (#4055)
Fixed incorrect examples on .plus(), and a missing word.

Make example code snippets closer to actual use.
2022-02-27 16:56:56 -08:00
Peter Johnson
d66555e42f [datalogtool] Add datalogtool
This is a support tool for datalog file conversion (and eventually
download/remote datalog file management).
2022-02-26 09:49:34 -08:00
Peter Johnson
9f52d8a3b1 [wpilib] DriverStation: Add DataLog support for modes and joystick data 2022-02-26 09:49:34 -08:00
Peter Johnson
757ea91932 [wpilib] Add DataLogManager
This creates a default log file that captures NT changes and
automatically renames the log file based on time and match info.

DriverStation joystick logging will be implemented by the DriverStation
class instead.
2022-02-26 09:49:34 -08:00
Peter Johnson
02a804f1c5 [ntcore] Add DataLog support 2022-02-26 09:49:34 -08:00
Peter Johnson
9b500df0d9 [wpiutil] Add high speed data logging 2022-02-26 09:49:34 -08:00
Peter Johnson
5a89575b3a [wpiutil] Import customized LLVM MemoryBuffer 2022-02-26 09:49:34 -08:00
Peter Johnson
b8c4d7527b [wpiutil] Add MappedFileRegion 2022-02-26 09:49:34 -08:00
Alberto Jahuey Moncada
ac5d46cfa7 [wpilibc] Fix ProfiledPID SetTolerance default velocity value (#4054)
When trying to set the tolerance of a ProfiledPID, it fails if you don't give it a velocity value. It was missing a conversion from double to the appropiate unit.
2022-02-25 20:27:56 -08:00
Thad House
bc9e96e86f [wpilib] Absolute Encoder API and behavior fixes (#4052)
SetPositionOffset was added. Been requested multiple times, and easy to implement.

The javadocs mentioned GetPositionInRotation. It has tripped up many people how to get the absolute position from the encoder (You currently have to have precreated the DutyCycle object). Add this method (as GetAbsolutePostition) to make this easier to do.

The checks for making sure a matching set of values was read was doing direct double comparisions. This worked ok in the DutyCycle case, but has problems in the analog case. Solve this by using an epsilon comparison.

And finally, scale AnalogEncoders analog input to 0-1 instead of 0-5. This was reported a few years ago, but the issue was missed. This caused the encoder to count from 0-5, then 1-6, then 2-7 etc. This is solved and now works correctly.

Closes #3188
Closes #4046
Closes #4051

And fixes the following issue on CD
https://www.chiefdelphi.com/t/wpilib-analogencoder-java/372649
2022-02-24 22:45:15 -08:00
Dustin Spicuzza
f88c435dd0 [hal] Add mechanism to cancel all periodic callbacks (#4049) 2022-02-23 09:46:01 -08:00
Leonard Abbas
e4b91005cf [examples] Update SwerveModule constructor doc (NFC) (#4042)
Renamed "port" to "channel" for consistency.
2022-02-22 09:26:16 -08:00
Leonard Abbas
a260bfd83b [examples] Remove "this" keyword from SwerveModule (#4043) 2022-02-21 09:27:00 -08:00
Leonard Abbas
18e262a100 [examples] Fix multiple doc typos in SwerveControllerCommand example (NFC) (#4044) 2022-02-21 09:26:20 -08:00
Dustin Spicuzza
4bd1f526ab [wpilibc] Prevent StopMotor from terminating robot during MotorSafety check (#4038)
- Nothing else in that function can throw, so protecting StopMotor should be sufficient
- Fixes #4036
2022-02-19 20:42:10 -08:00
Dustin Spicuzza
27847d7eb2 [sim] Expose GUI control functions via HAL_RegisterExtension (#4034) 2022-02-19 20:40:25 -08:00
Dustin Spicuzza
b2a8d3f0f3 [wpilibc] Add mechanism to reset MotorSafety list (#4037) 2022-02-19 20:38:30 -08:00
Tyler Veness
49adac9564 [wpilib] Check for signedness in ArcadeDriveIK() (#4028)
If xSpeed == -0.0 and zRotation > 0, the algorithm assumes it's in the
third quadrant instead of the first since +0.0 == -0.0.

Also added tests for inverse kinematic functions, fixed some
MecanumDrive test bugs, and added Java MecanumDrive.driveCartesianIK()
and KilloughDrive.driveCartesianIK() overloads with defaulted gyro angle
that C++ already had.

Fixes #4022.
2022-02-17 18:03:59 -08:00
Peter Johnson
a19d1133b1 [wpiutil] libuv: Fix sign compare warnings in gcc 11.2 (#4031) 2022-02-13 16:56:53 -08:00
Peter Johnson
dde91717e4 [build] cmake: Add ability to customize target warnings (#4032) 2022-02-13 16:53:55 -08:00
Peter Johnson
e9050afd67 [sim] Update sim match time to match real robot (#4024)
The real robot has match time set to -1.0 until it's enabled, and then
counts down. Disabling the robot sets the time to -1.0.

The sim GUI has been updated to add preset buttons for auto and teleop
match times. The enable match timing checkbox has been removed as it's
no longer required.

The DS socket plugin has also been fixed to properly initialize
matchTime to -1.0 and reset it to -1.0 on disable.
2022-02-12 22:31:10 -08:00
sciencewhiz
165d2837cf [wpilib] Preferences: Set Persistent in Init methods (#4025)
Fixes #4018
2022-02-12 22:30:02 -08:00
Peter Johnson
ac7549edca [glass] Fix snprintf truncation warning (#4029) 2022-02-12 22:29:26 -08:00
Jonah Snider
4d96bc72e0 [wpilibj] Fix typos in error messages for non-null assertions (#4014) 2022-02-11 18:11:15 -08:00
Dustin Spicuzza
3411eee20f [hal] Replace hardcoded sim array sizes with constants (#4015) 2022-02-10 00:12:07 -08:00
Dustin Spicuzza
74de97eeca [wpilibc] Add mechanism to reset various global structures (#4007) 2022-02-09 22:14:12 -08:00
sciencewhiz
4e3cc25012 [examples] Fix periodic function rate comment (NFC) (#4013)
Fixes #3979
2022-02-08 13:19:31 -08:00
Dustin Spicuzza
90c1db393e [sim] Add exported functions to control the sim GUI (#3995) 2022-02-07 00:39:45 -08:00
sciencewhiz
2f43274aa4 [wpilibj] MechanismRoot2d: Add flush to setPosition (#4011)
Fixes #4010.
2022-02-06 22:47:33 -08:00
Peter Johnson
aeca09db09 [glass] Support remapping of Enter key (#3994)
This is useful for editing of values without disabling the DS.
2022-02-06 00:11:37 -08:00
Peter Johnson
c107f22c67 [sim] Sim GUI: don't force-show Timing and Other Devices (#4001)
Instead preserve their saved visible state.
2022-02-06 00:11:12 -08:00
Peter Johnson
68fe51e8da [wpigui] Update PFD to latest, fix kdialog multiselect (#4005) 2022-02-06 00:10:43 -08:00
modelmat
8d08d67cf1 [wpigui] PFD: Add console warning if file chooser unavailable (#4003)
Also remove iostream use.
2022-02-06 00:10:20 -08:00
Dustin Spicuzza
4f1782f66e [wpilibc] Only call HAL_Report when initializing SmartDashboard (#4006) 2022-02-06 00:07:55 -08:00
Tyler Veness
3f77725cd3 Remove uses of iostream (#4004)
Most of these were unused, the IMU ones were just debug messages.

The only one that wasn't removed is in portable-file-dialogs.cpp since
the replacement looks less trivial.
2022-02-05 23:00:31 -08:00
Peter Johnson
5635f33a32 [glass] Increase plot depth to 20K points (#3993)
2K was sufficient for simulation because it's possible to pause time,
but isn't quite enough for looking at real robot data. 20K points
is 400 seconds at 50 Hz which should make pausing plots much more
useful.

As every point is looped over, this does increase CPU utilization
somewhat but doesn't seem to have much of an impact for typical
use cases. Increasing this further will necessitate some greater
optimizations (e.g. an initial cull using binary search).
2022-02-04 22:20:38 -08:00
Peter Johnson
bca4b7111b [glass] Fix PlotSeries::SetSource() (#3991)
This can be called in a delayed manner, so it's possible for
m_size to already be at maximum, which results in writing past
the end of the array. Instead, just call AppendValue().
2022-02-04 20:47:11 -08:00
Oblarg
6a6366b0d6 [commands] Add until() as alias for withInterrupt() (#3981)
This is a clearer description for the functionality.
Will deprecate withInterrupt next year.
2022-02-03 22:14:52 -08:00
Thad House
16bf2c70c5 [wpilib] Fix joystick out of range error messages (#3988) 2022-02-03 22:10:44 -08:00
Thad House
4b3edb742c [wpilib] Fix ADIS16448 IMU default constructor not working in Java (#3989)
Also fixes a few related uninitialized variables in C++.
2022-02-03 22:09:12 -08:00
Thad House
fcf23fc9e9 [hal] Fix potential gamedata out of bounds read (#3983)
The size was uninitialized.  If the size is smaller than the data,
NetComm just updates the size and does not initialize the data.
2022-02-01 22:22:48 -08:00
Jan-Felix Abellera
af5ef510c5 [wpilibc] Fix REV PH pulse duration units (#3982) 2022-02-01 20:28:48 -08:00
Jan-Felix Abellera
05401e2b81 [wpilib] Write REV PH firmware version to roboRIO to display on driver station (#3977) 2022-02-01 20:27:43 -08:00
Thad House
9fde0110b6 Update to 2022 v4.0 image (#3944) 2022-01-31 23:26:05 -08:00
sciencewhiz
b03f8ddb2e [examples] fix incorrect variable in Arm Simulation Pref (#3980) 2022-01-31 22:01:31 -08:00
sciencewhiz
a26df2a022 [examples] Update ArmSimulation example to use Preferences (#3976)
This shows more real world usage then hardcoding the setpoint and PID
gains. There were no current examples using Preferences. This will also
be used to update frc-docs article for Preferences.
2022-01-31 00:17:04 -08:00
Oblarg
d68d6674e8 [examples] Armbot: rename kCos to kG (#3975) 2022-01-31 00:16:26 -08:00
sciencewhiz
a8f0f6bb90 [wpilibj] Fix ADIS16448 getRate to return rate instead of angle (#3974) 2022-01-29 20:17:57 -08:00
Thad House
dd9c92d5bf [build] Remove debug info from examples (#3971)
They take up a LOT of disk space.
2022-01-27 20:59:13 -08:00
Thad House
84df14dd70 [rtns] Fix icons (#3972) 2022-01-27 20:58:07 -08:00
sciencewhiz
560094ad92 [examples] Correct Mecanum example axes (#3955) 2022-01-27 20:57:41 -08:00
Jan-Felix Abellera
7ea1be9c01 [wpilibc] Fix typo in hardware version for REV PDH (#3969) 2022-01-27 17:54:38 -08:00
Jan-Felix Abellera
700f13bffd [wpilibj] Make methods public for Java REV PDH (#3970) 2022-01-27 17:54:14 -08:00
Jan-Felix Abellera
b6aa7c1aa9 [wpilibj] Make methods public for Java REVPH (#3968) 2022-01-27 17:53:45 -08:00
Tyler Veness
eb4d183e48 [wpimath] Fix clang-tidy bugprone-integer-division warning (#3966)
The integer conversion is deliberate.
2022-01-26 18:38:45 -08:00
Thad House
77e4e81e1e [wpilib] Add Field widget to BuiltInWidgets in shuffleboard (#3961) 2022-01-24 20:33:11 -08:00
Thad House
88f5cb6eb0 [build] Publish PDBs with C++ tools (#3960) 2022-01-24 20:32:17 -08:00
Tyler Veness
efae552f3e [wpimath] Remove DifferentialDriveKinematics include from odometry (#3958) 2022-01-24 16:02:00 -08:00
sciencewhiz
46b277421a [glass] Update Speed Controller Type name for 2022 WPILib (#3952) 2022-01-21 21:30:44 -08:00
modelmat
42908126b9 [wpilib] Add DCMotorSim (#3910) 2022-01-21 20:42:06 -08:00
Peter Johnson
a467392cbd [wpiutil] StackTrace: Add ability to override default implementation (#3951) 2022-01-21 17:22:41 -08:00
modelmat
78d0bcf49d [templates] Add SimulationInit()/SimulationPeriodic() to robot templates (#3943) 2022-01-21 16:23:46 -08:00
sciencewhiz
02a0ced9b0 [wpilib] MecanumDrive: update docs for axis to match implementation (NFC) (#3942)
Added note that implementation may change in the future, #3930.
2022-01-21 16:22:17 -08:00
shueja-personal
4ccfe1c9f2 [wpilib] Added docs clarification on units for drive class WheelSpeeds (NFC) (#3939) 2022-01-21 15:51:28 -08:00
Peter Johnson
830c0c5c2f [wpilib] MechanismLigament2d: Add getters for color and line weight (#3947)
Also add missing locking in C++.
2022-01-21 15:47:44 -08:00
Peter Johnson
5548a37465 [wpilib] PowerDistribution: Add module type getter (#3948) 2022-01-21 15:46:44 -08:00
Thad House
2f9a600de2 [hal] Fix PCM one shot (#3949) 2022-01-21 15:46:08 -08:00
Thad House
559db11a20 [myRobot] Skip deploying debug libraries for myRobot deploys (#3950) 2022-01-21 15:45:47 -08:00
Lenny Abbas
76c78e295b [examples] Reorder SwerveModules in SwerveControllerCommand example odometry update (#3934) 2022-01-21 11:04:43 -08:00
sciencewhiz
debbd5ff4b [wpilib] Improve PowerDistribution docs (NFC) (#3925)
Add docs for switchable channel.
Use PDP/PDH appropriately and clarify differences.
Fix typos.
2022-01-20 23:33:01 -08:00
Tyler Veness
841174f302 [commands] Change command vendordep JSON version number to 1.0.0 (#3938)
While the number doesn't matter, it being old is confusing a lot of
people.  We never increment the internal vendordep versions, so using a year
version number was a poor choice.

Closes #3921.
2022-01-20 23:32:02 -08:00
sciencewhiz
8c55844f91 [wpilib] Remove comment about Mecanum right side inverted (NFC) (#3929) 2022-01-18 01:00:55 -08:00
Thad House
0b990bf0f5 [hal] Fix PCM sticky faults clear function crashing (#3932)
A call to the PCM clear function was using the wrong handle passed down to the CAN layer, causing an error.
2022-01-18 00:59:51 -08:00
Thad House
104d7e2abc [hal] Don't throw exceptions in PCM JNI (#3933)
Since the CAN bus can easily become disconnected, we don't want this to crash. Instead, we just want this to report errors. This matches previous behavior.
2022-01-18 00:58:26 -08:00
Lenny Abbas
5ba69e1af1 [examples] Updated type in Java SwerveModule (#3928)
Changed turnOutput from var to double in SwerveModule. It doesn't make sense for driveOutput and turnOutput to have different types so they should both be doubles.
2022-01-17 12:20:55 -08:00
Chirag Kaushik
f3a0b5c7d7 [wpimath] Fix Java SimpleMotorFeedforward Docs (NFC) (#3926) 2022-01-17 09:59:04 -08:00
1247 changed files with 58706 additions and 28441 deletions

View File

@@ -2,6 +2,10 @@ name: CMake
on: [pull_request, push]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
@@ -16,50 +20,64 @@ jobs:
name: macOS
container: ""
flags: "-DWITH_JAVA=OFF"
name: "Build - ${{ 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
- 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 . -j$(nproc)
run: cmake --build . --parallel $(nproc)
- name: test
working-directory: build
run: ctest --output-on-failure
build-vcpkg:
build-windows:
env:
VCPKG_DEFAULT_TRIPLET: x64-windows
name: "Build - Windows"
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Prepare vcpkg
uses: lukka/run-vcpkg@v7
- uses: actions/checkout@v3
- name: Install CMake
uses: lukka/get-cmake@v3.23.0
- name: Run vcpkg
uses: lukka/run-vcpkg@v10.2
with:
vcpkgArguments: opencv
vcpkgDirectory: ${{ runner.workspace }}/vcpkg
vcpkgTriplet: x64-windows
vcpkgGitCommitId: d781bd9ca77ac3dc2f13d88169021d48459c665f # HEAD on 2021-07-25
- name: Configure & Build
uses: lukka/run-cmake@v3
with:
buildDirectory: ${{ runner.workspace }}/build
cmakeAppendedArgs: -DWITH_JAVA=OFF
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
useVcpkgToolchainFile: true
- name: Run Tests
vcpkgGitCommitId: f6af75acc923c833a5620943e3fc7d5e4930f0df # HEAD on 2022-04-10
runVcpkgInstall: true
- name: Install jinja
run: python -m pip install jinja2
- name: configure
run: mkdir build && cd build && cmake -DWITH_JAVA=OFF -DCMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake ..
- name: build
working-directory: build
run: cmake --build . --parallel $(nproc)
- name: test
working-directory: build
run: ctest -C "Debug" --output-on-failure
working-directory: ${{ runner.workspace }}/build

54
.github/workflows/comment-command.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
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
- 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.GITHUB_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: |
sudo sh -c "echo 'deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -cs)-proposed restricted main multiverse universe' >> /etc/apt/sources.list.d/proposed-repositories.list"
sudo apt-get update -q
sudo apt-get install -y clang-format-12
- name: Install wpiformat
run: pip3 install wpiformat
- name: Run wpiformat
run: wpiformat -clang 12
- 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

View File

@@ -2,6 +2,10 @@ name: Documentation
on: [push, workflow_dispatch]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
BASE_PATH: allwpilib/docs
@@ -10,8 +14,9 @@ jobs:
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@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
persist-credentials: false

View File

@@ -2,13 +2,17 @@ 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:18.04
container: wpilib/gazebo-ubuntu:20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Build with Gradle

View File

@@ -1,10 +1,14 @@
name: "Validate Gradle Wrapper"
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

View File

@@ -2,36 +2,43 @@ 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-18.04
- container: wpilib/roborio-cross-ubuntu:2022-20.04
artifact-name: Athena
build-options: "-Ponlylinuxathena"
- container: wpilib/raspbian-cross-ubuntu:10-18.04
- container: wpilib/raspbian-cross-ubuntu:10-20.04
artifact-name: Raspbian
build-options: "-Ponlylinuxraspbian"
- container: wpilib/aarch64-cross-ubuntu:bionic-18.04
- container: wpilib/aarch64-cross-ubuntu:bionic-20.04
artifact-name: Aarch64
build-options: "-Ponlylinuxaarch64bionic"
- container: wpilib/ubuntu-base:18.04
- container: wpilib/ubuntu-base:20.04
artifact-name: Linux
build-options: "-Dorg.gradle.jvmargs=-Xmx2g"
build-options: "-Ponlylinuxx86-64"
name: "Build - ${{ matrix.artifact-name }}"
runs-on: ubuntu-latest
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v2
- 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 -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
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 }}
@@ -47,16 +54,13 @@ jobs:
- os: windows-2019
artifact-name: Win64
architecture: x64
- os: windows-2019
artifact-name: Win32
architecture: x86
- os: macOS-11
artifact-name: macOS
architecture: x64
name: "Build - ${{ matrix.artifact-name }}"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v1
@@ -82,7 +86,10 @@ jobs:
shell: bash
if: startsWith(github.ref, 'refs/tags/v')
- name: Build with Gradle
run: ./gradlew build -PbuildServer -PskipJavaFormat ${{ env.EXTRA_GRADLE_ARGS }}
run: ./gradlew build --build-cache -PbuildServer -PskipJavaFormat ${{ 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 }} ${{ env.EXTRA_GRADLE_ARGS }}
if: |
@@ -97,7 +104,7 @@ jobs:
name: "Build - Documentation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v1
@@ -109,7 +116,10 @@ jobs:
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 }}
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
@@ -120,7 +130,7 @@ jobs:
needs: [build-docker, build-host, build-documentation]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
repository: wpilibsuite/build-tools
- uses: actions/download-artifact@v2

View File

@@ -6,15 +6,19 @@ on:
branches-ignore:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
wpiformat:
name: "wpiformat"
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-20.04
steps:
- uses: actions/checkout@v2
- 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
@@ -46,9 +50,10 @@ jobs:
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-20.04
steps:
- uses: actions/checkout@v2
- 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
@@ -72,11 +77,15 @@ jobs:
javaformat:
name: "Java format"
runs-on: ubuntu-latest
container: wpilib/ubuntu-base:18.04
container: wpilib/ubuntu-base:20.04
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- 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
@@ -88,7 +97,7 @@ jobs:
name: "Documentation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-java@v1

View File

@@ -2,6 +2,10 @@ name: Sanitizers
on: [pull_request, push]
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
@@ -11,7 +15,7 @@ jobs:
- name: asan
cmake-flags: "-DCMAKE_BUILD_TYPE=Asan"
ctest-env: ""
ctest-flags: "-E 'wpiutil|ntcore|wpilibc'"
ctest-flags: "-E 'wpinet|wpiutil|ntcore|wpilibc'"
- name: tsan
cmake-flags: "-DCMAKE_BUILD_TYPE=Tsan"
ctest-env: "TSAN_OPTIONS=second_deadlock_stack=1"
@@ -24,7 +28,8 @@ jobs:
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install Dependencies
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
@@ -33,17 +38,22 @@ jobs:
--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 . -j$(nproc)
run: cmake --build . --parallel $(nproc)
- name: test
working-directory: build
run: ${{ matrix.ctest-env }} ctest --output-on-failure ${{ matrix.ctest-flags }}

53
.github/workflows/upstream-utils.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
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_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: Check output
run: git --no-pager diff --exit-code HEAD

View File

@@ -44,4 +44,5 @@ includeOtherLibs {
^wpi/
^wpigui
^wpimath/
^wpinet/
}

View File

@@ -54,7 +54,6 @@ option(WITH_JAVA "Include java and JNI in the build" ON)
option(WITH_CSCORE "Build cscore (needs OpenCV)" ON)
option(WITH_WPIMATH "Build wpimath" ON)
option(WITH_WPILIB "Build hal, wpilibc/j, and myRobot (needs OpenCV)" ON)
option(WITH_OLD_COMMANDS "Build old commands" OFF)
option(WITH_EXAMPLES "Build examples" OFF)
option(WITH_TESTS "Build unit tests (requires internet connection)" ON)
option(WITH_GUI "Build GUI items" ON)
@@ -149,6 +148,7 @@ 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)")
@@ -156,9 +156,9 @@ 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)")
set(WPILIBOLDCOMMANDS_DEP_REPLACE "include(\${SELF_DIR}/wpilibOldcommands-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)")
@@ -166,7 +166,6 @@ 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)")
set(WPILIBOLDCOMMANDS_DEP_REPLACE "find_dependency(wpilibOldCommands)")
endif()
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
@@ -248,6 +247,7 @@ if (WITH_TESTS)
endif()
add_subdirectory(wpiutil)
add_subdirectory(wpinet)
add_subdirectory(ntcore)
if (WITH_WPIMATH)
@@ -262,6 +262,7 @@ if (WITH_GUI)
add_subdirectory(outlineviewer)
if (LIBSSH_FOUND)
add_subdirectory(roborioteamnumbersetter)
add_subdirectory(datalogtool)
endif()
endif()
@@ -282,9 +283,6 @@ if (WITH_WPILIB)
add_subdirectory(wpilibj)
add_subdirectory(wpilibc)
add_subdirectory(wpilibNewCommands)
if (WITH_OLD_COMMANDS)
add_subdirectory(wpilibOldCommands)
endif()
if (WITH_EXAMPLES)
add_subdirectory(wpilibcExamples)
endif()

View File

@@ -37,7 +37,7 @@ 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 12.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.

View File

@@ -134,14 +134,6 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* wpimath
* wpiutil
* wpilibOldCommands
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
### Third Party Artifacts

View File

@@ -26,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.
@@ -79,10 +88,18 @@ If opening from a fresh clone, generated java dependencies will not exist. Most
`./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)

View File

@@ -24,9 +24,7 @@ LLVM wpiutil/src/main/native/include/wpi/{various files}
JSON for Modern C++ wpiutil/src/main/native/include/wpi/json.h
wpiutil/src/main/native/cpp/json_*.cpp
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/
libuv wpinet/src/main/native/thirdparty/libuv/
fmtlib wpiutil/src/main/native/fmtlib/
sigslot wpiutil/src/main/native/include/wpi/Signal.h
wpiutil/src/test/native/cpp/sigslot/
@@ -34,11 +32,11 @@ tcpsockets wpiutil/src/main/native/cpp/TCP{Stream,Connector,Acceptor}
wpiutil/src/main/native/include/wpi/TCP*.h
MPack wpiutil/src/main/native/include/mpack.h
wpiutil/src/main/native/cpp/mpack.cpp
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-*
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/
@@ -54,7 +52,7 @@ Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineP
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
V8 export-template wpiutil/src/main/native/include/wpi/SymbolExports.h
==============================================================================
Google Test License
@@ -90,12 +88,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:
@@ -969,3 +1202,33 @@ 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.

View File

@@ -2,7 +2,9 @@ import edu.wpi.first.toolchain.*
buildscript {
repositories {
mavenCentral()
maven {
url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn'
}
}
dependencies {
classpath 'com.hubspot.jinjava:jinjava:2.6.0'
@@ -20,8 +22,8 @@ plugins {
id 'visual-studio'
id 'net.ltgt.errorprone' version '2.0.2' apply false
id 'com.github.johnrengelman.shadow' version '7.1.2' apply false
id 'com.diffplug.spotless' version '6.1.2' apply false
id 'com.github.spotbugs' version '5.0.4' apply false
id 'com.diffplug.spotless' version '6.4.2' apply false
id 'com.github.spotbugs' version '5.0.6' apply false
}
wpilibVersioning.buildServerMode = project.hasProperty('buildServer')
@@ -29,7 +31,9 @@ wpilibVersioning.releaseMode = project.hasProperty('releaseMode')
allprojects {
repositories {
mavenCentral()
maven {
url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn'
}
}
if (project.hasProperty('releaseMode')) {
wpilibRepositories.addAllReleaseRepositories(it)

View File

@@ -5,5 +5,5 @@ repositories {
}
}
dependencies {
implementation "edu.wpi.first:native-utils:2022.7.1"
implementation "edu.wpi.first:native-utils:2023.0.1"
}

View File

@@ -11,9 +11,11 @@ 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')
}
@@ -32,19 +34,6 @@ 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',
@@ -70,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'
}
}

View File

@@ -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.9'
implementation project(':wpiutil')
implementation project(':wpinet')
implementation project(':ntcore')
implementation project(':cscore')
implementation project(':cameraserver')
@@ -55,6 +58,7 @@ model {
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'
}
}

View File

@@ -37,27 +37,9 @@ import java.util.concurrent.atomic.AtomicInteger;
public final class CameraServer {
public static final int kBasePort = 1181;
@Deprecated public static final int kSize640x480 = 0;
@Deprecated public static final int kSize320x240 = 1;
@Deprecated public static final int kSize160x120 = 2;
private static final String kPublishName = "/CameraPublisher";
private static CameraServer server;
/**
* Get the CameraServer instance.
*
* @return The CameraServer instance.
* @deprecated Use the static methods
*/
@Deprecated
public static synchronized CameraServer getInstance() {
if (server == null) {
server = new CameraServer();
}
return server;
}
private static final AtomicInteger m_defaultUsbDevice = new AtomicInteger();
private static String m_primarySourceName;
private static final Map<String, VideoSource> m_sources = new HashMap<>();

View File

@@ -9,7 +9,7 @@
* <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&lt;MyFindTotePipeline&gt; {
*
* // A USB camera connected to the roboRIO.

View File

@@ -52,12 +52,6 @@ static Instance& GetInstance() {
return instance;
}
CameraServer* CameraServer::GetInstance() {
::GetInstance();
static CameraServer instance;
return &instance;
}
static std::string_view MakeSourceValue(CS_Source source,
wpi::SmallVectorImpl<char>& buf) {
CS_Status status = 0;

View File

@@ -9,7 +9,6 @@
#include <string>
#include <string_view>
#include <wpi/deprecated.h>
#include <wpi/span.h>
#include "cscore.h"
@@ -29,13 +28,6 @@ class CameraServer {
static constexpr int kSize320x240 = 1;
static constexpr int kSize160x120 = 2;
/**
* Get the CameraServer instance.
* @deprecated Use the static methods
*/
WPI_DEPRECATED("Use static methods")
static CameraServer* GetInstance();
/**
* Start automatically capturing images to send to the dashboard.
*

View File

@@ -1,7 +1,7 @@
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 /wd4146 /wd4244 /wd4251 /wd4267 /wd4996 /WX)
target_compile_options(${target} PRIVATE /wd4146 /wd4244 /wd4251 /wd4267 /WX /D_CRT_SECURE_NO_WARNINGS ${WPILIB_TARGET_WARNINGS})
endif()
endmacro()

View File

@@ -110,7 +110,7 @@ else()
set(LIBSSH_LIBRARIES ${LIBSSH_LIBRARY} ${LIBSSH_THREADS_LIBRARY})
mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES)
find_package_handle_standard_args(LibSSH FOUND_VAR LIBSSH_FOUND
find_package_handle_standard_args(LIBSSH FOUND_VAR LIBSSH_FOUND
REQUIRED_VARS LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES
VERSION_VAR LIBSSH_VERSION)
endif()

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.3.0)
# load settings in case of "try compile"
set(TOOLCHAIN_CONFIG_FILE "${WPILIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")

View File

@@ -84,13 +84,9 @@ model {
}
}
}
binary.tasks.withType(CppCompile) {
cppCompiler.args "-Wno-missing-field-initializers"
cppCompiler.args "-Wno-unused-variable"
cppCompiler.args "-Wno-error=deprecated-declarations"
}
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')

View File

@@ -12,7 +12,7 @@
#include <hal/cpp/fpga_clock.h>
#include <wpi/Logger.h>
#include <wpi/SmallVector.h>
#include <wpi/UDPClient.h>
#include <wpinet/UDPClient.h>
static void LoggerFunc(unsigned int level, const char* file, unsigned int line,
const char* msg) {

View File

@@ -194,6 +194,7 @@ struct RelayHandle {
do { \
ASSERT_EQ(status, HAL_USE_LAST_ERROR); \
const char* lastErrorMessageInMacro = HAL_GetLastError(&status); \
static_cast<void>(lastErrorMessageInMacro); \
ASSERT_EQ(status, x); \
} while (0)

View File

@@ -36,4 +36,5 @@ includeOtherLibs {
^support/
^tcpsockets/
^wpi/
^wpinet/
}

View File

@@ -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")

View File

@@ -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,6 +56,15 @@ model {
}
}
}
binaries {
all {
if (!it.buildable || !(it instanceof NativeBinarySpec)) {
return
}
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
}
}
}
@@ -144,19 +154,6 @@ Action<List<String>> symbolFilter = { symbols ->
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',
@@ -172,11 +169,9 @@ nativeUtils.exportsConfigs {
]
}
cscoreJNI {
x86SymbolFilter = symbolFilter
x64SymbolFilter = symbolFilter
}
cscoreJNICvStatic {
x86SymbolFilter = symbolFilter
x64SymbolFilter = symbolFilter
}
}
@@ -190,6 +185,7 @@ model {
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')
@@ -220,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 {

View File

@@ -6,8 +6,8 @@
#include <wpi/MemAlloc.h>
#include <wpi/StringExtras.h>
#include <wpi/TCPConnector.h>
#include <wpi/timestamp.h>
#include <wpinet/TCPConnector.h>
#include "Handle.h"
#include "Instance.h"

View File

@@ -14,12 +14,12 @@
#include <thread>
#include <vector>
#include <wpi/HttpUtil.h>
#include <wpi/SmallString.h>
#include <wpi/StringMap.h>
#include <wpi/condition_variable.h>
#include <wpi/raw_istream.h>
#include <wpi/span.h>
#include <wpinet/HttpUtil.h>
#include "SourceImpl.h"
#include "cscore_cpp.h"

View File

@@ -8,8 +8,8 @@
#include <memory>
#include <utility>
#include <wpi/EventLoopRunner.h>
#include <wpi/Logger.h>
#include <wpinet/EventLoopRunner.h>
#include "Log.h"
#include "NetworkListener.h"

View File

@@ -7,13 +7,13 @@
#include <chrono>
#include <fmt/format.h>
#include <wpi/HttpUtil.h>
#include <wpi/SmallString.h>
#include <wpi/StringExtras.h>
#include <wpi/TCPAcceptor.h>
#include <wpi/fmt/raw_ostream.h>
#include <wpi/raw_socket_istream.h>
#include <wpi/raw_socket_ostream.h>
#include <wpinet/HttpUtil.h>
#include <wpinet/TCPAcceptor.h>
#include <wpinet/raw_socket_istream.h>
#include <wpinet/raw_socket_ostream.h>
#include "Handle.h"
#include "Instance.h"

View File

@@ -12,13 +12,13 @@
#include <thread>
#include <vector>
#include <wpi/NetworkAcceptor.h>
#include <wpi/NetworkStream.h>
#include <wpi/SafeThread.h>
#include <wpi/SmallVector.h>
#include <wpi/raw_istream.h>
#include <wpi/raw_ostream.h>
#include <wpi/raw_socket_ostream.h>
#include <wpinet/NetworkAcceptor.h>
#include <wpinet/NetworkStream.h>
#include <wpinet/raw_socket_ostream.h>
#include "SinkImpl.h"

View File

@@ -5,8 +5,8 @@
#include "cscore_cpp.h"
#include <wpi/SmallString.h>
#include <wpi/hostname.h>
#include <wpi/json.h>
#include <wpinet/hostname.h>
#include "Handle.h"
#include "Instance.h"

View File

@@ -4,10 +4,10 @@
#include "UsbCameraListener.h"
#include <wpi/EventLoopRunner.h>
#include <wpi/StringExtras.h>
#include <wpi/uv/FsEvent.h>
#include <wpi/uv/Timer.h>
#include <wpinet/EventLoopRunner.h>
#include <wpinet/uv/FsEvent.h>
#include <wpinet/uv/Timer.h>
#include "Notifier.h"

29
datalogtool/.styleguide Normal file
View File

@@ -0,0 +1,29 @@
cppHeaderFileInclude {
\.h$
\.inc$
\.inl$
}
cppSrcFileInclude {
\.cpp$
}
generatedFileExclude {
src/main/native/resources/
src/main/native/win/datalogtool.ico
src/main/native/mac/datalogtool.icns
}
repoRootNameOverride {
datalogtool
}
includeOtherLibs {
^GLFW
^fmt/
^glass/
^imgui
^portable-file-dialog
^wpi/
^wpigui
}

View File

@@ -0,0 +1,29 @@
project(datalogtool)
include(CompileWarnings)
include(GenResources)
include(LinkMacOSGUI)
configure_file(src/main/generate/WPILibVersion.cpp.in WPILibVersion.cpp)
GENERATE_RESOURCES(src/main/native/resources generated/main/cpp DLT dlt datalogtool_resources_src)
file(GLOB datalogtool_src src/main/native/cpp/*.cpp ${CMAKE_CURRENT_BINARY_DIR}/WPILibVersion.cpp)
if (WIN32)
set(datalogtool_rc src/main/native/win/datalogtool.rc)
elseif(APPLE)
set(MACOSX_BUNDLE_ICON_FILE datalogtool.icns)
set(APP_ICON_MACOSX src/main/native/mac/datalogtool.icns)
set_source_files_properties(${APP_ICON_MACOSX} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
endif()
add_executable(datalogtool ${datalogtool_src} ${datalogtool_resources_src} ${datalogtool_rc} ${APP_ICON_MACOSX})
wpilib_link_macos_gui(datalogtool)
target_link_libraries(datalogtool libglass ${LIBSSH_LIBRARIES})
target_include_directories(datalogtool PRIVATE ${LIBSSH_INCLUDE_DIRS})
if (WIN32)
set_target_properties(datalogtool PROPERTIES WIN32_EXECUTABLE YES)
elseif(APPLE)
set_target_properties(datalogtool PROPERTIES MACOSX_BUNDLE YES OUTPUT_NAME "datalogTool")
endif()

32
datalogtool/Info.plist Normal file
View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>datalogTool</string>
<key>CFBundleExecutable</key>
<string>datalogtool</string>
<key>CFBundleDisplayName</key>
<string>datalogTool</string>
<key>CFBundleIdentifier</key>
<string>edu.wpi.first.tools.datalogTool</string>
<key>CFBundleIconFile</key>
<string>datalogtool.icns</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleShortVersionString</key>
<string>2021</string>
<key>CFBundleVersion</key>
<string>2021</string>
<key>LSMinimumSystemVersion</key>
<string>10.11</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>

134
datalogtool/build.gradle Normal file
View File

@@ -0,0 +1,134 @@
import org.gradle.internal.os.OperatingSystem
if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxraspbian') && !project.hasProperty('onlylinuxaarch64bionic')) {
description = "roboRIO Team Number Setter"
apply plugin: 'cpp'
apply plugin: 'c'
apply plugin: 'google-test-test-suite'
apply plugin: 'visual-studio'
apply plugin: 'edu.wpi.first.NativeUtils'
if (OperatingSystem.current().isWindows()) {
apply plugin: 'windows-resources'
}
ext {
nativeName = 'datalogtool'
}
apply from: "${rootDir}/shared/resources.gradle"
apply from: "${rootDir}/shared/config.gradle"
def wpilibVersionFileInput = file("src/main/generate/WPILibVersion.cpp.in")
def wpilibVersionFileOutput = file("$buildDir/generated/main/cpp/WPILibVersion.cpp")
nativeUtils {
nativeDependencyContainer {
libssh(getNativeDependencyTypeClass('WPIStaticMavenDependency')) {
groupId = "edu.wpi.first.thirdparty.frc2022"
artifactId = "libssh"
headerClassifier = "headers"
sourceClassifier = "sources"
ext = "zip"
version = '0.95-1'
targetPlatforms.addAll(nativeUtils.wpi.platforms.desktopPlatforms)
}
}
}
task generateCppVersion() {
description = 'Generates the wpilib version class'
group = 'WPILib'
outputs.file wpilibVersionFileOutput
inputs.file wpilibVersionFileInput
if (wpilibVersioning.releaseMode) {
outputs.upToDateWhen { false }
}
// We follow a simple set of checks to determine whether we should generate a new version file:
// 1. If the release type is not development, we generate a new version file
// 2. If there is no generated version number, we generate a new version file
// 3. If there is a generated build number, and the release type is development, then we will
// only generate if the publish task is run.
doLast {
def version = wpilibVersioning.version.get()
println "Writing version ${version} to $wpilibVersionFileOutput"
if (wpilibVersionFileOutput.exists()) {
wpilibVersionFileOutput.delete()
}
def read = wpilibVersionFileInput.text.replace('${wpilib_version}', version)
wpilibVersionFileOutput.write(read)
}
}
gradle.taskGraph.addTaskExecutionGraphListener { graph ->
def willPublish = graph.hasTask(publish)
if (willPublish) {
generateCppVersion.outputs.upToDateWhen { false }
}
}
def generateTask = createGenerateResourcesTask('main', 'DLT', 'dlt', project)
project(':').libraryBuild.dependsOn build
tasks.withType(CppCompile) {
dependsOn generateTask
dependsOn generateCppVersion
}
model {
components {
// By default, a development executable will be generated. This is to help the case of
// testing specific functionality of the library.
"${nativeName}"(NativeExecutableSpec) {
baseName = 'datalogtool'
sources {
cpp {
source {
srcDirs 'src/main/native/cpp', "$buildDir/generated/main/cpp"
include '**/*.cpp'
}
exportedHeaders {
srcDirs 'src/main/native/include'
}
}
if (OperatingSystem.current().isWindows()) {
rc {
source {
srcDirs 'src/main/native/win'
include '*.rc'
}
}
}
}
binaries.all {
if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.raspbian || it.targetPlatform.name == nativeUtils.wpi.platforms.aarch64bionic) {
it.buildable = false
return
}
it.cppCompiler.define("LIBSSH_STATIC")
lib project: ':glass', library: 'glass', linkage: 'static'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
lib project: ':wpigui', library: 'wpigui', linkage: 'static'
nativeUtils.useRequiredLibrary(it, 'imgui_static', 'libssh')
if (it.targetPlatform.operatingSystem.isWindows()) {
it.linker.args << 'Gdi32.lib' << 'Shell32.lib' << 'd3d11.lib' << 'd3dcompiler.lib'
it.linker.args << 'ws2_32.lib' << 'advapi32.lib' << 'crypt32.lib' << 'user32.lib'
} else if (it.targetPlatform.operatingSystem.isMacOsX()) {
it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore'
it.linker.args << '-framework' << 'Kerberos'
} else {
it.linker.args << '-lX11'
}
}
}
}
}
apply from: 'publish.gradle'
}

107
datalogtool/publish.gradle Normal file
View File

@@ -0,0 +1,107 @@
apply plugin: 'maven-publish'
def baseArtifactId = 'DataLogTool'
def artifactGroupId = 'edu.wpi.first.tools'
def zipBaseName = '_GROUP_edu_wpi_first_tools_ID_DataLogTool_CLS'
def outputsFolder = file("$project.buildDir/outputs")
model {
tasks {
// Create the run task.
$.components.datalogtool.binaries.each { bin ->
if (bin.buildable && bin.name.toLowerCase().contains("debug")) {
Task run = project.tasks.create("run", Exec) {
commandLine bin.tasks.install.runScriptFile.get().asFile.toString()
}
run.dependsOn bin.tasks.install
}
}
}
publishing {
def dataLogToolTaskList = []
$.components.each { component ->
component.binaries.each { binary ->
if (binary in NativeExecutableBinarySpec && binary.component.name.contains("datalogtool")) {
if (binary.buildable && (binary.name.contains('Release') || binary.name.contains('release'))) {
// We are now in the binary that we want.
// This is the default application path for the ZIP task.
def applicationPath = binary.executable.file
def icon = file("$project.projectDir/src/main/native/mac/datalogtool.icns")
// Create the macOS bundle.
def bundleTask = project.tasks.create("bundleDataLogToolOsxApp", Copy) {
description("Creates a macOS application bundle for DataLogTool")
from(file("$project.projectDir/Info.plist"))
into(file("$project.buildDir/outputs/bundles/DataLogTool.app/Contents"))
into("MacOS") { with copySpec { from binary.executable.file } }
into("Resources") { with copySpec { from icon } }
doLast {
if (project.hasProperty("developerID")) {
// Get path to binary.
exec {
workingDir rootDir
def args = [
"sh",
"-c",
"codesign --force --strict --deep " +
"--timestamp --options=runtime " +
"--verbose -s ${project.findProperty("developerID")} " +
"$project.buildDir/outputs/bundles/DataLogTool.app/"
]
commandLine args
}
}
}
}
// Reset the application path if we are creating a bundle.
if (binary.targetPlatform.operatingSystem.isMacOsX()) {
applicationPath = file("$project.buildDir/outputs/bundles")
project.build.dependsOn bundleTask
}
// Create the ZIP.
def task = project.tasks.create("copyDataLogToolExecutable", Zip) {
description("Copies the DataLogTool executable to the outputs directory.")
destinationDirectory = outputsFolder
archiveBaseName = '_M_' + zipBaseName
duplicatesStrategy = 'exclude'
classifier = nativeUtils.getPublishClassifier(binary)
from(licenseFile) {
into '/'
}
from(applicationPath)
into(nativeUtils.getPlatformPath(binary))
}
if (binary.targetPlatform.operatingSystem.isMacOsX()) {
bundleTask.dependsOn binary.tasks.link
task.dependsOn(bundleTask)
}
task.dependsOn binary.tasks.link
dataLogToolTaskList.add(task)
project.build.dependsOn task
project.artifacts { task }
addTaskToCopyAllOutputs(task)
}
}
}
}
publications {
datalogtool(MavenPublication) {
dataLogToolTaskList.each { artifact it }
artifactId = baseArtifactId
groupId = artifactGroupId
version wpilibVersioning.version.get()
}
}
}
}

View File

@@ -0,0 +1,7 @@
/*
* Autogenerated file! Do not manually edit this file. This version is regenerated
* any time the publish task is run, or when this file is deleted.
*/
const char* GetWPILibVersion() {
return "${wpilib_version}";
}

View File

@@ -0,0 +1,156 @@
// 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 "App.h"
#include <libssh/libssh.h>
#include <memory>
#include <string_view>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <glass/Context.h>
#include <glass/MainMenuBar.h>
#include <glass/Storage.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <wpigui.h>
#include "Downloader.h"
#include "Exporter.h"
namespace gui = wpi::gui;
const char* GetWPILibVersion();
namespace dlt {
std::string_view GetResource_dlt_16_png();
std::string_view GetResource_dlt_32_png();
std::string_view GetResource_dlt_48_png();
std::string_view GetResource_dlt_64_png();
std::string_view GetResource_dlt_128_png();
std::string_view GetResource_dlt_256_png();
std::string_view GetResource_dlt_512_png();
} // namespace dlt
bool gShutdown = false;
static std::unique_ptr<Downloader> gDownloader;
static bool* gDownloadVisible;
static float gDefaultScale = 1.0;
void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) {
if ((cond & ImGuiCond_FirstUseEver) != 0) {
ImGui::SetNextWindowPos(pos * gDefaultScale, cond, pivot);
} else {
ImGui::SetNextWindowPos(pos, cond, pivot);
}
}
void SetNextWindowSize(const ImVec2& size, ImGuiCond cond) {
if ((cond & ImGuiCond_FirstUseEver) != 0) {
ImGui::SetNextWindowSize(size * gDefaultScale, cond);
} else {
ImGui::SetNextWindowPos(size, cond);
}
}
static void DisplayDownload() {
if (!*gDownloadVisible) {
return;
}
SetNextWindowPos(ImVec2{0, 250}, ImGuiCond_FirstUseEver);
SetNextWindowSize(ImVec2{375, 260}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Download", gDownloadVisible)) {
if (!gDownloader) {
gDownloader = std::make_unique<Downloader>(
glass::GetStorageRoot().GetChild("download"));
}
gDownloader->Display();
}
ImGui::End();
}
static void DisplayMainMenu() {
ImGui::BeginMainMenuBar();
static glass::MainMenuBar mainMenu;
mainMenu.WorkspaceMenu();
gui::EmitViewMenu();
if (ImGui::BeginMenu("Window")) {
ImGui::MenuItem("Download", nullptr, gDownloadVisible);
ImGui::EndMenu();
}
bool about = false;
if (ImGui::BeginMenu("Info")) {
if (ImGui::MenuItem("About")) {
about = true;
}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
if (about) {
ImGui::OpenPopup("About");
}
if (ImGui::BeginPopupModal("About")) {
ImGui::Text("Datalog Tool");
ImGui::Separator();
ImGui::Text("v%s", GetWPILibVersion());
ImGui::Separator();
ImGui::Text("Save location: %s", glass::GetStorageDir().c_str());
if (ImGui::Button("Close")) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
}
static void DisplayGui() {
DisplayMainMenu();
DisplayInputFiles();
DisplayEntries();
DisplayOutput(glass::GetStorageRoot().GetChild("output"));
DisplayDownload();
}
void Application(std::string_view saveDir) {
ssh_init();
gui::CreateContext();
glass::CreateContext();
// Add icons
gui::AddIcon(dlt::GetResource_dlt_16_png());
gui::AddIcon(dlt::GetResource_dlt_32_png());
gui::AddIcon(dlt::GetResource_dlt_48_png());
gui::AddIcon(dlt::GetResource_dlt_64_png());
gui::AddIcon(dlt::GetResource_dlt_128_png());
gui::AddIcon(dlt::GetResource_dlt_256_png());
gui::AddIcon(dlt::GetResource_dlt_512_png());
glass::SetStorageName("datalogtool");
glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
: saveDir);
gui::AddWindowScaler([](float scale) { gDefaultScale = scale; });
gui::AddLateExecute(DisplayGui);
gui::Initialize("Datalog Tool", 925, 510);
gDownloadVisible =
&glass::GetStorageRoot().GetChild("download").GetBool("visible", true);
gui::Main();
gShutdown = true;
glass::DestroyContext();
gui::DestroyContext();
gDownloader.reset();
ssh_finalize();
}

View File

@@ -4,10 +4,8 @@
#pragma once
#include <frc/buttons/Trigger.h>
#include <imgui.h>
class ReplaceMeTrigger : public frc::Trigger {
public:
ReplaceMeTrigger();
bool Get() override;
};
void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0,
const ImVec2& pivot = ImVec2(0, 0));
void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0);

View File

@@ -0,0 +1,72 @@
// 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 "DataLogThread.h"
#include <fmt/format.h>
DataLogThread::~DataLogThread() {
if (m_thread.joinable()) {
m_active = false;
m_thread.join();
}
}
void DataLogThread::ReadMain() {
for (auto record : m_reader) {
if (!m_active) {
break;
}
++m_numRecords;
if (record.IsStart()) {
wpi::log::StartRecordData data;
if (record.GetStartData(&data)) {
std::scoped_lock lock{m_mutex};
if (m_entries.find(data.entry) != m_entries.end()) {
fmt::print("...DUPLICATE entry ID, overriding\n");
}
m_entries[data.entry] = data;
m_entryNames.emplace(data.name, data);
sigEntryAdded(data);
} else {
fmt::print("Start(INVALID)\n");
}
} else if (record.IsFinish()) {
int entry;
if (record.GetFinishEntry(&entry)) {
std::scoped_lock lock{m_mutex};
auto it = m_entries.find(entry);
if (it == m_entries.end()) {
fmt::print("...ID not found\n");
} else {
m_entries.erase(it);
}
} else {
fmt::print("Finish(INVALID)\n");
}
} else if (record.IsSetMetadata()) {
wpi::log::MetadataRecordData data;
if (record.GetSetMetadataData(&data)) {
std::scoped_lock lock{m_mutex};
auto it = m_entries.find(data.entry);
if (it == m_entries.end()) {
fmt::print("...ID not found\n");
} else {
it->second.metadata = data.metadata;
auto nameIt = m_entryNames.find(it->second.name);
if (nameIt != m_entryNames.end()) {
nameIt->second.metadata = data.metadata;
}
}
} else {
fmt::print("SetMetadata(INVALID)\n");
}
} else if (record.IsControl()) {
fmt::print("Unrecognized control record\n");
}
}
sigDone();
m_done = true;
}

View File

@@ -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.
#pragma once
#include <atomic>
#include <functional>
#include <map>
#include <string>
#include <string_view>
#include <thread>
#include <utility>
#include <wpi/DataLogReader.h>
#include <wpi/DenseMap.h>
#include <wpi/Signal.h>
#include <wpi/mutex.h>
class DataLogThread {
public:
explicit DataLogThread(wpi::log::DataLogReader reader)
: m_reader{std::move(reader)}, m_thread{[=] { ReadMain(); }} {}
~DataLogThread();
bool IsDone() const { return m_done; }
std::string_view GetBufferIdentifier() const {
return m_reader.GetBufferIdentifier();
}
unsigned int GetNumRecords() const { return m_numRecords; }
unsigned int GetNumEntries() const {
std::scoped_lock lock{m_mutex};
return m_entryNames.size();
}
// Passes wpi::log::StartRecordData to func
template <typename T>
void ForEachEntryName(T&& func) {
std::scoped_lock lock{m_mutex};
for (auto&& kv : m_entryNames) {
func(kv.second);
}
}
wpi::log::StartRecordData GetEntry(std::string_view name) const {
std::scoped_lock lock{m_mutex};
auto it = m_entryNames.find(name);
if (it == m_entryNames.end()) {
return {};
}
return it->second;
}
const wpi::log::DataLogReader& GetReader() const { return m_reader; }
// note: these are called on separate thread
wpi::sig::Signal_mt<const wpi::log::StartRecordData&> sigEntryAdded;
wpi::sig::Signal_mt<> sigDone;
private:
void ReadMain();
wpi::log::DataLogReader m_reader;
mutable wpi::mutex m_mutex;
std::atomic_bool m_active{true};
std::atomic_bool m_done{false};
std::atomic<unsigned int> m_numRecords{0};
std::map<std::string, wpi::log::StartRecordData, std::less<>> m_entryNames;
wpi::DenseMap<int, wpi::log::StartRecordData> m_entries;
std::thread m_thread;
};

View File

@@ -0,0 +1,393 @@
// 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 "Downloader.h"
#include <libssh/sftp.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#else
#include <sys/fcntl.h>
#endif
#include <algorithm>
#include <filesystem>
#include <fmt/format.h>
#include <glass/Storage.h>
#include <imgui.h>
#include <imgui_stdlib.h>
#include <portable-file-dialogs.h>
#include <wpi/StringExtras.h>
#include <wpi/fs.h>
#include "Sftp.h"
Downloader::Downloader(glass::Storage& storage)
: m_serverTeam{storage.GetString("serverTeam")},
m_remoteDir{storage.GetString("remoteDir", "/home/lvuser")},
m_username{storage.GetString("username", "lvuser")},
m_localDir{storage.GetString("localDir")},
m_deleteAfter{storage.GetBool("deleteAfter", true)},
m_thread{[this] { ThreadMain(); }} {}
Downloader::~Downloader() {
{
std::scoped_lock lock{m_mutex};
m_state = kExit;
}
m_cv.notify_all();
m_thread.join();
}
void Downloader::DisplayConnect() {
// IP or Team Number text box
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
ImGui::InputText("Team Number / Address", &m_serverTeam);
// Username/password
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
ImGui::InputText("Username", &m_username);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
ImGui::InputText("Password", &m_password, ImGuiInputTextFlags_Password);
// Connect button
if (ImGui::Button("Connect")) {
m_state = kConnecting;
m_cv.notify_all();
}
}
void Downloader::DisplayDisconnectButton() {
if (ImGui::Button("Disconnect")) {
m_state = kDisconnecting;
m_cv.notify_all();
}
}
void Downloader::DisplayRemoteDirSelector() {
ImGui::SameLine();
if (ImGui::Button("Refresh")) {
m_state = kGetFiles;
m_cv.notify_all();
}
// Remote directory text box
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
if (ImGui::InputText("Remote Dir", &m_remoteDir,
ImGuiInputTextFlags_EnterReturnsTrue)) {
m_state = kGetFiles;
m_cv.notify_all();
}
// List directories
for (auto&& dir : m_dirList) {
if (ImGui::Selectable(dir.c_str())) {
if (dir == "..") {
if (wpi::ends_with(m_remoteDir, '/')) {
m_remoteDir.resize(m_remoteDir.size() - 1);
}
m_remoteDir = wpi::rsplit(m_remoteDir, '/').first;
if (m_remoteDir.empty()) {
m_remoteDir = "/";
}
} else {
if (!wpi::ends_with(m_remoteDir, '/')) {
m_remoteDir += '/';
}
m_remoteDir += dir;
}
m_state = kGetFiles;
m_cv.notify_all();
}
}
}
void Downloader::DisplayLocalDirSelector() {
// Local directory text / select button
if (ImGui::Button("Select Download Folder...")) {
m_localDirSelector =
std::make_unique<pfd::select_folder>("Select Download Folder");
}
ImGui::TextUnformatted(m_localDir.c_str());
// Delete after download (checkbox)
ImGui::Checkbox("Delete after download", &m_deleteAfter);
// Download button
if (!m_localDir.empty()) {
if (ImGui::Button("Download")) {
m_state = kDownload;
m_cv.notify_all();
}
}
}
size_t Downloader::DisplayFiles() {
// List of files (multi-select) (changes to progress bar for downloading)
size_t fileCount = 0;
if (ImGui::BeginTable(
"files", 3,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("File");
ImGui::TableSetupColumn("Size");
ImGui::TableSetupColumn("Download");
ImGui::TableHeadersRow();
for (auto&& download : m_downloadList) {
if ((m_state == kDownload || m_state == kDownloadDone) &&
!download.enabled) {
continue;
}
++fileCount;
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::TextUnformatted(download.name.c_str());
ImGui::TableNextColumn();
auto sizeText = fmt::format("{}", download.size);
ImGui::TextUnformatted(sizeText.c_str());
ImGui::TableNextColumn();
if (m_state == kDownload || m_state == kDownloadDone) {
if (!download.status.empty()) {
ImGui::TextUnformatted(download.status.c_str());
} else {
ImGui::ProgressBar(download.complete);
}
} else {
auto checkboxLabel = fmt::format("##{}", download.name);
ImGui::Checkbox(checkboxLabel.c_str(), &download.enabled);
}
}
ImGui::EndTable();
}
return fileCount;
}
void Downloader::Display() {
if (m_localDirSelector && m_localDirSelector->ready(0)) {
m_localDir = m_localDirSelector->result();
m_localDirSelector.reset();
}
std::scoped_lock lock{m_mutex};
if (!m_error.empty()) {
ImGui::TextUnformatted(m_error.c_str());
}
switch (m_state) {
case kDisconnected:
DisplayConnect();
break;
case kConnecting:
DisplayDisconnectButton();
ImGui::Text("Connecting to %s...", m_serverTeam.c_str());
break;
case kDisconnecting:
ImGui::TextUnformatted("Disconnecting...");
break;
case kConnected:
case kGetFiles:
DisplayDisconnectButton();
DisplayRemoteDirSelector();
if (DisplayFiles() > 0) {
DisplayLocalDirSelector();
}
break;
case kDownload:
case kDownloadDone:
DisplayDisconnectButton();
DisplayFiles();
if (m_state == kDownloadDone) {
if (ImGui::Button("Download complete!")) {
m_state = kGetFiles;
m_cv.notify_all();
}
}
break;
default:
break;
}
}
void Downloader::ThreadMain() {
std::unique_ptr<sftp::Session> session;
static constexpr size_t kBufSize = 32 * 1024;
std::unique_ptr<uint8_t[]> copyBuf = std::make_unique<uint8_t[]>(kBufSize);
std::unique_lock lock{m_mutex};
while (m_state != kExit) {
State prev = m_state;
m_cv.wait(lock, [&] { return m_state != prev; });
m_error.clear();
try {
switch (m_state) {
case kConnecting:
if (auto team = wpi::parse_integer<unsigned int>(m_serverTeam, 10)) {
// team number
session = std::make_unique<sftp::Session>(
fmt::format("roborio-{}-frc.local", team.value()), 22,
m_username, m_password);
} else {
session = std::make_unique<sftp::Session>(m_serverTeam, 22,
m_username, m_password);
}
lock.unlock();
try {
session->Connect();
} catch (...) {
lock.lock();
throw;
}
lock.lock();
// FALLTHROUGH
case kGetFiles: {
std::string dir = m_remoteDir;
std::vector<sftp::Attributes> fileList;
lock.unlock();
try {
fileList = session->ReadDir(dir);
} catch (sftp::Exception& ex) {
lock.lock();
if (ex.err == SSH_FX_OK || ex.err == SSH_FX_CONNECTION_LOST) {
throw;
}
m_error = ex.what();
m_dirList.clear();
m_downloadList.clear();
m_state = kConnected;
break;
}
std::sort(
fileList.begin(), fileList.end(),
[](const auto& l, const auto& r) { return l.name < r.name; });
lock.lock();
m_dirList.clear();
m_downloadList.clear();
for (auto&& attr : fileList) {
if (attr.type == SSH_FILEXFER_TYPE_DIRECTORY) {
if (attr.name != ".") {
m_dirList.emplace_back(attr.name);
}
} else if (attr.type == SSH_FILEXFER_TYPE_REGULAR &&
(attr.flags & SSH_FILEXFER_ATTR_SIZE) != 0 &&
wpi::ends_with(attr.name, ".wpilog")) {
m_downloadList.emplace_back(attr.name, attr.size);
}
}
m_state = kConnected;
break;
}
case kDisconnecting:
session.reset();
m_state = kDisconnected;
break;
case kDownload: {
for (auto&& download : m_downloadList) {
if (m_state != kDownload) {
// user aborted
break;
}
if (!download.enabled) {
continue;
}
auto remoteFilename = fmt::format(
"{}{}{}", m_remoteDir,
wpi::ends_with(m_remoteDir, '/') ? "" : "/", download.name);
auto localFilename = fs::path{m_localDir} / download.name;
uint64_t fileSize = download.size;
lock.unlock();
// open local file
std::error_code ec;
fs::file_t of = fs::OpenFileForWrite(localFilename, ec,
fs::CD_CreateNew, fs::OF_None);
if (ec) {
// failed to open
lock.lock();
download.status = ec.message();
continue;
}
int ofd = fs::FileToFd(of, ec, fs::OF_None);
if (ofd == -1 || ec) {
// failed to convert to fd
lock.lock();
download.status = ec.message();
continue;
}
try {
// open remote file
sftp::File f = session->Open(remoteFilename, O_RDONLY, 0);
// copy in chunks
uint64_t total = 0;
while (total < fileSize) {
uint64_t toCopy = (std::min)(fileSize - total,
static_cast<uint64_t>(kBufSize));
auto copied = f.Read(copyBuf.get(), toCopy);
if (write(ofd, copyBuf.get(), copied) !=
static_cast<int64_t>(copied)) {
// error writing
close(ofd);
fs::remove(localFilename, ec);
lock.lock();
download.status = "error writing local file";
goto err;
}
total += copied;
lock.lock();
download.complete = static_cast<float>(total) / fileSize;
lock.unlock();
}
// close local file
close(ofd);
ofd = -1;
// delete remote file (if enabled)
if (m_deleteAfter) {
f = sftp::File{};
session->Unlink(remoteFilename);
}
} catch (sftp::Exception& ex) {
if (ofd != -1) {
// close local file and delete it (due to failure)
close(ofd);
fs::remove(localFilename, ec);
}
lock.lock();
download.status = ex.what();
if (ex.err == SSH_FX_OK || ex.err == SSH_FX_CONNECTION_LOST) {
throw;
}
continue;
}
lock.lock();
err : {}
}
if (m_state == kDownload) {
m_state = kDownloadDone;
}
break;
}
default:
break;
}
} catch (sftp::Exception& ex) {
m_error = ex.what();
session.reset();
m_state = kDisconnected;
}
}
}

View File

@@ -0,0 +1,78 @@
// 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 <memory>
#include <string>
#include <thread>
#include <vector>
#include <wpi/condition_variable.h>
#include <wpi/mutex.h>
namespace glass {
class Storage;
} // namespace glass
namespace pfd {
class select_folder;
} // namespace pfd
class Downloader {
public:
explicit Downloader(glass::Storage& storage);
~Downloader();
void Display();
private:
void DisplayConnect();
void DisplayDisconnectButton();
void DisplayRemoteDirSelector();
void DisplayLocalDirSelector();
size_t DisplayFiles();
void ThreadMain();
wpi::mutex m_mutex;
enum State {
kDisconnected,
kConnecting,
kConnected,
kDisconnecting,
kGetFiles,
kDownload,
kDownloadDone,
kExit
} m_state = kDisconnected;
std::condition_variable m_cv;
std::string& m_serverTeam;
std::string& m_remoteDir;
std::string& m_username;
std::string m_password;
std::string& m_localDir;
std::unique_ptr<pfd::select_folder> m_localDirSelector;
bool& m_deleteAfter;
std::vector<std::string> m_dirList;
struct DownloadState {
DownloadState(std::string_view name, uint64_t size)
: name{name}, size{size} {}
std::string name;
uint64_t size;
bool enabled = true;
float complete = 0.0;
std::string status;
};
std::vector<DownloadState> m_downloadList;
std::string m_error;
std::thread m_thread;
};

View File

@@ -0,0 +1,661 @@
// 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 "Exporter.h"
#include <atomic>
#include <ctime>
#include <future>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <string_view>
#include <vector>
#include <fmt/chrono.h>
#include <fmt/format.h>
#include <glass/Storage.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <imgui_stdlib.h>
#include <portable-file-dialogs.h>
#include <wpi/DenseMap.h>
#include <wpi/MemoryBuffer.h>
#include <wpi/SmallVector.h>
#include <wpi/SpanExtras.h>
#include <wpi/StringExtras.h>
#include <wpi/fmt/raw_ostream.h>
#include <wpi/fs.h>
#include <wpi/mutex.h>
#include <wpi/raw_ostream.h>
#include "App.h"
#include "DataLogThread.h"
namespace {
struct InputFile {
explicit InputFile(std::unique_ptr<DataLogThread> datalog);
InputFile(std::string_view filename, std::string_view status)
: filename{filename},
stem{fs::path{filename}.stem().string()},
status{status} {}
~InputFile();
std::string filename;
std::string stem;
std::unique_ptr<DataLogThread> datalog;
std::string status;
bool highlight = false;
};
struct Entry {
explicit Entry(const wpi::log::StartRecordData& srd)
: name{srd.name}, type{srd.type}, metadata{srd.metadata} {}
std::string name;
std::string type;
std::string metadata;
std::set<InputFile*> inputFiles;
bool typeConflict = false;
bool metadataConflict = false;
bool selected = true;
// used only during export
int column = -1;
};
struct EntryTreeNode {
explicit EntryTreeNode(std::string_view name) : name{name} {}
std::string name; // name of just this node
std::string path; // full path if entry is nullptr
Entry* entry = nullptr;
std::vector<EntryTreeNode> children; // children, sorted by name
int selected = 1;
};
} // namespace
static std::map<std::string, std::unique_ptr<InputFile>, std::less<>>
gInputFiles;
static wpi::mutex gEntriesMutex;
static std::map<std::string, std::unique_ptr<Entry>, std::less<>> gEntries;
static std::vector<EntryTreeNode> gEntryTree;
std::atomic_int gExportCount{0};
// must be called with gEntriesMutex held
static void RebuildEntryTree() {
gEntryTree.clear();
wpi::SmallVector<std::string_view, 16> parts;
for (auto& kv : gEntries) {
parts.clear();
// split on first : if one is present
auto [prefix, mainpart] = wpi::split(kv.first, ':');
if (mainpart.empty() || wpi::contains(prefix, '/')) {
mainpart = kv.first;
} else {
parts.emplace_back(prefix);
}
wpi::split(mainpart, parts, '/', -1, false);
// ignore a raw "/" key
if (parts.empty()) {
continue;
}
// get to leaf
auto nodes = &gEntryTree;
for (auto part : wpi::drop_back(wpi::span{parts.begin(), parts.end()})) {
auto it =
std::find_if(nodes->begin(), nodes->end(),
[&](const auto& node) { return node.name == part; });
if (it == nodes->end()) {
nodes->emplace_back(part);
// path is from the beginning of the string to the end of the current
// part; this works because part is a reference to the internals of
// kv.first
nodes->back().path.assign(kv.first.data(),
part.data() + part.size() - kv.first.data());
it = nodes->end() - 1;
}
nodes = &it->children;
}
auto it = std::find_if(nodes->begin(), nodes->end(), [&](const auto& node) {
return node.name == parts.back();
});
if (it == nodes->end()) {
nodes->emplace_back(parts.back());
// no need to set path, as it's identical to kv.first
it = nodes->end() - 1;
}
it->entry = kv.second.get();
}
}
InputFile::InputFile(std::unique_ptr<DataLogThread> datalog_)
: filename{datalog_->GetBufferIdentifier()},
stem{fs::path{filename}.stem().string()},
datalog{std::move(datalog_)} {
datalog->sigEntryAdded.connect([this](const wpi::log::StartRecordData& srd) {
std::scoped_lock lock{gEntriesMutex};
auto it = gEntries.find(srd.name);
if (it == gEntries.end()) {
it = gEntries.emplace(srd.name, std::make_unique<Entry>(srd)).first;
RebuildEntryTree();
} else {
if (it->second->type != srd.type) {
it->second->typeConflict = true;
}
if (it->second->metadata != srd.metadata) {
it->second->metadataConflict = true;
}
}
it->second->inputFiles.emplace(this);
});
}
InputFile::~InputFile() {
if (gShutdown || !datalog) {
return;
}
std::scoped_lock lock{gEntriesMutex};
bool changed = false;
for (auto it = gEntries.begin(); it != gEntries.end();) {
it->second->inputFiles.erase(this);
if (it->second->inputFiles.empty()) {
it = gEntries.erase(it);
changed = true;
} else {
++it;
}
}
if (changed) {
RebuildEntryTree();
}
}
static std::unique_ptr<InputFile> LoadDataLog(std::string_view filename) {
std::error_code ec;
auto buf = wpi::MemoryBuffer::GetFile(filename, ec);
std::string fn{filename};
if (ec) {
return std::make_unique<InputFile>(
fn, fmt::format("Could not open file: {}", ec.message()));
}
wpi::log::DataLogReader reader{std::move(buf)};
if (!reader.IsValid()) {
return std::make_unique<InputFile>(fn, "Not a valid datalog file");
}
return std::make_unique<InputFile>(
std::make_unique<DataLogThread>(std::move(reader)));
}
void DisplayInputFiles() {
static std::unique_ptr<pfd::open_file> dataFileSelector;
SetNextWindowPos(ImVec2{0, 20}, ImGuiCond_FirstUseEver);
SetNextWindowSize(ImVec2{375, 230}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Input Files")) {
if (ImGui::Button("Open File(s)...")) {
dataFileSelector = std::make_unique<pfd::open_file>(
"Select Data Log", "",
std::vector<std::string>{"DataLog Files", "*.wpilog"},
pfd::opt::multiselect);
}
ImGui::BeginTable(
"Input Files", 3,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchProp);
ImGui::TableSetupColumn("File");
ImGui::TableSetupColumn("Status");
ImGui::TableSetupColumn("X", ImGuiTableColumnFlags_WidthFixed |
ImGuiTableColumnFlags_NoHeaderLabel |
ImGuiTableColumnFlags_NoHeaderWidth);
ImGui::TableHeadersRow();
for (auto it = gInputFiles.begin(); it != gInputFiles.end();) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (it->second->highlight) {
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,
IM_COL32(0, 64, 0, 255));
it->second->highlight = false;
}
ImGui::TextUnformatted(it->first.c_str());
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", it->second->filename.c_str());
}
ImGui::TableNextColumn();
if (it->second->datalog) {
ImGui::Text("%u records, %u entries%s",
it->second->datalog->GetNumRecords(),
it->second->datalog->GetNumEntries(),
it->second->datalog->IsDone() ? "" : " (working)");
} else {
ImGui::TextUnformatted(it->second->status.c_str());
}
ImGui::TableNextColumn();
ImGui::PushID(it->first.c_str());
if (ImGui::SmallButton("X")) {
it = gInputFiles.erase(it);
gExportCount = 0;
} else {
++it;
}
ImGui::PopID();
}
ImGui::EndTable();
}
ImGui::End();
// Load data file(s)
if (dataFileSelector && dataFileSelector->ready(0)) {
auto result = dataFileSelector->result();
for (auto&& filename : result) {
// don't allow duplicates
std::string stem = fs::path{filename}.stem().string();
auto it = gInputFiles.find(stem);
if (it == gInputFiles.end()) {
gInputFiles.emplace(std::move(stem), LoadDataLog(filename));
gExportCount = 0;
}
}
dataFileSelector.reset();
}
}
static bool EmitEntry(const std::string& name, Entry& entry) {
ImGui::TableNextColumn();
bool rv = ImGui::Checkbox(name.c_str(), &entry.selected);
if (ImGui::IsItemHovered() && gInputFiles.size() > 1) {
for (auto inputFile : entry.inputFiles) {
inputFile->highlight = true;
}
}
ImGui::TableNextColumn();
if (entry.typeConflict) {
ImGui::TextUnformatted("(Inconsistent)");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
for (auto inputFile : entry.inputFiles) {
ImGui::Text(
"%s: %s", inputFile->stem.c_str(),
std::string{inputFile->datalog->GetEntry(entry.name).type}.c_str());
}
ImGui::EndTooltip();
}
} else {
ImGui::TextUnformatted(entry.type.c_str());
}
ImGui::TableNextColumn();
if (entry.metadataConflict) {
ImGui::TextUnformatted("(Inconsistent)");
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
for (auto inputFile : entry.inputFiles) {
ImGui::Text(
"%s: %s", inputFile->stem.c_str(),
std::string{inputFile->datalog->GetEntry(entry.name).metadata}
.c_str());
}
ImGui::EndTooltip();
}
} else {
ImGui::TextUnformatted(entry.metadata.c_str());
}
return rv;
}
static bool EmitEntryTree(std::vector<EntryTreeNode>& tree) {
bool rv = false;
for (auto&& node : tree) {
if (node.entry) {
if (EmitEntry(node.name, *node.entry)) {
rv = true;
}
}
if (!node.children.empty()) {
ImGui::TableNextColumn();
auto label = fmt::format("##check_{}", node.name);
if (node.selected == -1) {
ImGui::PushItemFlag(ImGuiItemFlags_MixedValue, true);
bool b = false;
if (ImGui::Checkbox(label.c_str(), &b)) {
node.selected = 3; // 3 = enable group
rv = true;
}
ImGui::PopItemFlag();
} else {
bool b = node.selected == 1 || node.selected == 3;
if (ImGui::Checkbox(label.c_str(), &b)) {
node.selected = b ? 3 : 2; // 2 = disable group
rv = true;
}
}
ImGui::SameLine();
bool open = ImGui::TreeNodeEx(node.name.c_str(),
ImGuiTreeNodeFlags_SpanFullWidth);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
if (open) {
if (EmitEntryTree(node.children)) {
rv = true;
}
ImGui::TreePop();
}
}
}
return rv;
}
static void RefreshTreeCheckboxes(std::vector<EntryTreeNode>& tree,
int* selected) {
bool first = true;
for (auto&& node : tree) {
if (node.entry) {
if (first && *selected == -1) {
*selected = node.entry->selected ? 1 : 0;
}
if ((*selected == 0 && node.entry->selected) ||
(*selected == 1 && !node.entry->selected)) {
*selected = -1; // inconsistent
} else if (*selected == 2) { // disable group
node.entry->selected = false;
} else if (*selected == 3) { // enable group
node.entry->selected = true;
}
}
if (!node.children.empty()) {
if (*selected == 2) { // disable group
node.selected = 2;
} else if (*selected == 3) { // enable group
node.selected = 3;
}
RefreshTreeCheckboxes(node.children, &node.selected);
if (node.selected == 2) {
node.selected = 0;
} else if (node.selected == 3) {
node.selected = 1;
}
if (first && *selected == -1) {
*selected = node.selected;
} else if (node.selected == -1 ||
(*selected == 0 && node.selected == 1) ||
(*selected == 1 && node.selected == 0)) {
*selected = -1; // inconsistent
}
}
first = false;
}
}
void DisplayEntries() {
SetNextWindowPos(ImVec2{380, 20}, ImGuiCond_FirstUseEver);
SetNextWindowSize(ImVec2{540, 365}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Entries")) {
static bool treeView = true;
if (ImGui::BeginPopupContextItem()) {
ImGui::MenuItem("Tree View", "", &treeView);
ImGui::EndPopup();
}
std::scoped_lock lock{gEntriesMutex};
ImGui::BeginTable(
"Entries", 3,
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchProp);
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Type");
ImGui::TableSetupColumn("Metadata");
ImGui::TableHeadersRow();
if (treeView) {
if (EmitEntryTree(gEntryTree)) {
int selected = -1;
RefreshTreeCheckboxes(gEntryTree, &selected);
}
} else {
for (auto&& kv : gEntries) {
EmitEntry(kv.first, *kv.second);
}
}
ImGui::EndTable();
}
ImGui::End();
}
static wpi::mutex gExportMutex;
static std::vector<std::string> gExportErrors;
static void PrintEscapedCsvString(wpi::raw_ostream& os, std::string_view str) {
auto s = str;
while (!s.empty()) {
std::string_view fragment;
std::tie(fragment, s) = wpi::split(s, '"');
os << fragment;
if (!s.empty()) {
os << '"' << '"';
}
}
if (wpi::ends_with(str, '"')) {
os << '"' << '"';
}
}
static void ValueToCsv(wpi::raw_ostream& os, const Entry& entry,
const wpi::log::DataLogRecord& record) {
// handle systemTime specially
if (entry.name == "systemTime" && entry.type == "int64") {
int64_t val;
if (record.GetInteger(&val)) {
std::time_t timeval = val / 1000000;
fmt::print(os, "{:%Y-%m-%d %H:%M:%S}.{:06}", *std::localtime(&timeval),
val % 1000000);
return;
}
} else if (entry.type == "double") {
double val;
if (record.GetDouble(&val)) {
fmt::print(os, "{}", val);
return;
}
} else if (entry.type == "int64") {
int64_t val;
if (record.GetInteger(&val)) {
fmt::print(os, "{}", val);
return;
}
} else if (entry.type == "string" || entry.type == "json") {
std::string_view val;
record.GetString(&val);
os << '"';
PrintEscapedCsvString(os, val);
os << '"';
return;
} else if (entry.type == "boolean") {
bool val;
if (record.GetBoolean(&val)) {
fmt::print(os, "{}", val);
return;
}
} else if (entry.type == "boolean[]") {
std::vector<int> val;
if (record.GetBooleanArray(&val)) {
fmt::print(os, "{}", fmt::join(val, ";"));
return;
}
} else if (entry.type == "double[]") {
std::vector<double> val;
if (record.GetDoubleArray(&val)) {
fmt::print(os, "{}", fmt::join(val, ";"));
return;
}
} else if (entry.type == "float[]") {
std::vector<float> val;
if (record.GetFloatArray(&val)) {
fmt::print(os, "{}", fmt::join(val, ";"));
return;
}
} else if (entry.type == "int64[]") {
std::vector<int64_t> val;
if (record.GetIntegerArray(&val)) {
fmt::print(os, "{}", fmt::join(val, ";"));
return;
}
} else if (entry.type == "string[]") {
std::vector<std::string_view> val;
if (record.GetStringArray(&val)) {
os << '"';
bool first = true;
for (auto&& v : val) {
if (!first) {
os << ';';
}
first = false;
PrintEscapedCsvString(os, v);
}
os << '"';
return;
}
}
fmt::print(os, "<invalid>");
}
static void ExportCsvFile(InputFile& f, wpi::raw_ostream& os, int style) {
// header
if (style == 0) {
os << "Timestamp,Name,Value\n";
} else if (style == 1) {
// scan for exported fields for this file to print header and assign columns
os << "Timestamp";
int columnNum = 0;
for (auto&& entry : gEntries) {
if (entry.second->selected &&
entry.second->inputFiles.find(&f) != entry.second->inputFiles.end()) {
os << ',' << '"';
PrintEscapedCsvString(os, entry.first);
os << '"';
entry.second->column = columnNum++;
} else {
entry.second->column = -1;
}
}
os << '\n';
}
wpi::DenseMap<int, Entry*> nameMap;
for (auto&& record : f.datalog->GetReader()) {
if (record.IsStart()) {
wpi::log::StartRecordData data;
if (record.GetStartData(&data)) {
auto it = gEntries.find(data.name);
if (it != gEntries.end() && it->second->selected) {
nameMap[data.entry] = it->second.get();
}
}
} else if (record.IsFinish()) {
int entry;
if (record.GetFinishEntry(&entry)) {
nameMap.erase(entry);
}
} else if (!record.IsControl()) {
auto entryIt = nameMap.find(record.GetEntry());
if (entryIt == nameMap.end()) {
continue;
}
Entry* entry = entryIt->second;
if (style == 0) {
fmt::print(os, "{},\"", record.GetTimestamp() / 1000000.0);
PrintEscapedCsvString(os, entry->name);
os << '"' << ',';
ValueToCsv(os, *entry, record);
os << '\n';
} else if (style == 1 && entry->column != -1) {
fmt::print(os, "{},", record.GetTimestamp() / 1000000.0);
for (int i = 0; i < entry->column; ++i) {
os << ',';
}
ValueToCsv(os, *entry, record);
os << '\n';
}
}
}
}
static void ExportCsv(std::string_view outputFolder, int style) {
fs::path outPath{outputFolder};
for (auto&& f : gInputFiles) {
if (f.second->datalog) {
std::error_code ec;
auto of = fs::OpenFileForWrite(
outPath / fs::path{f.first}.replace_extension("csv"), ec,
fs::CD_CreateNew, fs::OF_Text);
if (ec) {
std::scoped_lock lock{gExportMutex};
gExportErrors.emplace_back(
fmt::format("{}: {}", f.first, ec.message()));
++gExportCount;
continue;
}
wpi::raw_fd_ostream os{fs::FileToFd(of, ec, fs::OF_Text), true};
ExportCsvFile(*f.second, os, style);
}
++gExportCount;
}
}
void DisplayOutput(glass::Storage& storage) {
static std::string& outputFolder = storage.GetString("outputFolder");
static std::unique_ptr<pfd::select_folder> outputFolderSelector;
SetNextWindowPos(ImVec2{380, 390}, ImGuiCond_FirstUseEver);
SetNextWindowSize(ImVec2{540, 120}, ImGuiCond_FirstUseEver);
if (ImGui::Begin("Output")) {
if (ImGui::Button("Select Output Folder...")) {
outputFolderSelector =
std::make_unique<pfd::select_folder>("Select Output Folder");
}
ImGui::TextUnformatted(outputFolder.c_str());
static const char* const options[] = {"List", "Table"};
static int style = 0;
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::Combo("Style", &style, options,
sizeof(options) / sizeof(const char*));
static std::future<void> exporter;
if (!gInputFiles.empty() && !outputFolder.empty() &&
ImGui::Button("Export CSV") &&
(gExportCount == 0 ||
gExportCount == static_cast<int>(gInputFiles.size()))) {
gExportCount = 0;
gExportErrors.clear();
exporter = std::async(std::launch::async, ExportCsv, outputFolder, style);
}
if (exporter.valid()) {
ImGui::SameLine();
ImGui::Text("Exported %d/%d", gExportCount.load(),
static_cast<int>(gInputFiles.size()));
}
{
std::scoped_lock lock{gExportMutex};
for (auto&& err : gExportErrors) {
ImGui::TextUnformatted(err.c_str());
}
}
}
ImGui::End();
if (outputFolderSelector && outputFolderSelector->ready(0)) {
outputFolder = outputFolderSelector->result();
outputFolderSelector.reset();
}
}

View File

@@ -4,9 +4,12 @@
#pragma once
#include <frc/commands/CommandGroup.h>
namespace glass {
class Storage;
} // namespace glass
class ReplaceMeCommandGroup : public frc::CommandGroup {
public:
ReplaceMeCommandGroup();
};
void DisplayInputFiles();
void DisplayEntries();
void DisplayOutput(glass::Storage& storage);
extern bool gShutdown;

View File

@@ -0,0 +1,215 @@
// 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 "Sftp.h"
#include <fmt/format.h>
using namespace sftp;
Attributes::Attributes(sftp_attributes&& attr)
: name{attr->name}, flags{attr->flags}, type{attr->type}, size{attr->size} {
sftp_attributes_free(attr);
}
static std::string GetError(sftp_session sftp) {
switch (sftp_get_error(sftp)) {
case SSH_FX_EOF:
return "end of file";
case SSH_FX_NO_SUCH_FILE:
return "no such file";
case SSH_FX_PERMISSION_DENIED:
return "permission denied";
case SSH_FX_FAILURE:
return "SFTP failure";
case SSH_FX_BAD_MESSAGE:
return "SFTP bad message";
case SSH_FX_NO_CONNECTION:
return "SFTP no connection";
case SSH_FX_CONNECTION_LOST:
return "SFTP connection lost";
case SSH_FX_OP_UNSUPPORTED:
return "SFTP operation unsupported";
case SSH_FX_INVALID_HANDLE:
return "SFTP invalid handle";
case SSH_FX_NO_SUCH_PATH:
return "no such path";
case SSH_FX_FILE_ALREADY_EXISTS:
return "file already exists";
case SSH_FX_WRITE_PROTECT:
return "write protected filesystem";
case SSH_FX_NO_MEDIA:
return "no media inserted";
default:
return ssh_get_error(sftp->session);
}
}
Exception::Exception(sftp_session sftp)
: runtime_error{GetError(sftp)}, err{sftp_get_error(sftp)} {}
File::~File() {
if (m_handle) {
sftp_close(m_handle);
}
}
Attributes File::Stat() const {
sftp_attributes attr = sftp_fstat(m_handle);
if (!attr) {
throw Exception{m_handle->sftp};
}
return Attributes{std::move(attr)};
}
size_t File::Read(void* buf, uint32_t count) {
auto rv = sftp_read(m_handle, buf, count);
if (rv < 0) {
throw Exception{m_handle->sftp};
}
return rv;
}
File::AsyncId File::AsyncReadBegin(uint32_t len) const {
int rv = sftp_async_read_begin(m_handle, len);
if (rv < 0) {
throw Exception{m_handle->sftp};
}
return rv;
}
size_t File::AsyncRead(void* data, uint32_t len, AsyncId id) {
auto rv = sftp_async_read(m_handle, data, len, id);
if (rv == SSH_ERROR) {
throw Exception{ssh_get_error(m_handle->sftp->session)};
}
if (rv == SSH_AGAIN) {
return 0;
}
return rv;
}
size_t File::Write(wpi::span<const uint8_t> data) {
auto rv = sftp_write(m_handle, data.data(), data.size());
if (rv < 0) {
throw Exception{m_handle->sftp};
}
return rv;
}
void File::Seek(uint64_t offset) {
if (sftp_seek64(m_handle, offset) < 0) {
throw Exception{m_handle->sftp};
}
}
uint64_t File::Tell() const {
return sftp_tell64(m_handle);
}
void File::Rewind() {
sftp_rewind(m_handle);
}
void File::Sync() {
if (sftp_fsync(m_handle) < 0) {
throw Exception{m_handle->sftp};
}
}
Session::Session(std::string_view host, int port, std::string_view user,
std::string_view pass)
: m_host{host}, m_port{port}, m_username{user}, m_password{pass} {
// Create a new SSH session.
m_session = ssh_new();
if (!m_session) {
throw Exception{"The SSH session could not be allocated."};
}
// Set the host, user, and port.
ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.c_str());
ssh_options_set(m_session, SSH_OPTIONS_USER, m_username.c_str());
ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port);
// Set timeout to 3 seconds.
int64_t timeout = 3L;
ssh_options_set(m_session, SSH_OPTIONS_TIMEOUT, &timeout);
// Set other miscellaneous options.
ssh_options_set(m_session, SSH_OPTIONS_STRICTHOSTKEYCHECK, "no");
}
Session::~Session() {
if (m_sftp) {
sftp_free(m_sftp);
}
if (m_session) {
ssh_free(m_session);
}
}
void Session::Connect() {
// Connect to the server.
int rc = ssh_connect(m_session);
if (rc != SSH_OK) {
throw Exception{ssh_get_error(m_session)};
}
// Authenticate with password.
rc = ssh_userauth_password(m_session, nullptr, m_password.c_str());
if (rc != SSH_AUTH_SUCCESS) {
throw Exception{ssh_get_error(m_session)};
}
// Allocate the SFTP session.
m_sftp = sftp_new(m_session);
if (!m_sftp) {
throw Exception{ssh_get_error(m_session)};
}
// Initialize.
rc = sftp_init(m_sftp);
if (rc != SSH_OK) {
sftp_free(m_sftp);
m_sftp = nullptr;
throw Exception{ssh_get_error(m_session)};
}
}
void Session::Disconnect() {
if (m_sftp) {
sftp_free(m_sftp);
m_sftp = nullptr;
}
ssh_disconnect(m_session);
}
std::vector<Attributes> Session::ReadDir(const std::string& path) {
sftp_dir dir = sftp_opendir(m_sftp, path.c_str());
if (!dir) {
throw Exception{m_sftp};
}
std::vector<Attributes> rv;
while (sftp_attributes attr = sftp_readdir(m_sftp, dir)) {
rv.emplace_back(std::move(attr));
}
sftp_closedir(dir);
return rv;
}
void Session::Unlink(const std::string& filename) {
if (sftp_unlink(m_sftp, filename.c_str()) < 0) {
throw Exception{m_sftp};
}
}
File Session::Open(const std::string& filename, int accesstype, mode_t mode) {
sftp_file f = sftp_open(m_sftp, filename.c_str(), accesstype, mode);
if (!f) {
throw Exception{m_sftp};
}
return File{std::move(f)};
}

View File

@@ -0,0 +1,144 @@
// 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 <libssh/libssh.h>
#include <libssh/sftp.h>
#include <stdexcept>
#include <string>
#include <string_view>
#include <vector>
#include <wpi/span.h>
namespace sftp {
struct Attributes {
Attributes() = default;
explicit Attributes(sftp_attributes&& attr);
std::string name;
uint32_t flags = 0;
uint8_t type = 0;
uint64_t size = 0;
};
/**
* This is the exception that will be thrown if something goes wrong.
*/
class Exception : public std::runtime_error {
public:
explicit Exception(const std::string& msg) : std::runtime_error{msg} {}
explicit Exception(sftp_session sftp);
int err = 0;
};
class File {
public:
File() = default;
explicit File(sftp_file&& handle) : m_handle{handle} {}
~File();
Attributes Stat() const;
void SetNonblocking() { sftp_file_set_nonblocking(m_handle); }
void SetBlocking() { sftp_file_set_blocking(m_handle); }
using AsyncId = uint32_t;
size_t Read(void* buf, uint32_t count);
AsyncId AsyncReadBegin(uint32_t len) const;
size_t AsyncRead(void* data, uint32_t len, AsyncId id);
size_t Write(wpi::span<const uint8_t> data);
void Seek(uint64_t offset);
uint64_t Tell() const;
void Rewind();
void Sync();
std::string_view GetName() const { return m_handle->name; }
uint64_t GetOffset() const { return m_handle->offset; }
bool IsEof() const { return m_handle->eof; }
bool IsNonblocking() const { return m_handle->nonblocking; }
private:
sftp_file m_handle{nullptr};
};
/**
* This class is a C++ implementation of the SshSessionController in
* wpilibsuite/deploy-utils. It handles connecting to an SSH server, running
* commands, and transferring files.
*/
class Session {
public:
/**
* Constructs a new session controller.
*
* @param host The hostname of the server to connect to.
* @param port The port that the sshd server is operating on.
* @param user The username to login as.
* @param pass The password for the given username.
*/
Session(std::string_view host, int port, std::string_view user,
std::string_view pass);
/**
* Destroys the controller object. This also disconnects the session from the
* server.
*/
~Session();
/**
* Opens the SSH connection to the given host.
*/
void Connect();
/**
* Disconnects the SSH connection.
*/
void Disconnect();
/**
* Reads directory entries
*
* @param path remote path
* @return vector of file attributes
*/
std::vector<Attributes> ReadDir(const std::string& path);
/**
* Unlinks (deletes) a file.
*
* @param filename filename
*/
void Unlink(const std::string& filename);
/**
* Opens a file.
*
* @param filename filename
* @param accesstype O_RDONLY, O_WRONLY, or O_RDWR, combined with O_CREAT,
* O_EXCL, or O_TRUNC
* @param mode permissions to use if a new file is created
* @return File
*/
File Open(const std::string& filename, int accesstype, mode_t mode);
private:
ssh_session m_session{nullptr};
sftp_session m_sftp{nullptr};
std::string m_host;
int m_port;
std::string m_username;
std::string m_password;
};
} // namespace sftp

View File

@@ -0,0 +1,25 @@
// 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 <string_view>
void Application(std::string_view saveDir);
#ifdef _WIN32
int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine,
int nCmdShow) {
int argc = __argc;
char** argv = __argv;
#else
int main(int argc, char** argv) {
#endif
std::string_view saveDir;
if (argc == 2) {
saveDir = argv[1];
}
Application(saveDir);
return 0;
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

View File

@@ -0,0 +1 @@
IDI_ICON1 ICON "datalogtool.ico"

View File

@@ -11,7 +11,6 @@ evaluationDependsOn(':cameraserver')
evaluationDependsOn(':wpimath')
evaluationDependsOn(':wpilibc')
evaluationDependsOn(':wpilibj')
evaluationDependsOn(':wpilibOldCommands')
evaluationDependsOn(':wpilibNewCommands')
def baseArtifactIdCpp = 'documentation'
@@ -34,7 +33,6 @@ cppProjectZips.add(project(':cscore').cppHeadersZip)
cppProjectZips.add(project(':cameraserver').cppHeadersZip)
cppProjectZips.add(project(':wpimath').cppHeadersZip)
cppProjectZips.add(project(':wpilibc').cppHeadersZip)
cppProjectZips.add(project(':wpilibOldCommands').cppHeadersZip)
cppProjectZips.add(project(':wpilibNewCommands').cppHeadersZip)
doxygen {
@@ -204,7 +202,6 @@ task generateJavaDocs(type: Javadoc) {
source project(':wpimath').sourceSets.main.java
source project(':wpilibj').sourceSets.main.java
source project(':cameraserver').sourceSets.main.java
source project(':wpilibOldCommands').sourceSets.main.java
source project(':wpilibNewCommands').sourceSets.main.java
source configurations.javaSource.collect { zipTree(it) }
include '**/*.java'

View File

@@ -69,19 +69,6 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra
nativeUtils.exportsConfigs {
glass {
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',
@@ -151,6 +138,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra
}
lib library: nativeName, linkage: 'static'
lib project: ':ntcore', library: 'ntcore', linkage: 'shared'
lib project: ':wpinet', library: 'wpinet', linkage: 'shared'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'shared'
lib project: ':wpimath', library: 'wpimath', linkage: 'shared'
lib project: ':wpigui', library: 'wpigui', linkage: 'static'
@@ -189,6 +177,7 @@ if (!project.hasProperty('onlylinuxathena') && !project.hasProperty('onlylinuxra
lib library: 'glassnt', linkage: 'static'
lib library: nativeName, linkage: 'static'
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
lib project: ':wpinet', library: 'wpinet', linkage: 'static'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
lib project: ':wpimath', library: 'wpimath', linkage: 'static'
lib project: ':wpigui', library: 'wpigui', linkage: 'static'

View File

@@ -77,7 +77,7 @@ model {
$.components.each { component ->
component.binaries.each { binary ->
if (binary in NativeExecutableBinarySpec && binary.component.name.contains("glassApp")) {
if (binary.buildable && binary.name.contains("Release")) {
if (binary.buildable && (binary.name.contains('Release') || binary.name.contains('release'))) {
// We are now in the binary that we want.
// This is the default application path for the ZIP task.
def applicationPath = binary.executable.file
@@ -130,6 +130,14 @@ model {
}
from(applicationPath)
if (binary.targetPlatform.operatingSystem.isWindows()) {
def exePath = binary.executable.file.absolutePath
exePath = exePath.substring(0, exePath.length() - 4)
def pdbPath = new File(exePath + '.pdb')
from(pdbPath)
}
into(nativeUtils.getPlatformPath(binary))
}

View File

@@ -47,6 +47,26 @@ static std::unique_ptr<glass::Window> gNetworkTablesLogWindow;
static glass::MainMenuBar gMainMenu;
static bool gAbout = false;
static bool gSetEnterKey = false;
static bool gKeyEdit = false;
static int* gEnterKey;
static void (*gPrevKeyCallback)(GLFWwindow*, int, int, int, int);
static void RemapEnterKeyCallback(GLFWwindow* window, int key, int scancode,
int action, int mods) {
if (action == GLFW_PRESS || action == GLFW_RELEASE) {
if (gKeyEdit) {
*gEnterKey = key;
gKeyEdit = false;
} else if (*gEnterKey == key) {
key = GLFW_KEY_ENTER;
}
}
if (gPrevKeyCallback) {
gPrevKeyCallback(window, key, scancode, action, mods);
}
}
static void NtInitialize() {
// update window title when connection status changes
@@ -178,6 +198,9 @@ int main(int argc, char** argv) {
gMainMenu.AddMainMenu([] {
if (ImGui::BeginMenu("View")) {
if (ImGui::MenuItem("Set Enter Key")) {
gSetEnterKey = true;
}
if (ImGui::MenuItem("Reset Time")) {
glass::ResetTime();
}
@@ -231,9 +254,48 @@ int main(int argc, char** argv) {
}
ImGui::EndPopup();
}
if (gSetEnterKey) {
ImGui::OpenPopup("Set Enter Key");
gSetEnterKey = false;
}
if (ImGui::BeginPopupModal("Set Enter Key")) {
ImGui::Text("Set the key to use to mean 'Enter'");
ImGui::Text("This is useful to edit values without the DS disabling");
ImGui::Separator();
ImGui::Text("Key:");
ImGui::SameLine();
char editLabel[40];
char nameBuf[32];
const char* name = glfwGetKeyName(*gEnterKey, 0);
if (!name) {
std::snprintf(nameBuf, sizeof(nameBuf), "%d", *gEnterKey);
name = nameBuf;
}
std::snprintf(editLabel, sizeof(editLabel), "%s###edit",
gKeyEdit ? "(press key)" : name);
if (ImGui::SmallButton(editLabel)) {
gKeyEdit = true;
}
ImGui::SameLine();
if (ImGui::SmallButton("Reset")) {
*gEnterKey = GLFW_KEY_ENTER;
}
if (ImGui::Button("Close")) {
ImGui::CloseCurrentPopup();
gKeyEdit = false;
}
ImGui::EndPopup();
}
});
gui::Initialize("Glass - DISCONNECTED", 1024, 768);
gEnterKey = &glass::GetStorageRoot().GetInt("enterKey", GLFW_KEY_ENTER);
if (auto win = gui::GetSystemWindow()) {
gPrevKeyCallback = glfwSetKeyCallback(win, RemapEnterKeyCallback);
}
gui::Main();
gNetworkTablesSettingsWindow.reset();

View File

@@ -14,7 +14,7 @@ using namespace glass;
static const char* stations[] = {"Red 1", "Red 2", "Red 3",
"Blue 1", "Blue 2", "Blue 3"};
void glass::DisplayFMS(FMSModel* model, bool* matchTimeEnabled) {
void glass::DisplayFMS(FMSModel* model) {
if (!model->Exists() || model->IsReadOnly()) {
return DisplayFMSReadOnly(model);
}
@@ -49,10 +49,6 @@ void glass::DisplayFMS(FMSModel* model, bool* matchTimeEnabled) {
// Match Time
if (auto data = model->GetMatchTimeData()) {
if (matchTimeEnabled) {
ImGui::Checkbox("Match Time Enabled", matchTimeEnabled);
}
double val = data->GetValue();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
if (ImGui::InputDouble("Match Time", &val, 0, 0, "%.1f",
@@ -60,9 +56,17 @@ void glass::DisplayFMS(FMSModel* model, bool* matchTimeEnabled) {
model->SetMatchTime(val);
}
data->EmitDrag();
bool enabled = false;
if (auto enabledData = model->GetEnabledData()) {
enabled = enabledData->GetValue();
}
ImGui::SameLine();
if (ImGui::Button("Reset")) {
model->SetMatchTime(0.0);
if (ImGui::Button("Auto") && !enabled) {
model->SetMatchTime(15.0);
}
ImGui::SameLine();
if (ImGui::Button("Teleop") && !enabled) {
model->SetMatchTime(135.0);
}
}

View File

@@ -105,7 +105,7 @@ class PlotSeries {
int& m_digitalBitGap;
// value storage
static constexpr int kMaxSize = 2000;
static constexpr int kMaxSize = 20000;
static constexpr double kTimeGap = 0.05;
std::atomic<int> m_size = 0;
std::atomic<int> m_offset = 0;
@@ -246,7 +246,7 @@ void PlotSeries::SetSource(DataSource* source) {
m_source = source;
// add initial value
m_data[m_size++] = ImPlotPoint{wpi::Now() * 1.0e-6, source->GetValue()};
AppendValue(source->GetValue(), 0);
m_newValueConn = source->valueChanged.connect_connection(
[this](double value, uint64_t time) { AppendValue(value, time); });

View File

@@ -47,7 +47,7 @@ class FMSModel : public Model {
* @param matchTimeEnabled If not null, a checkbox is displayed for
* "enable match time" linked to this value
*/
void DisplayFMS(FMSModel* model, bool* matchTimeEnabled = nullptr);
void DisplayFMS(FMSModel* model);
void DisplayFMSReadOnly(FMSModel* model);
} // namespace glass

View File

@@ -16,7 +16,7 @@
namespace glass {
class NTSpeedControllerModel : public SpeedControllerModel {
public:
static constexpr const char* kType = "Speed Controller";
static constexpr const char* kType = "Motor Controller";
explicit NTSpeedControllerModel(std::string_view path);
NTSpeedControllerModel(NT_Inst instance, std::string_view path);

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.2)
cmake_minimum_required(VERSION 3.3.0)
project(googletest-download NONE)

View File

@@ -1,6 +1,6 @@
# The --add-exports flags work around a bug with spotless and JDK 17
# https://github.com/diffplug/spotless/issues/834
org.gradle.jvmargs=-Xmx1g \
org.gradle.jvmargs=-Xmx2g \
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
--add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \
--add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \

View File

@@ -133,19 +133,6 @@ Action<List<String>> symbolFilter = { symbols ->
nativeUtils.exportsConfigs {
hal {
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',
@@ -161,7 +148,6 @@ nativeUtils.exportsConfigs {
]
}
halJNI {
x86SymbolFilter = symbolFilter
x64SymbolFilter = symbolFilter
}
}

View File

@@ -52,7 +52,7 @@ public class NotifierJNI extends JNIWrapper {
public static native void cleanNotifier(int notifierHandle);
/**
* Sets the notifier to wakeup the waiter in another triggerTime microseconds.
* Sets the notifier to wake up the waiter at triggerTime microseconds.
*
* @param notifierHandle Notifier handle.
* @param triggerTime Trigger time in microseconds.

View File

@@ -335,8 +335,13 @@ HAL_Bool HAL_GetCTREPCMSolenoidVoltageFault(HAL_CTREPCMHandle handle,
void HAL_ClearAllCTREPCMStickyFaults(HAL_CTREPCMHandle handle,
int32_t* status) {
auto pcm = pcmHandles->Get(handle);
if (pcm == nullptr) {
*status = HAL_HANDLE_ERROR;
return;
}
uint8_t controlData[] = {0, 0, 0, 0x80};
HAL_WriteCANPacket(handle, controlData, sizeof(controlData), Control2,
HAL_WriteCANPacket(pcm->canHandle, controlData, sizeof(controlData), Control2,
status);
}
@@ -393,7 +398,7 @@ void HAL_SetCTREPCMOneShotDuration(HAL_CTREPCMHandle handle, int32_t index,
(std::min)(static_cast<uint32_t>(durMs) / 10,
static_cast<uint32_t>(0xFF));
HAL_WriteCANPacketRepeating(pcm->canHandle, pcm->oneShot.sol10MsPerUnit, 8,
Control2, SendPeriod, status);
Control3, SendPeriod, status);
}
} // extern "C"

View File

@@ -110,10 +110,15 @@ static int32_t HAL_GetControlWordInternal(HAL_ControlWord* controlWord) {
static int32_t HAL_GetMatchInfoInternal(HAL_MatchInfo* info) {
MatchType_t matchType = MatchType_t::kMatchType_none;
info->gameSpecificMessageSize = sizeof(info->gameSpecificMessage);
int status = FRC_NetworkCommunication_getMatchInfo(
info->eventName, &matchType, &info->matchNumber, &info->replayNumber,
info->gameSpecificMessage, &info->gameSpecificMessageSize);
if (info->gameSpecificMessageSize > sizeof(info->gameSpecificMessage)) {
info->gameSpecificMessageSize = 0;
}
info->matchType = static_cast<HAL_MatchType>(matchType);
*(std::end(info->eventName) - 1) = '\0';

View File

@@ -14,7 +14,6 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <string>
#include <thread>

View File

@@ -48,4 +48,6 @@ int32_t HALSIM_RegisterSimPeriodicAfterCallback(
void HALSIM_CancelSimPeriodicAfterCallback(int32_t uid) {}
void HALSIM_CancelAllSimPeriodicCallbacks(void) {}
} // extern "C"

View File

@@ -46,7 +46,7 @@ void HAL_FreeAnalogInputPort(HAL_AnalogInputHandle analogPortHandle);
HAL_Bool HAL_CheckAnalogModule(int32_t module);
/**
* Checks that the analog output channel number is value.
* Checks that the analog output channel number is valid.
* Verifies that the analog channel number is one of the legal channel numbers.
* Channel numbers are 0-based.
*

View File

@@ -58,7 +58,7 @@ double HAL_GetAnalogOutput(HAL_AnalogOutputHandle analogOutputHandle,
int32_t* status);
/**
* Checks that the analog output channel number is value.
* Checks that the analog output channel number is valid.
*
* Verifies that the analog channel number is one of the legal channel numbers.
* Channel numbers are 0-based.

View File

@@ -22,7 +22,8 @@ extern "C" {
/**
* Initializes a CAN device.
*
* These follow the FIRST standard CAN layout. Link TBD
* These follow the FIRST standard CAN layout.
* https://docs.wpilib.org/en/stable/docs/software/can-devices/can-addressing.html
*
* @param[in] manufacturer the can manufacturer
* @param[in] deviceId the device ID (0-63)

View File

@@ -36,4 +36,6 @@ int32_t HALSIM_RegisterSimPeriodicAfterCallback(
HALSIM_SimPeriodicCallback callback, void* param);
void HALSIM_CancelSimPeriodicAfterCallback(int32_t uid);
void HALSIM_CancelAllSimPeriodicCallbacks(void);
} // extern "C"

View File

@@ -87,9 +87,21 @@ template <typename T, HAL_Value (*MakeValue)(T), const char* (*GetName)(),
T (*GetDefault)() = nullptr>
class SimDataValue final : public impl::SimDataValueBase<T, MakeValue> {
public:
// FIXME: GCC 12.1 gives the false positive "the address of <GetDefault> will
// never be NULL" because it doesn't realize the default template parameter can
// make GetDefault nullptr. In C++20, replace "T (*GetDefault)() = nullptr" with
// "T (*GetDefault)() = [] { return T(); }" and unconditionally call
// GetDefault() to fix the warning.
#if __GNUC__ >= 12
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Waddress"
#endif // __GNUC__ >= 12
SimDataValue()
: impl::SimDataValueBase<T, MakeValue>(
GetDefault != nullptr ? GetDefault() : T()) {}
#if __GNUC__ >= 12
#pragma GCC diagnostic pop
#endif // __GNUC__ >= 12
explicit SimDataValue(T value)
: impl::SimDataValueBase<T, MakeValue>(value) {}

View File

@@ -409,6 +409,11 @@ void HALSIM_CancelSimPeriodicAfterCallback(int32_t uid) {
gSimPeriodicAfter.Cancel(uid);
}
void HALSIM_CancelAllSimPeriodicCallbacks(void) {
gSimPeriodicBefore.Reset();
gSimPeriodicAfter.Reset();
}
int64_t HAL_Report(int32_t resource, int32_t instanceNumber, int32_t context,
const char* feature) {
return 0; // Do nothing for now

View File

@@ -7,6 +7,7 @@
#include <stdint.h>
namespace hal {
constexpr int32_t kAccelerometers = 1;
constexpr int32_t kNumAccumulators = 2;
constexpr int32_t kNumAnalogTriggers = 8;
constexpr int32_t kNumAnalogInputs = 8;
@@ -18,6 +19,7 @@ constexpr int32_t kNumDigitalChannels = 31;
constexpr int32_t kNumPWMChannels = 20;
constexpr int32_t kNumDigitalPWMOutputs = 6;
constexpr int32_t kNumEncoders = 8;
constexpr int32_t kI2CPorts = 2;
constexpr int32_t kNumInterrupts = 8;
constexpr int32_t kNumRelayChannels = 8;
constexpr int32_t kNumRelayHeaders = kNumRelayChannels / 2;
@@ -27,8 +29,13 @@ constexpr int32_t kNumCTREPDPModules = 63;
constexpr int32_t kNumCTREPDPChannels = 16;
constexpr int32_t kNumREVPDHModules = 63;
constexpr int32_t kNumREVPDHChannels = 24;
constexpr int32_t kNumPDSimModules = kNumREVPDHModules;
constexpr int32_t kNumPDSimChannels = kNumREVPDHChannels;
constexpr int32_t kNumDutyCycles = 8;
constexpr int32_t kNumAddressableLEDs = 1;
constexpr int32_t kNumREVPHModules = 63;
constexpr int32_t kNumREVPHChannels = 16;
constexpr int32_t kSPIAccelerometers = 5;
constexpr int32_t kSPIPorts = 5;
} // namespace hal

View File

@@ -9,7 +9,7 @@ using namespace hal;
namespace hal::init {
void InitializeAccelerometerData() {
static AccelerometerData sad[1];
static AccelerometerData sad[kAccelerometers];
::hal::SimAccelerometerData = sad;
}
} // namespace hal::init

View File

@@ -30,7 +30,7 @@ void DriverStationData::ResetData() {
fmsAttached.Reset(false);
dsAttached.Reset(true);
allianceStationId.Reset(static_cast<HAL_AllianceStationID>(0));
matchTime.Reset(0.0);
matchTime.Reset(-1.0);
{
std::scoped_lock lock(m_joystickDataMutex);

View File

@@ -126,7 +126,7 @@ class DriverStationData {
SimDataValue<HAL_AllianceStationID, MakeAllianceStationIdValue,
GetAllianceStationIdName>
allianceStationId{static_cast<HAL_AllianceStationID>(0)};
SimDataValue<double, HAL_MakeDouble, GetMatchTimeName> matchTime{0.0};
SimDataValue<double, HAL_MakeDouble, GetMatchTimeName> matchTime{-1.0};
private:
SimCallbackRegistry<HAL_JoystickAxesCallback, GetJoystickAxesName>

View File

@@ -9,7 +9,7 @@ using namespace hal;
namespace hal::init {
void InitializeI2CData() {
static I2CData sid[2];
static I2CData sid[kI2CPorts];
::hal::SimI2CData = sid;
}
} // namespace hal::init

View File

@@ -9,8 +9,6 @@
#include "hal/simulation/SimDataValue.h"
namespace hal {
constexpr int32_t kNumPDSimModules = hal::kNumREVPDHModules;
constexpr int32_t kNumPDSimChannels = hal::kNumREVPDHChannels;
class PowerDistributionData {
HAL_SIMDATAVALUE_DEFINE_NAME(Initialized)

View File

@@ -9,7 +9,7 @@ using namespace hal;
namespace hal::init {
void InitializeSPIAccelerometerData() {
static SPIAccelerometerData ssad[5];
static SPIAccelerometerData ssad[kSPIAccelerometers];
::hal::SimSPIAccelerometerData = ssad;
}
} // namespace hal::init

View File

@@ -9,7 +9,7 @@ using namespace hal;
namespace hal::init {
void InitializeSPIData() {
static SPIData ssd[5];
static SPIData ssd[kSPIPorts];
::hal::SimSPIData = ssd;
}
} // namespace hal::init

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.2)
cmake_minimum_required(VERSION 3.3.0)
project(imgui-download NONE)
@@ -15,7 +15,7 @@ ExternalProject_Add(glfw3
)
ExternalProject_Add(gl3w
GIT_REPOSITORY https://github.com/skaslev/gl3w
GIT_TAG 3755745085ac2e865fd22270cfe9169c26640f70
GIT_TAG 5f8d7fd191ba22ff2b60c1106d7135bb9a335533
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/gl3w-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/gl3w-build"
INSTALL_COMMAND ""

View File

@@ -36,14 +36,6 @@ if (OperatingSystem.current().isWindows()) {
if (runtimeVerNumber != null) {
runtimeLocation = file("$runtimeLocation\\$runtimeVerNumber")
def x86Folder = null
file("$runtimeLocation\\x86").eachFile {
if (it.name.endsWith('.CRT')) {
x86Folder = it
}
}
def x64Folder = null
file("$runtimeLocation\\x64").eachFile {
@@ -52,14 +44,6 @@ if (OperatingSystem.current().isWindows()) {
}
}
def x86ZipTask = tasks.create('x86RuntimeZip', Zip) {
destinationDirectory = outputsFolder
archiveBaseName = zipBaseName
classifier = 'x86'
from x86Folder
}
def x64ZipTask = tasks.create('x64RuntimeZip', Zip) {
destinationDirectory = outputsFolder
archiveBaseName = zipBaseName
@@ -68,17 +52,14 @@ if (OperatingSystem.current().isWindows()) {
from x64Folder
}
addTaskToCopyAllOutputs(x86ZipTask)
addTaskToCopyAllOutputs(x64ZipTask)
build.dependsOn x86ZipTask
build.dependsOn x64ZipTask
publishing {
publications {
runtime(MavenPublication) {
artifact x86ZipTask
artifact x64ZipTask
artifactId = "${baseArtifactId}"

View File

@@ -36,7 +36,9 @@ mainClassName = 'frc.robot.Main'
apply plugin: 'com.github.johnrengelman.shadow'
repositories {
mavenCentral()
maven {
url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn'
}
}
dependencies {
@@ -44,10 +46,10 @@ dependencies {
implementation project(':wpimath')
implementation project(':hal')
implementation project(':wpiutil')
implementation project(':wpinet')
implementation project(':ntcore')
implementation project(':cscore')
implementation project(':cameraserver')
implementation project(':wpilibOldCommands')
implementation project(':wpilibNewCommands')
}
@@ -86,6 +88,9 @@ deploy {
myRobotCpp(NativeExecutableArtifact) {
libraryDirectory = '/usr/local/frc/third-party/lib'
def excludes = getLibraryFilter().getExcludes()
excludes.add('**/*.so.debug')
excludes.add('**/*.so.*.debug')
postdeploy << { ctx ->
ctx.execute('chmod +x myRobotCpp')
}
@@ -158,7 +163,6 @@ model {
deploy.targets.roborio.artifacts.myRobotCpp.binary = binary
}
}
lib project: ':wpilibOldCommands', library: 'wpilibOldCommands', linkage: 'shared'
lib project: ':wpilibNewCommands', library: 'wpilibNewCommands', linkage: 'shared'
lib project: ':wpilibc', library: 'wpilibc', linkage: 'shared'
lib project: ':wpimath', library: 'wpimath', linkage: 'shared'
@@ -168,9 +172,11 @@ model {
lib project: ':ntcore', library: 'ntcoreJNIShared', linkage: 'shared'
lib project: ':cscore', library: 'cscoreJNIShared', linkage: 'shared'
lib project: ':wpimath', library: 'wpimathJNIShared', linkage: 'shared'
lib project: ':wpinet', library: 'wpinetJNIShared', linkage: 'shared'
lib project: ':wpiutil', library: 'wpiutilJNIShared', linkage: 'shared'
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')
@@ -205,7 +211,6 @@ model {
deploy.targets.roborio.artifacts.myRobotCppStatic.binary = binary
}
}
lib project: ':wpilibOldCommands', library: 'wpilibOldCommands', linkage: 'static'
lib project: ':wpilibNewCommands', library: 'wpilibNewCommands', linkage: 'static'
lib project: ':wpilibc', library: 'wpilibc', linkage: 'static'
lib project: ':wpimath', library: 'wpimath', linkage: 'static'
@@ -213,6 +218,7 @@ model {
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
lib project: ':cscore', library: 'cscore', linkage: 'static'
project(':hal').addHalDependency(binary, 'static')
lib project: ':wpinet', library: 'wpinet', linkage: 'static'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
nativeUtils.useRequiredLibrary(binary, 'ni_link_libraries', 'ni_runtime_libraries')

View File

@@ -30,4 +30,5 @@ includeOtherLibs {
^fmt/
^support/
^wpi/
^wpinet/
}

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