Compare commits

...

734 Commits

Author SHA1 Message Date
Tyler Veness
7f4265facc [wpimath] Add LinearFilter::FiniteDifference() (#3900)
This allows making more general finite difference filters, like central
finite difference. SysId uses this for acceleration filtering.
2022-01-15 20:18:11 -08:00
Tyler Veness
63d1fb3bed [wpiutil] Modify fmt to not throw on write failure (#3919)
This was causing issues with tools, as the launchers would close stdout/stderr, resulting in write failures.
2022-01-15 20:10:32 -08:00
Tyler Veness
36af6d25a5 [wpimath] Fix input vector in pose estimator docs (NFC) (#3923) 2022-01-15 20:03:39 -08:00
Thad House
8f387f7255 [wpilibj] Switch ControlWord mutex to actual reentrant mutex (#3922)
It seems like the JVM does not handle recursive calls to object monitor based locks correctly. A few bugs in the past have been reported to have caused deadlocks if this occurs. It looks like the version of Java we use is fixed, but there could be other bugs, and it seems like this area of the code isn't tested much. Based on the stacks reported in #3896, it really seems like this is occurring. So we're going to attempt to switch to explicit mutex based classes, which shouldn't have bugs like this, and we will see if that fixes the issue.
2022-01-15 15:24:06 -08:00
David Vo
792e735e08 [wpimath] Move TrajectoryGenerator::SetErrorHandler definition to .cpp (#3920)
Otherwise this function causes linking errors when used on Windows.
2022-01-15 08:58:49 -08:00
Tyler Veness
3b76de83eb [commands] Fix ProfiledPIDCommand use-after-free (#3904)
Fixes #3903.
2022-01-14 23:56:48 -08:00
PJ Reiniger
ad9f738cfa [fieldimages] Fix maven publishing (#3897) 2022-01-14 23:55:10 -08:00
modelmat
49455199e5 [examples] Use left/rightGroup.Get() for simulator inputs to fix inversions (#3908) 2022-01-14 23:54:20 -08:00
modelmat
64426502ea [wpimath] Fix arm -> flywheel typo (NFC) (#3911) 2022-01-14 23:53:45 -08:00
Tyler Veness
8cc112d196 [wpiutil] Fix wpi::array for move-only types (#3917)
Fixes #3916.
2022-01-14 23:53:12 -08:00
Tyler Veness
e78cd49861 [build] Upgrade Java formatter plugins (#3894) 2022-01-11 22:24:16 -08:00
Tyler Veness
cfb4f756d6 [build] Upgrade to shadow 7.1.2 (#3893) 2022-01-11 21:10:15 -08:00
Tyler Veness
ba0908216c [wpimath] Fix crash in KF latency compensator (#3888)
It would crash in C++ if the global measurement was sooner than all the
snapshots.

Align Java with the changes and better document computation approach.
2022-01-09 23:01:04 -08:00
Peter Johnson
a3a0334fad [build] cmake: Move fieldImages to WITH_GUI (#3885)
This will only ever be used by GUI applications, and the jar build
method it uses can misbehave in some cross-compile scenarios.
2022-01-09 20:26:54 -08:00
sciencewhiz
cf7460c3a8 [fieldImages] Add 2022 field (#3883) 2022-01-08 23:24:24 -08:00
Tyler Veness
db0fbb6448 [wpimath] Fix LQR matrix constructor overload for Q, R, and N (#3884)
It was using the continuous B matrix to compute the feedback gain
instead of the discrete B matrix.

Tests were added for the matrix constructor overloads.
2022-01-08 23:23:53 -08:00
sciencewhiz
8ac45f20bb [commands] Update Command documentation (NFC) (#3881)
Add reference to which VendorDep the class is included in.
Add missing OldCommands C++ Documentation (copied from Java).
2022-01-08 11:11:34 -08:00
Tyler Veness
b3707cca0b [wpiutil] Upgrade to fmt 8.1.1 (#3879)
The changes to PneumaticsBase.cpp were to fix errors like the following
from enum classes not being formattable:
```
allwpilib/wpilibc/src/main/native/cpp/PneumaticsBase.cpp:36:9:   required from here
allwpilib/wpiutil/src/main/native/fmtlib/include/fmt/core.h:2672:12: error: use of deleted function ‘fmt::v8::detail::fallback_formatter<T, Char, Enable>::fallback_formatter() [with T = frc::PneumaticsModuleType; Char = char; Enable = void]’
 2672 |   auto f = conditional_t<has_formatter<mapped_type, context>::value,
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2673 |                          formatter<mapped_type, char_type>,
      |                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 2674 |                          fallback_formatter<T, char_type>>();
      |                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
2022-01-08 11:10:42 -08:00
Tyler Veness
a69ee3ece9 [wpimath] Const-qualify Twist2d scalar multiply (#3882)
Fixes #3880.
2022-01-08 11:09:29 -08:00
Drew Williams
750d9a30c9 [examples] Fix Eigen out of range error when running example (#3877)
Simple typo fix.
2022-01-08 00:15:26 -08:00
Peter Johnson
41c5b2b5ac [rtns] Add cmake build (#3866)
This needs libssh to build, so on Linux systems it's necessary to
install libssh-dev.
2022-01-08 00:14:48 -08:00
Tyler Veness
6cf3f9b28e [build] Upgrade to Gradle 7.3.3 (#3878)
This is the same version robot projects currently use.
2022-01-08 00:14:27 -08:00
Starlight220
269cf03472 [examples] Add communication examples (e.g. arduino) (#2500)
Co-authored-by: Andrew Dassonville <dassonville.andrew@gmail.com>
2022-01-06 18:08:57 -08:00
sciencewhiz
5ccfc4adbd [oldcommands] Deprecate PIDWrappers, since they use deprecated interfaces (#3868) 2022-01-06 18:05:24 -08:00
Peter Johnson
b6f44f98be [hal] Add warning about onboard I2C (#3871)
Adds HAL layer warning for #3842. This is needed in the case when a
vendor uses the HAL directly rather than using the WPILib I2C class.

This should not result in a duplicate warning for WPILib I2C users due
to the duplicate message checking performed in HAL_SendError().

We don't want to remove the WPILib I2C warning because it gives stack
trace information while the HAL layer one can't.
2022-01-06 17:44:27 -08:00
Peter Johnson
0dca57e9ec [templates] romieducational: Invert drivetrain and disable motor safety (#3869) 2022-01-06 11:29:15 -08:00
Tyler Veness
22c4da152e [wpilib] Add GetRate() to ADIS classes (#3864)
The angular rate is treated somewhat like an angle during calibration,
but the datasheet says it's angular rate. The variables were renamed to
make this clearer.
2022-01-04 22:26:23 -08:00
Peter Johnson
05d66f862d [templates] Change the template ordering to put command based first (#3863)
Previously it was a bit buried.
2022-01-04 21:23:57 -08:00
Dustin Spicuzza
b09f5b2cf2 [wpilibc] Add virtual dtor for LinearSystemSim (#3861) 2022-01-03 21:25:02 -08:00
Tyler Veness
a2510aaa0e [wpilib] Make ADIS IMU classes unit-safe (#3860)
The gyro rate getters were removed since that data isn't available.
2022-01-03 20:00:53 -08:00
Tyler Veness
947f589916 [wpilibc] Rename ADIS_16470_IMU.cpp to match class name (#3859) 2022-01-03 17:53:57 -08:00
Peter Johnson
bbd8980a20 [myRobot] Fix cameraserver library order (#3858) 2022-01-03 11:59:29 -08:00
Tyler Veness
831052f118 [wpilib] Add simulation support to ADIS classes (#3857) 2022-01-03 11:44:12 -08:00
Noah Andrews
c137569f91 [wpilib] Throw exception if the REV Pneumatic Hub firmware version is older than 22.0.0 (#3853) 2022-01-03 11:09:30 -08:00
sciencewhiz
dae61226fa Fix Maven Artifacts readme (#3856)
Add wpiutil to wpimath
Add wpimath to wpilibj and wpilibc
2022-01-03 10:18:49 -08:00
sciencewhiz
3ad4594a88 Update Maven artifacts readme for 2022 (#3855) 2022-01-01 13:28:36 -08:00
Matteo Kimura
112acb9a62 [wpilibc] Move ADIS IMU constants to inside class (#3852) 2022-01-01 11:40:28 -08:00
Peter Johnson
ecee224e81 [wpilib] Allow SendableCameraWrappers to take arbitrary URLs (#3850)
Useful for adding cameras that are streamed from a coprocessor

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
Co-authored-by: Sam Carlberg <sam.carlberg@gmail.com>
2022-01-01 10:10:37 -08:00
Peter Johnson
a3645dea34 LICENSE: Bump year range to include 2022 (#3854) 2022-01-01 00:00:16 -08:00
Jan-Felix Abellera
7c09f44898 [wpilib] Use PSI for compressor config and sensor reading (#3847)
This adds the REV Analog Pressure Sensor PSI to volt (and vice versa) conversion to allow setting the compressor config in PSI and getting the sensor reading in PSI. Also adds input validation for pressure values at the higher level.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-12-31 21:04:56 -08:00
Peter Johnson
f401ea9aae [wpigui] Remove wpiutil linkage (#3851)
It was only being used for fs::remove() (added in #3463), which is easily
replaced by std::remove().

The code change does not affect the WPILib tools, as this code is not used when JSON save files are used.
2021-12-31 07:56:31 -08:00
Peter Johnson
bf8517f1e6 [wpimath] TimeInterpolatableBufferTest: Fix lint warnings (#3849) 2021-12-31 00:06:08 -08:00
David Vo
528087e308 [hal] Use enums with fixed underlying type in clang C (#3297)
This will allow static analysis tools that use clang to always determine the correct intended parameter types for HAL functions.
2021-12-30 21:20:05 -08:00
Thad House
1f59ff72f9 [wpilib] Add ADIS IMUs (#3777)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
Co-authored-by: Matteo Kimura <mateus.sakata@gmail.com>
2021-12-30 19:43:53 -08:00
Matt
315be873c4 [wpimath] Add TimeInterpolatableBuffer (#2695)
These classes are useful for storing previous robot positions to use in conjunction with the upcoming pose estimators.

Co-authored-by: Prateek Machiraju <prateek.machiraju@gmail.com>
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
Co-authored-by: cttew <cttewari@gmail.com>
2021-12-30 19:08:05 -08:00
Oblarg
b8d019cdb4 [wpilib] Rename NormalizeWheelSpeeds to DesaturateWheelSpeeds (#3791) 2021-12-30 18:30:08 -08:00
Peter Johnson
102f23bbdb [wpilibj] DriverStation: Set thread interrupted state (#3846)
This is a Java best practice when catching InterruptedException.
2021-12-30 13:13:52 -08:00
Kevin-OConnor
b85c24a79c [wpilib] Add warning about onboard I2C (#3842) 2021-12-30 13:13:03 -08:00
Oblarg
eee29daaf9 [newCommands] Trigger: Allow override of debounce type (#3845)
Previously Trigger could only be debounced on rising edges.
This change preserves the default behavior but adds the capability to override it.
2021-12-29 16:10:43 -08:00
Oblarg
aa9dfabde2 [wpimath] Move debouncer to filters (#3838) 2021-12-28 09:49:41 -08:00
Peter Johnson
5999a26fba [wpiutil] Add GetSystemTime() (#3840)
This portably gets the time in microseconds since the Unix epoch.
2021-12-27 23:06:31 -08:00
sciencewhiz
1e82595ffb [examples] Fix arcade inversions (#3841)
Accounts for differences between ArcadeDrive and the methods used
in some other examples.
2021-12-27 23:05:42 -08:00
Peter Johnson
e373fa476b [wpiutil] Add disableMockTime to JNI (#3839)
This exposes the equivalent of SetNowImpl(nullptr) to Java.
2021-12-27 09:51:32 -08:00
sciencewhiz
dceb5364f4 [examples] Ensure right side motors are inverted (#3836)
Fixes #3827
Adds MotorController inversion for right side, removes inversion in
setVoltage methods.

Also fixes various XboxController negations (was inconsistent throughout examples).
2021-12-26 19:25:26 -08:00
Oblarg
baacbc8e24 [wpilib] Tachometer: Add function to return RPS (#3833) 2021-12-26 15:52:18 -08:00
Austin Shalit
84b15f0883 [templates] Add Java Romi Educational template (#3837)
This is a combination of a Romi Gradle project and Educational robot (added in #3309)
2021-12-26 15:46:22 -08:00
Dalton Smith
c0da9d2d35 [examples] Invert Right Motor in Romi Java examples (#3828) 2021-12-26 15:42:53 -08:00
sciencewhiz
0fe0be2733 [build] Change project year to intellisense (#3835)
This means VSCode won't prompt to upgrade (added in beta 4)
2021-12-25 20:50:06 -06:00
Tyler Veness
eafa947338 [wpimath] Make copies of trajectory constraint arguments (#3832)
This avoids stack-use-after-scope bugs in code like the following when
the original argument goes out of scope:
```cpp
frc2::Command* RobotContainer::GetAutonomousCommand() {
  // Create a voltage constraint to ensure we don't accelerate too fast
  frc::DifferentialDriveVoltageConstraint autoVoltageConstraint(
      frc::SimpleMotorFeedforward<units::meters>(
          DriveConstants::ks, DriveConstants::kv, DriveConstants::ka),
      DriveConstants::kDriveKinematics, 10_V);
```
2021-12-25 07:19:43 -06:00
sciencewhiz
9d13ae8d01 [wpilib] Add notes for Servo get that it only returns cmd (NFC) (#3820)
Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
2021-12-23 22:22:18 -08:00
Tyler Veness
2a64e4bae5 [wpimath] Give drivetrain a more realistic width in TrajectoryJsonTest.java (#3822)
Fixes #3819.
2021-12-22 22:28:23 -08:00
Tyler Veness
c3fd20db59 [wpilib] Fix trajectory sampling in DifferentialDriveSim test (#3821)
Also rename C++ test file to match class name.

Fixes #3818.
2021-12-22 22:27:51 -08:00
WarrenReynolds
6f91f37cd0 [examples] Fix SwerveControllerCommand order of Module States (#3815)
DriveSubsystem::SetModulesStates applies module state to incorrect modules.

Fixes #3814.
2021-12-22 12:26:02 -08:00
Peter Johnson
5158730b81 [wpigui] Upgrade to imgui 1.86, GLFW 3.3.6 (#3817)
The GLFW upgrade fixes gamepads not being mapped at startup.
2021-12-22 12:24:36 -08:00
Thad House
2ad2d2ca96 [wpiutil] MulticastServiceResolver: Fix C array returning functions (#3816) 2021-12-22 09:52:57 -08:00
Starlight220
b5fd29774f [wpilibj] Trigger: implement BooleanSupplier interface (#3811) 2021-12-21 11:33:16 -08:00
sciencewhiz
9f8f330e96 [wpilib] Fix Mecanum and SwerveControllerCommand when desired rotation passed (#3808) 2021-12-19 20:08:28 -08:00
Tyler Veness
1ad3b1b333 [hal] Don't copy byte to where null terminator goes (#3807)
Fixes the following compiler warning:
```
/__w/allwpilib/allwpilib/hal/src/main/native/sim/Notifier.cpp:323:21: error: 'char* strncpy(char*, const char*, size_t)' specified bound 64 equals destination size [-Werror=stringop-truncation]
         std::strncpy(arr[num].name, notifier->name.c_str(),
         ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                      sizeof(arr[num].name));
                      ~~~~~~~~~~~~~~~~~~~~~~
```
2021-12-19 16:46:12 -08:00
Thad House
dfc24425c3 [build] Fix gazebo gradle IDE warnings (#3806)
Also add note on how to generate all files for the IDE.
2021-12-19 14:20:08 -08:00
Thad House
c02577bb51 [glass] Configure delay loading for windows camera server support (#3803)
We don't currently support cameras in glass, but it's something we want to do in the future. However, when we do this, glass will completely stop working on N builds of windows, and it would fail to load at all with no messages. To solve this, we can delayload the media foundation dlls that are missing. The executable will then launch even without the dlls present, and we can attempt to load them at runtime and dynamically disable camera support.

When we get around to implementing it, we can just call HasCameraSupport, and dynamically hide all camera related code behind that flag.
2021-12-19 14:19:24 -08:00
sciencewhiz
c9e6a96a61 [wpilib] Document range of Servo angle (NFC) (#3796) 2021-12-19 13:53:31 -08:00
Thad House
9778626f34 [wpilib, hal] Add support for getting faults and versions from power distribution (#3794) 2021-12-19 13:42:49 -08:00
Thad House
34b2d0dae1 [wpilib, hal] High Level REV PH changes (#3792)
More functionality was implemented at the HAL level, so expose that to the wpilib level.

This also does units changes for all the PH related functionality.
2021-12-19 13:41:35 -08:00
Thad House
59a7528fd6 [cscore] Fix crash when usbcamera is deleted before message pump thread fully starts (#3804)
shared_from_this will assert if the shared pointer is in the middle of being destructed. Because we access shared_from_this in the message pump, this can easily occur. The solution is to grab the weak pointer, manually attempt to lock it, and only continue if that succeeds. The message pump is already synchronized to the usb camera being destructed, so this is a fine behavior.
2021-12-19 13:39:23 -08:00
Thad House
11d9859ef1 [build] Update plugins to remove log4j vulnerabilities (#3805) 2021-12-19 13:38:48 -08:00
Peter Johnson
e44ed752ad [glass] Fix CollapsingHeader in Encoder, PCM, and DeviceTree (#3797)
The new storage approach was attempting to save both the name and the
open status to the same storage key.
2021-12-19 07:35:12 -08:00
Thad House
52b2dd5b89 [build] Bump native utils to remove log4j (#3802) 2021-12-19 07:33:12 -08:00
sciencewhiz
c46636f218 [wpilib] Improve new counter classes documentation (NFC) (#3801) 2021-12-18 21:40:03 -08:00
sciencewhiz
dc531462e1 [build] Update to gradle 7.3.2 (#3800) 2021-12-18 21:34:35 -08:00
Tyler Veness
92ba98621c [wpimath] Add helper variable templates for units type traits (#3790) 2021-12-18 11:32:32 -08:00
sciencewhiz
d41d051f1b [wpilibc] Fix Mecanum & Swerve ControllerCommand lambda capture (#3795)
Fixes #3765
Also fixes SwerveControllerCommand example calling command twice.
2021-12-18 11:30:57 -08:00
sciencewhiz
c5ae0effac OtherVersions.md: Add one missing case of useLocal (#3788) 2021-12-15 20:30:34 -08:00
Tyler Veness
b3974c6ed3 [wpimath] Upgrade to Drake v0.37.0 (#3786) 2021-12-14 06:41:38 -08:00
Peter Johnson
589a00e379 [wpilibc] Start DriverStation thread from RobotBase (#3785)
With the change from GetInstance to static functions, many functions
don't call DriverStation::GetInstance(), so the DS thread wasn't
getting started by default.  Call InDisabled() to make sure this
happens.
2021-12-12 22:23:13 -08:00
Tyler Veness
8d9836ca02 [wpilib] Improve curvature drive documentation (NFC) (#3783) 2021-12-12 17:59:04 -08:00
Peter Johnson
8b5bf8632e [myRobot] Add wpimath and wpiutil JNI (#3784) 2021-12-12 17:57:52 -08:00
sciencewhiz
1846114491 [examples] Update references from characterization to SysId (NFC) (#3782) 2021-12-11 21:25:43 -08:00
Thad House
2c461c794e [build] Update to gradle 7.3 (#3778) 2021-12-10 21:26:28 -08:00
Jan-Felix Abellera
109363daa4 [hal] Add remaining driver functions for REVPH (#3776)
Add the remaining HAL functions needed to fully support the Pneumatic Hub and its latest firmware.

- Clear sticky faults
- Get device voltage
- Get 5v supply voltage (used for analog to PSI calculation)
- Get solenoid voltage
- Get solenoid current
- Get device firmware and hardware version

Some minor refactoring was done for naming of some internal functions for consistency purposes.
2021-12-09 12:29:09 -08:00
Jan-Felix Abellera
41d26bee8d [hal] Refactor REV PDH (#3775)
Refactors retrieving the faults from the device to match the implementation that we have for the Pneumatic Hub. Instead of having a getter function for each fault, there is a single function to get all faults (sticky or normal) for use with the higher level API

Renames functions to be consistent

Removes some functions that don't need to be included in wpilib:
- Identify device - this just flashes the module LED on the device and has no use in wpilib
- Is PDH enabled - the PDH does not change state depending on robot enabled state

PDH frame and signal names were updated in our DBC, and this PR makes use of the newly generated CAN frame helper functions
2021-12-09 12:27:06 -08:00
Tyler Veness
7269a170fb Upgrade maven deps to latest versions and fix new linter errors (#3772)
This also makes the Gradle build work with JDK 17.

The extra JVM args in gradle.properties works around a bug with spotless
and JDK 17: https://github.com/diffplug/spotless/issues/834

PMD.CloseResource was ignored because it's almost always a false
positive, and there are many of them.
2021-12-09 12:20:08 -08:00
Thad House
441f2ed9b0 [build] actions: use fixed image versions instead latest (#3761) 2021-12-09 12:12:59 -08:00
Modelmat
15275433d4 [examples] Fix duplicate port allocations in C++ SwerveBot/SwerveDrivePoseEstimator/RomiReference (#3773)
- Remove duplicate motor port (2) from C++ SwerveBot/SwerveDrivePoseEstimator

Java has the correct motor ports.

- Fix duplicate port allocation in C++ RomiReference by correcting if/else check

Java logic was already correct, and confirms this change.
2021-12-06 21:08:34 -08:00
Jason Daming
1ac02d2f58 [examples] Fix drive Joystick axes in several examples (#3769) 2021-12-06 16:40:10 -08:00
Jason Daming
8ee6257e92 [wpilib] DifferentialDrivetrainSim.KitbotMotor: Add NEO and Falcon 500 (#3762) 2021-12-06 14:46:58 -08:00
Prateek Machiraju
d81ef2bc5c [wpilib] Fix deadlocks in Mechanism2d et al. (#3770)
UpdateEntries() and Flush() are called from methods that lock the mutex,
so locking it again will cause deadlocks. This also updates the Java
code to make MechanismObject2d::update synchronized like in the C++
version.
2021-12-06 14:42:02 -08:00
Tyler Veness
acb64dff97 [wpimath] Make RamseteController::Calculate() more concise (#3763) 2021-12-06 12:57:42 -08:00
Jan-Felix Abellera
3f6cf76a8c [hal] Refactor REV PH CAN frames (#3756) 2021-12-06 10:08:57 -08:00
Peter Johnson
3ef2dab465 [wpilib] DutyCycleEncoder: add setting of duty cycle range (#3759)
As the sensor needs to maintain an actual duty cycle, it can't go all
the way from 0-100, so provide a way to set the min and max and linearly
map between the two.
2021-12-05 14:28:08 -08:00
sciencewhiz
a5a56dd067 Readme: Add Visual Studio 2022 (#3760) 2021-12-05 14:27:37 -08:00
Tyler Veness
04957a6d30 [wpimath] Fix units of RamseteController's b and zeta (#3757)
Fixes #3755.
2021-12-03 18:21:30 -08:00
Peter Johnson
5da54888f8 [glass] Upgrade imgui to 0.85, implot to HEAD, glfw to 3.3.5 (#3754)
This in particular upgrades the plot widget with a few new features
and makes more plot configuration persistent.
2021-12-03 17:23:18 -08:00
Thad House
6c93365b0f [wpiutil] MulticastService cleanup (#3750)
Fix duplicated constructors, and also use simpler utf conversion API on windows.
2021-12-02 21:06:55 -08:00
Thad House
1c4a8bfb66 [cscore] Cleanup Windows USB camera impl (#3751)
- Use wpiutil string conversion rather than codecvt (which is deprecated).
- Force A function types.
2021-12-02 13:48:03 -08:00
Thad House
d51a1d3b3d [rtns] Fix icon (#3749) 2021-11-30 21:58:58 -08:00
Thad House
aced2e7da6 Add roboRIO Team Number Setter tool (#3744) 2021-11-30 11:17:30 -08:00
Thad House
fa1ceca83a [wpilibj] Use DS cache for iterative robot control word cache (#3748)
The root cause of #3747 is CommandScheduler's ds state checks are behind iterative robots checks. This means that the iterative robot state could return enabled, but the DS cache could still be reporting disabled. This results in a race in the Disabled -> Enabled transition, which manifests in commands not running.

Previously, iterative robot base pulled from the DS cache. This meant that the ds cache was always updated before an iterative robot base loop could run. This still had a race, but this could only occur on the Enabled -> Disable transition, which is much less noticeable and would usually just result in a command running for an extra loop.

We can move back to the old behavior by grabbing the new iterative robot base check variables to use the DS cache.
2021-11-29 20:56:58 -08:00
sciencewhiz
0ea05d34e6 [build] Update to gradle 7.2 (#3746) 2021-11-29 20:53:26 -08:00
Thad House
09db4f672b [build] Update to native utils 2022.6.1 (#3745) 2021-11-29 13:04:08 -08:00
Thad House
4ba80a3a8c [wpigui] Don't recursively render frames in size callback (#3743)
WindowSizeCallback can sometimes be called while doing a render. If this occurs, imgui asserts. Avoid this case.
2021-11-28 01:03:40 -08:00
Peter Johnson
ae208d2b17 [wpiutil] StringExtras: Add substr() (#3742)
Unlike std::string and std::string_view, this substr() allows a start
greater than the length of the string, in which case an empty string
is returned.  This matches llvm::StringRef behavior.
2021-11-27 21:31:40 -08:00
Thad House
6f51cb3b98 [wpiutil] MulticastResolver: make event manual reset, change to multiple read (#3736) 2021-11-27 11:16:24 -08:00
Peter Johnson
f6159ee1a2 [glass] Fix Drive widget handling of negative rotation (#3739)
This would crash in debug mode due to an imgui assertion in PathArcTo.
2021-11-27 10:58:45 -08:00
Thad House
7f401ae895 [build] Update NI libraries to 2022.2.3 (#3738) 2021-11-27 09:43:07 -08:00
Peter Johnson
0587b7043a [glass] Use JSON files for storage instead of imgui ini
Storage is now nested.

Separate "roots" can be configured which save to separate files.
In particular, this is used to save wpigui and ImGui window position
to a -window.json file.

ImGui's ini (for window position) is mapped to JSON.

You can optionally specify a directory to load from on the command line.
If one isn't provided, it uses the global system directory.
Any changes made are automatically saved here.

Workspace | Open: select directory, the current layout is replaced with that
workspace, and future auto-saves also switch to that location. The main
window size/location is not changed, only the contents.

Workspace | Save As: select directory, the current layout is saved there,
and future auto-saves also switch to that location.

Workspace | Reset: window locations are preserved, but all other settings
are reset to default (including e.g. removing plot windows). This will also
end up clearing the current save file. as with load, the main window
size/location is not changed.

Workspace | Save As Global: "save as" to the global system location

Notably, the main window size/location is only loaded at startup, but is
auto-saved as part of the current workspace.
2021-11-27 00:12:13 -08:00
Peter Johnson
0bbf51d566 [wpigui] Change maximized to bool 2021-11-27 00:12:13 -08:00
Peter Johnson
92c6eae6b0 [wpigui] PFD: Add explicit to constructors 2021-11-27 00:12:13 -08:00
Peter Johnson
141354cd79 [wpigui] Add hooks for custom load/save settings
Add GetPlatformSaveFileDir().
2021-11-27 00:12:13 -08:00
Thad House
f6e9fc7d71 [wpiutil] Handle multicast service collision on linux (#3734) 2021-11-26 23:20:54 -08:00
Peter Johnson
d8418be7d1 [glass, outlineviewer] Return 0 from WinMain (#3735)
While this is implicit in main(), WinMain() requires an explicit return.
2021-11-26 23:19:45 -08:00
Thad House
82066946e5 [wpiutil] Add mDNS resolver and announcer (#3733) 2021-11-25 22:08:26 -08:00
Thad House
4b1defc8d8 [wpilib] Remove automatic PD type from module type enum (#3732)
Using automatic type doesn't work with any module number, so the API was confusing.
2021-11-23 23:03:45 -08:00
Oblarg
da90c1cd2c [wpilib] Add bang-bang controller (#3676)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-11-23 20:34:46 -08:00
Thad House
3aa54fa027 [wpilib] Add new counter implementations (#2447) 2021-11-23 20:33:36 -08:00
Thad House
b156db400d [hal, wpilib] Incorporate pneumatic control type into wpilibc/j (#3728) 2021-11-23 20:32:02 -08:00
sciencewhiz
9aba2b7583 [oldCommands] Add wrappers for WPILib objects to work with old PID Controller (#3710) 2021-11-23 20:30:30 -08:00
Jan-Felix Abellera
a9931223f0 [hal] Add REV PH faults (#3729) 2021-11-22 21:15:32 -08:00
Tyler Veness
aacf9442e4 [wpimath] Fix units typo in LinearSystemId source comment (#3730) 2021-11-22 21:14:38 -08:00
Tyler Veness
7db10ecf00 [wpilibc] Make SPI destructor virtual since SPI contains virtual functions (#3727) 2021-11-20 11:21:02 -08:00
Tyler Veness
a0a5b2aea5 [wpimath] Upgrade to EJML 0.41 (#3726) 2021-11-20 01:02:37 -08:00
Jan-Felix Abellera
eb835598a4 [hal] Add HAL functions for compressor config modes on REV PH (#3724) 2021-11-20 01:02:23 -08:00
Tyler Veness
f0ab6df5b6 [wpimath] Upgrade to Drake v0.36.0 (#3722) 2021-11-16 14:37:29 -08:00
sciencewhiz
075144faa3 [docs] Parse files without extensions with Doxygen (#3721)
Fixes inclusion of wpi::numbers and some Eigen files
2021-11-16 11:22:34 -08:00
Thad House
32468a40cb [hal] Remove use of getDmaDescriptor from autospi (#3717)
It’s not necessary, as the index equals the channel.
2021-11-13 08:55:21 -08:00
Vasista Vovveti
38611e9dd7 [hal] Fix REVPH Analog Pressure channel selection (#3716) 2021-11-10 18:22:18 -08:00
sciencewhiz
4d78def31e [wpilib] Add DeadbandElimination forwarding to PWMMotorController (#3714) 2021-11-09 21:24:47 -08:00
Tyler Veness
3be0c1217a [wpilibcExamples] Make GearsBot use idiomatic C++ (#3711)
Replace pointer constructor arguments with references, and const qualify
getters where possible.

Also remove redundant simulation P gain.

Fixes #1146.
2021-11-09 20:11:50 -08:00
Tyler Veness
42d3a50aa2 [hal] Check error codes during serial port initialization (#3712)
Throw if serial port init fails.

Fixes #2036.
2021-11-09 20:10:48 -08:00
PJ Reiniger
52f1464029 Add project with field images and their json config files (#3668) 2021-11-08 22:48:16 -08:00
Thad House
68ce62e2e9 [hal] Add autodetect for power modules (#3706)
Default autodetect to REV if no devices are found, as only the REV devices have control functionality (the switchable output).
2021-11-07 13:53:38 -08:00
Thad House
3dd41c0d37 [wpilib] Don't print PD errors for LiveWindow reads (#3708)
If something happens with the PD connection, these would have spammed messages continuously.
This wasn't the case previously, and we don't want this behavior now.
2021-11-07 13:45:28 -08:00
Thad House
7699a1f827 [hal] Fix sim not working with automatic PD type and default module (#3707) 2021-11-05 23:30:10 -07:00
Peter Johnson
e473a00f97 [wpiutil] Base64: Add unsigned span/vector variants (#3702) 2021-11-01 07:48:26 -07:00
Peter Johnson
52f2d580eb [wpiutil] raw_uv_ostream: Add reset() (#3701)
This enables reuse of a raw_uv_ostream object.
2021-11-01 07:47:13 -07:00
Peter Johnson
d7b1e3576f [wpiutil] WebSocket: move std::function (#3700) 2021-11-01 07:46:15 -07:00
sciencewhiz
93799fbe9d [examples] Fix description of TrapezoidProfileSubsystem (#3699) 2021-11-01 00:08:53 -07:00
Tyler Veness
b84644740d [wpimath] Document pose estimator states, inputs, and outputs (#3698)
Fixes #3244.
2021-10-29 17:37:13 -07:00
Tyler Veness
2dc35c1399 [wpimath] Fix classpaths for JNI class loads (#3697)
Found by inspecting the results of the following rg commands:
`rg --multiline 'FindClass\(\s*"'`
`rg 'JClass' -A 1`

Fixes #3660.
2021-10-29 16:23:46 -07:00
Tyler Veness
2cb171f6f5 [docs] Set Doxygen extract_all to true and fix Doxygen failures (#3695)
The template argument order for UnscentedTransform was reversed to match
all the other UKF classes. Since UnscentedTransform is intended as a
class for internal use only, this shouldn't cause much breakage.
2021-10-29 15:07:05 -07:00
Tyler Veness
a939cd9c89 [wpimath] Print uncontrollable/unobservable models in LQR and KF (#3694)
IsDetectable() was added to make the code easier to read.
2021-10-29 00:03:02 -07:00
Tyler Veness
d5270d113b [wpimath] Clean up C++ StateSpaceUtil tests (#3692) 2021-10-29 00:02:03 -07:00
Tyler Veness
b20903960b [wpimath] Remove redundant discretization tests from StateSpaceUtilTest (#3689)
DiscretizationTest already does these.
2021-10-29 00:01:41 -07:00
Tyler Veness
c0cb545b41 [wpilibc] Add deprecated Doxygen attribute to SpeedController (#3691)
Fixes #3690.
2021-10-29 00:01:04 -07:00
Tyler Veness
35c9f66a75 [wpilib] Rename PneumaticsHub to PneumaticHub (#3686)
Fixes #3684.
2021-10-29 00:00:31 -07:00
Tyler Veness
796d03d105 [wpiutil] Remove unused LLVM header (#3688) 2021-10-28 00:18:26 -07:00
Tyler Veness
8723caf78d [wpilibj] Make Java TrapezoidProfile.Constraints an immutable class (#3687) 2021-10-28 00:17:36 -07:00
Tyler Veness
187f50a344 [wpimath] Catch incorrect parameters to state-space models earlier (#3680)
This allows giving more descriptive exceptions than if they are thrown
later in KalmanFilter, for example.

Fixes #3678.
2021-10-27 20:18:57 -07:00
Tyler Veness
8d04606c4d Replace instances of frc-characterization with SysId (NFC) (#3681) 2021-10-27 06:40:17 -07:00
Peter Johnson
b82d4f6e58 [hal, cscore, ntcore] Use WPI common handle type base 2021-10-26 23:39:11 -07:00
Peter Johnson
87e34967ef [wpiutil] Add synchronization primitives
These enable more consistent use of synchronization across the
native libraries.  Users can create Event and Semaphore primitives, but
in addition, libraries can set up any handle as an Event-type signal.
2021-10-26 23:39:11 -07:00
Peter Johnson
e32499c546 [wpiutil] Add ParallelTcpConnector (#3655)
This is a libuv-based parallel, repeating TCP connector for making
multiple parallel DNS resolution and TCP connection attempts to a
network server.
2021-10-26 23:37:58 -07:00
Tyler Veness
aa0b49228d [wpilib] Remove redundant "quick turn" docs for curvature drive (NFC) (#3674)
The parameter docs for allowTurnInPlace say the same thing, and it's no
longer called "quick turn".
2021-10-26 23:37:11 -07:00
Noah Andrews
57301a7f9c [hal] REVPH: Start closed-loop compressor control on init (#3673)
Similar to the PCM, we're going to make the PH not do anything with the compressor until the PH HAL object has been initialized. The mechanism we're going to use to signal to the PH that that has happened is to begin sending the state of the solenoids (which will all be set to off at this point).
2021-10-26 23:36:47 -07:00
sciencewhiz
d1842ea8fb [wpilib] Improve interrupt docs (NFC) (#3679) 2021-10-26 23:35:01 -07:00
Peter Johnson
558151061e [wpiutil] Add DsClient (#3654)
This is a libuv-based implementation of the Driver Station client
for getting robot IPs from the Driver Station port 1742 server.
2021-10-26 23:34:27 -07:00
Tyler Veness
181723e573 Replace .to<double>() and .template to<double>() with .value() (#3667)
It's a less verbose way to do the same thing.
2021-10-25 08:58:12 -07:00
sciencewhiz
6bc1db44bc [commands] Add pointer overload of AddRequirements (artf6003) (#3669)
Also update documentation in CommandBase.
2021-10-25 08:57:22 -07:00
Tyler Veness
737b57ed5f [wpimath] Update to drake v0.35.0 (#3665) 2021-10-22 23:02:08 -07:00
Austin Shalit
4d287d1ae2 [build] Upgrade WPIJREArtifact to JRE 2022-11.0.12u5 (#3666) 2021-10-22 23:01:09 -07:00
apple
f26eb5ada4 [hal] Fix another typo (get -> gets) (NFC) (#3663) 2021-10-22 11:49:21 -07:00
apple
94ed275ba6 [hal] Fix misspelling (numer -> number) (NFC) (#3662) 2021-10-22 07:23:13 -07:00
Peter Johnson
ac2f44da33 [wpiutil] uv: use move for std::function (#3653)
Also use function_ref for Loop::Walk().
2021-10-20 23:24:59 -07:00
Peter Johnson
75fa1fbfbf [wpiutil] json::serializer: Optimize construction (#3647)
Remove unused locale pointer.
2021-10-20 21:09:04 -07:00
Peter Johnson
5e689faea8 [wpiutil] Import MessagePack implementation (mpack) (#3650) 2021-10-20 21:08:31 -07:00
Peter Johnson
649a50b401 [wpiutil] Add LEB128 byte-by-byte reader (#3652)
This is needed for compatibility with streaming data (e.g. libuv) where partial data
may be received.  Also add raw_ostream writer.
2021-10-20 18:50:20 -07:00
Peter Johnson
e94397a97d [wpiutil] Move json_serializer.h to public headers (#3646)
This makes it possible to do "manual" JSON-compliant serialization more efficiently
(e.g. without needing to construct a full json object).
2021-10-20 11:18:13 -07:00
Peter Johnson
4ec58724d7 [wpiutil] uv::Tcp: Clarify SetNoDelay documentation (#3649) 2021-10-20 08:46:44 -07:00
Peter Johnson
8cb294aa4a [wpiutil] WebSocket: Make Shutdown() public (#3651) 2021-10-20 08:45:58 -07:00
Peter Johnson
2b3a9a52b3 [wpiutil] json: Fix map iterator key() for std::string_view (#3645) 2021-10-20 08:45:16 -07:00
Peter Johnson
138cbb94b2 [wpiutil] uv::Async: Add direct call for no-parameter specialization (#3648) 2021-10-20 08:44:33 -07:00
sciencewhiz
e56d6dea81 [ci] Update testbench pool image to ubuntu-latest (#3643) 2021-10-18 21:39:43 -07:00
sciencewhiz
43f30e44e4 [build] Enable comments in doxygen source files (#3644) 2021-10-18 21:39:22 -07:00
sciencewhiz
9e6db17ef4 [build] Enable doxygen preprocessor expansion of WPI_DEPRECATED (#3642)
This fixes documentation for SpeedController and SpeedControllerGroup
2021-10-18 21:29:23 -07:00
sciencewhiz
0e631ad2f2 Add WPILib version to issue template (#3641) 2021-10-18 09:09:57 -07:00
Austin Shalit
6229d8d2ff [build] Docs: set case_sense_names to false (#3392)
This means the output will be consistent for all 3 major os and prevent case issues when sharing files.
2021-10-15 00:37:59 -07:00
Tyler Veness
4647d09b50 [docs] Fix Doxygen warnings, add CI docs lint job (#3639)
The CI docs lint build is configured to fail on Doxygen warnings.
2021-10-14 18:09:38 -07:00
sciencewhiz
4ad3a54026 [hal] Fix PWM allocation channel (#3637)
Previously it showed 31 when 0 was doubly allocated
2021-10-14 07:28:49 -07:00
sciencewhiz
05e5feac41 [docs] Fix brownout docs (NFC) (#3638) 2021-10-14 07:28:21 -07:00
Prateek Machiraju
67df469c58 [examples] Remove old command-based templates and examples (#3263)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-10-13 19:17:58 -07:00
Thad House
689e9ccfb5 [hal, wpilib] Add brownout voltage configuration (#3632) 2021-10-13 19:14:27 -07:00
sciencewhiz
9cd4bc407a [docs] Add useLocal to avoid using installer artifacts (#3634) 2021-10-13 10:38:33 -07:00
Peter Johnson
61996c2bbf [cscore] Fix Java direct callback notifications (#3631)
These relied on the OnStart and OnExit callbacks which were not present
in the wpiutil common CallbackManager code.  Add support for these and
fix up other use cases.

Also fixes notifications to correctly filter on event kind.

This fixes a breakage caused by #3133.
2021-10-13 08:46:07 -07:00
Thad House
6d3dd99eb2 [build] Update to newest native-utils (#3633) 2021-10-13 07:47:10 -07:00
Tyler Veness
f0b484892c [wpiutil] Fix StringMap iterator equality check (#3629)
This fixes the following warning.
The member function operator== only works in C++17, and the friend operator== only works in C++20.

```
 /Users/runner/.gradle/caches/transforms-2/files-2.1/c671f5a5dff922b8870f4eb33f4c8e2a/wpiutil-cpp-2022.1.1-alpha-3-1-g4e3fd7d-headers/wpi/json.h:1847:46: warning: ISO C++20 considers use of overloaded operator '==' (with operand types 'const typename json::object_t::iterator' (aka 'const StringMapIterator<wpi::json>') and 'const typename json::object_t::iterator') to be ambiguous despite there being a unique best viable function [-Wambiguous-reversed-operator]
                return (m_it.object_iterator == other.m_it.object_iterator);
                        ~~~~~~~~~~~~~~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/runner/.gradle/caches/transforms-2/files-2.1/c671f5a5dff922b8870f4eb33f4c8e2a/wpiutil-cpp-2022.1.1-alpha-3-1-g4e3fd7d-headers/wpi/json.h:1863:20: note: in instantiation of member function 'wpi::detail::iter_impl<const wpi::json>::operator==' requested here
        return not operator==(other);
                   ^
/Users/runner/.gradle/caches/transforms-2/files-2.1/c671f5a5dff922b8870f4eb33f4c8e2a/wpiutil-cpp-2022.1.1-alpha-3-1-g4e3fd7d-headers/wpi/json.h:5008:20: note: in instantiation of member function 'wpi::detail::iter_impl<const wpi::json>::operator!=' requested here
            if (it != end())
                   ^
/Users/runner/.gradle/caches/transforms-2/files-2.1/c671f5a5dff922b8870f4eb33f4c8e2a/wpiutil-cpp-2022.1.1-alpha-3-1-g4e3fd7d-headers/wpi/json.h:5025:16: note: in instantiation of function template specialization 'wpi::json::value<std::basic_string<char>, 0>' requested here
        return value(key, std::string(default_value));
               ^
/Users/runner/.gradle/caches/transforms-2/files-2.1/c671f5a5dff922b8870f4eb33f4c8e2a/wpiutil-cpp-2022.1.1-alpha-3-1-g4e3fd7d-headers/wpi/StringMap.h:442:8: note: ambiguity is between a regular call to this operator and a call with the argument order reversed
  bool operator==(const DerivedTy &RHS) const { return Ptr == RHS.Ptr; }
       ^
```
2021-10-12 23:28:26 -07:00
Lucas
8352cbb7a3 Update development build instructions for 2022 (#3616)
Updates the instructions for development and local WPILib builds as per the GradleRIO 2022 updates.
2021-10-12 22:47:16 -07:00
sciencewhiz
6da08b71dc [examples] Fix Intermediate Vision Java Example description (#3628)
Copy from C++
2021-10-11 22:55:33 -07:00
Peter Johnson
5d99059bf9 [wpiutil] Remove optional.h (#3627)
This has been replaced fully by std::optional and deprecated for a year.
2021-10-11 22:54:33 -07:00
Tyler Veness
fa41b106ab [glass, wpiutil] Add missing format args (#3626)
These were caught by compile-time format string parsing in C++20.
2021-10-11 22:54:20 -07:00
Thad House
4e3fd7d420 [build] Enable Zc:__cplusplus for Windows (#3625)
This makes the version actually be correct.
2021-10-11 20:30:22 -07:00
Starlight220
791d8354da [build] Suppress deprecation/removal warnings for old commands (#3618) 2021-10-10 20:07:12 -07:00
Thad House
10f19e6fc3 [hal, wpilib] Add REV PneumaticsHub (#3600) 2021-10-10 20:04:50 -07:00
Peter Johnson
4c61a13057 [ntcore] Revert to per-element copy for toNative() (#3621)
arraycopy() does not unbox values, so throws an exception.

This was broken in #3419 due to a false positive in PMD
(see https://sourceforge.net/p/pmd/bugs/804/).
2021-10-10 15:53:35 -07:00
Peter Johnson
7b3f62244f [wpiutil] SendableRegistry: Print exception stacktrace (#3620) 2021-10-10 15:53:11 -07:00
Thad House
d347928e4d [hal] Use better error for when console out is enabled while attempting to use onboard serial port (#3622) 2021-10-10 15:52:50 -07:00
Tyler Veness
cc31079a11 [hal] Use setcap instead of setuid for setting thread priorities (#3613)
We originally moved to setuid admin so user programs could do other
things requiring admin if they wanted. However, these things, like
setting RT priorities of other processes, can usually be done instead as
admin during the GradleRIO 2022 deploy process, or adding commands to
the robotCommand script. By going back to setcap, we can simplify the
HAL code.
2021-10-04 09:49:34 -07:00
Tyler Veness
4676648b78 [wpimath] Upgrade to Drake v0.34.0 (#3607) 2021-09-29 15:39:47 -07:00
Thad House
c7594c9111 [build] Allow building wpilibc in cmake without cscore and opencv (#3605)
The hard dependency on cscore was removed a while ago in gradle, so make it not a hard requirement in cmake.
2021-09-27 21:37:04 -07:00
Tyler Veness
173cb7359d [wpilib] Add TimesliceRobot (#3502) 2021-09-26 13:56:33 -07:00
Tyler Veness
af295879fb [hal] Set error status for I2C port out of range (#3603)
Closes #1369.
2021-09-26 10:38:17 -07:00
Tyler Veness
95dd20a151 [build] Enable spotbugs (#3601)
Benign spotbugs warnings were suppressed, and all others were fixed. Bug
descriptions are documented here:
https://spotbugs.readthedocs.io/en/stable/bugDescriptions.html

Co-authored-by: Austin Shalit <austinshalit@gmail.com>
2021-09-24 16:04:02 -07:00
Tyler Veness
b65fce86bf [wpilib] Remove Timer lock in wpilibj and update docs (#3602)
Timer reports a negative duration if the sim timing is restarted. This
can be worked around by calling Reset(). Other options included:

1. Have RestartTiming() call Timer::Reset() on a list of instantiated
   Timers.
2. Have Timer::Get() reset the timer if it notices time went backwards.
   This requires dropping const qualification though, which is a
   breaking change that only fixes a minor edge case.

Closes #2732.
2021-09-24 16:01:13 -07:00
Tyler Veness
3b8d3bbcbf Remove unused and add missing deprecated.h includes (#3599)
I generated lists of includes and uses via
`rg -l deprecated.h | sort -u` and `rg -l WPI_DEPRECATED | sort -u`
respectively. If a file was in the first list but not the second, the
include was unused. If a file was in the second list but not the first,
the include needed to be added.
2021-09-22 18:29:57 -07:00
Tyler Veness
f9e976467f [examples] Rename DriveTrain classes to Drivetrain (#3594)
Drivetrain is one word, not two.
2021-09-22 13:27:26 -07:00
Tyler Veness
118a27be2f [wpilib] Add Timer tests (#3595) 2021-09-22 13:26:58 -07:00
Tyler Veness
59c89428e5 [wpilib] Deprecate Timer::HasPeriodPassed() (#3598)
AdvanceIfElapsed() is safer to use, as it has less surprising side effects.
2021-09-22 13:01:37 -07:00
Tyler Veness
202ca5e782 Force C++17 in .clang-format (#3597) 2021-09-22 10:04:03 -07:00
Tyler Veness
d6f185d8e5 Rename tests for consistency (#3592)
I started with the output of styleguide#217, then renamed a few classes
to fix compilation.

ntcore's StorageTest needed some manual renaming since it put the Test
word in the middle instead of at the end.

One limitation of wpiformat is test cases that were only named "Test"
were unmodified, and an error was generated. These test cases were
manually given more descriptive names:

* TimedRobotTest mode test cases had "Mode" appended to the name. Java
  tests were renamed to match.
* UvAsyncTest and UvAsyncFunctionTest cases were given alternate names
2021-09-21 06:12:50 -07:00
Tyler Veness
54ca474dba [ci] Enable asan and tsan in CI for tests that pass (#3591)
ctest's -E flag skips tests that match a regular expression.
2021-09-19 20:03:40 -07:00
Tyler Veness
1ca383b23b Add Debouncer (#3590)
Supersedes #2358 with updates and cleanups.

Closes #2482 and closes #2487 because we shouldn't support both
time-based and count-based debouncing approaches.

Co-authored-by: oblarg <emichaelbarnett@gmail.com>
2021-09-19 19:58:16 -07:00
Thad House
179fde3a7b [build] Update to 2022 native utils and gradle 7 (#3588) 2021-09-19 17:59:14 -07:00
sciencewhiz
50198ffcf1 [examples] Add Mechanism2d visualization to Elevator Sim (#3587) 2021-09-18 22:06:14 -07:00
sciencewhiz
a446c25598 [examples] Synchronize C++ and Java Mechanism2d examples (#3589)
- Synchronize dimensions
- Make both joints different colors for clarity
2021-09-18 22:05:35 -07:00
Tyler Veness
a7fb831035 [ci] clang-tidy: Generate compilation commands DB with Gradle (#3585) 2021-09-18 10:19:34 -07:00
sciencewhiz
4f5e0c9f85 [examples] Update ArmSimulation example to use Mechanism2d (#3572)
- Correct several comments that referenced elevator
- Changed noise to be 1 encoder tick instead of half a degree
- Changed gear ratio and PID value to be better tuned
- Updated bounds to be similar to a single jointed arm
2021-09-17 22:55:31 -07:00
Tyler Veness
8164b91dc4 [CI] Print CMake test output on failure (#3583) 2021-09-17 22:54:47 -07:00
sciencewhiz
4d5fca27ef [wpilib] Impove Mechanism2D documentation (NFC) (#3584) 2021-09-17 22:54:10 -07:00
Tyler Veness
fe59e4b9fe Make C++ test names more consistent (#3586)
Inconsistent names were found using the following regular expressions.

* `rg "TEST(_F|_P)?\(\w+,\s+\w+Test\)"`
* `rg "TEST(_F|_P)?\(\w+,\s+Test\w+\)"`
* `rg "TEST(_F|_P)?\(\w+Tests,\s+\w+\)"`

Fixes #3495.
2021-09-17 22:51:51 -07:00
sciencewhiz
5c88685495 [wpilibc] Fix C++ MechanisimRoot2D to use same NT entries as Java/Glass (#3582)
Fixes #3578
2021-09-17 12:13:36 -07:00
Tyler Veness
9359431bad [wpimath] Clean up Eigen usage
* Replace Matrix<> with Vector<> where vectors are explicitly intended.
  I found these via `rg "Eigen::Matrix<double, \w+, 1>"`.
* Pass all Eigen matrices by const reference. I found these via `rg
  "\(Eigen"` on main (the initializer list constructors make more false
  positives).
* Replace MakeMatrix() and operator<< usage with initializer list
  constructors. I found these via `rg MakeMatrix` and `rg "<<"`
  respectively.
* Deprecate MakeMatrix()
2021-09-17 12:12:19 -07:00
Tyler Veness
72716f51ce [wpimath] Upgrade to Eigen 3.4 2021-09-17 12:12:19 -07:00
Thad House
382deef750 [wpimath] Explicitly export wpimath symbols
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-09-17 12:12:19 -07:00
Peter Johnson
161e211734 [ntcore] Match standard handle layout, only allow 16 instances (#3577)
Now that there are only 16 instances, store them all statically.

Make tests more reliable by using different ports for each connection in listener tests.
2021-09-17 12:11:00 -07:00
Peter Johnson
263a248119 [wpimath] Use jinja for codegen (#3574)
While not really needed for wpimath, it will make more complex codegen
in the future significantly easier.
2021-09-17 00:10:29 -07:00
Tyler Veness
725251d294 [wpilib] Increase tolerances of DifferentialDriveSimTest (#3581) 2021-09-16 23:42:46 -07:00
Tyler Veness
4dff873013 [wpimath] Make LinearFilter::Factorial() constexpr (#3579)
Since BackwardFiniteDifference() gives it a compile-time constant, it
can be evaluated in a constexpr context.
2021-09-16 20:45:24 -07:00
Thad House
60ede67abd [hal, wpilib] Switch PCM to be a single object that is allowed to be duplicated (#3475)
Having PCM as a singleton is a problem, as multiple things need to use it, and that gets really ugly. This changes PCM's to be a reference counted object, that can be passed around and constructed from multiple places.

In Java, this is using a map to hold a data store with a ref count, and allocating new objects any time a duplicate is requested.

In C++, this uses a trick constructor to store a PCM instance in the data store itself. This instance can then be passed to base objects using std::shared_ptr's aliasing constructor, which means constructing a solenoid from a PCM is not allocating after the 1st one.

This did require removing sendable from PCM. A compressor class was added back in to act as sendable for the PCM.

After this change is finished, the only change RobotBuilder and Team Code would require is passing a module type to solenoid constructors.

Co-authored-by: sciencewhiz <sciencewhiz@users.noreply.github.com>
2021-09-16 18:50:27 -07:00
Tyler Veness
906bfc8464 [build] Add CMake build support for sanitizers (#3576)
* Address sanitizer uses -DCMAKE_BUILD_TYPE=Asan
* Thread sanitizer uses -DCMAKE_BUILD_TYPE=Tsan
* Undefined behavior sanitizer uses -DCMAKE_BUILD_TYPE=Ubsan

Only ubsan is enabled in CI for now because asan and tsan report
failures.
2021-09-16 18:48:41 -07:00
Ryan Hirasaki
0d4f08ad9c [hal] Simplify string copy of joystick name (#3575) 2021-09-16 09:32:57 -07:00
Peter Johnson
a52bf87b7d [wpiutil] Add Java function package (#3570)
The standard Java package is missing BooleanConsumer as well as Float classes.

Update SendableBuilder to use it instead of internal BooleanConsumer
interface.
2021-09-15 21:36:11 -07:00
Peter Johnson
40c7645d6e [wpiutil] UidVector: Return old object from erase() (#3571)
This makes it possible to erase and then do additional cleanup (e.g. on a unique_ptr).
2021-09-15 21:35:20 -07:00
Peter Johnson
5b886a23fd [wpiutil] jni_util: Add size, operator[] to JArrayRef (#3569)
These make it usable more like a standard container.
2021-09-15 21:34:16 -07:00
Tyler Veness
65797caa7b [sim] Fix halsim_ds_socket stringop overflow warning from GCC 10 (#3568)
Fixes #3567.
2021-09-14 20:49:02 -07:00
Thad House
66abb39880 [hal] Update runtime enum to allow selecting roborio 2 (#3565)
In some cases, knowing roborio 2 might be useful. This also creates a higher level enum that might be usable later for the discussion on more complex runtime types.
2021-09-13 22:05:38 -07:00
Thad House
95a12e0ee8 [hal] UidSetter: Don't revert euid if its already current value (#3566)
When running from admin account, this hangs for 5-10 seconds.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-09-13 21:08:39 -07:00
Tyler Veness
27951442b8 [wpimath] Use external Eigen headers only (#3564)
Internal headers are no longer allowed as of
https://gitlab.com/libeigen/eigen/-/merge_requests/631. Based on
benchmarking I conducted in that thread, there doesn't seem to be a
performance penalty for including the full headers anymore.
2021-09-13 14:31:01 -07:00
Austin Shalit
c42e053ae9 [docs] Update to doxygen 1.9.2 (#3562) 2021-09-12 15:19:04 -07:00
sciencewhiz
e7048c8c8b [docs] Disable doxygen linking for common words that are also classes (#3563)
Add % in front of name in order to suppress doxygen link creation. https://www.doxygen.nl/manual/autolink.html
2021-09-12 15:18:45 -07:00
Thad House
d8e0b6c977 [wpilibj] Fix java async interrupts (#3559) 2021-09-11 09:21:02 -07:00
Thad House
5e6c34c61c Update to 2022 roborio image (#3537) 2021-09-10 13:00:58 -07:00
Tyler Veness
828f073ebd [wpiutil] Fix uv::Buffer memory leaks caught by asan (#3555) 2021-09-09 23:14:10 -07:00
Tyler Veness
2dd5701ac0 [cscore] Fix mutex use-after-free in cscore test (#3557)
Fixes #3546.
2021-09-09 23:13:56 -07:00
Tyler Veness
531439198e [ntcore] Fix NetworkTables memory leaks caught by asan (#3556)
Closes #3543.
2021-09-09 23:13:36 -07:00
Tyler Veness
3d9a4d585e [wpilibc] Fix AnalogTriggerOutput memory leak reported by asan (#3554)
Fixes #3542.

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
2021-09-09 19:32:00 -07:00
Tyler Veness
54eda59286 [wpiutil] Ignore ubsan vptr upcast warning in SendableHelper moves (#3553)
The move ctor is trying to cast from e.g. SendableHelper to PIDController before PIDController has been constructed, which is potentially UB. We don't actually use anything in PIDController though, so it's OK in our case.
2021-09-09 12:33:50 -07:00
sciencewhiz
5a4f75c9f8 [wpilib] Replace Speed controller comments with motor controller (NFC) (#3551)
Makes comments consistent with #3302
2021-09-08 22:09:08 -07:00
Tyler Veness
7810f665f1 [wpiutil] Fix bug in uleb128 (#3540)
Caused by UB in left shift; identified by ubsan.
2021-09-08 16:24:28 -07:00
sciencewhiz
697e2dd330 [wpilib] Fix errant jaguar reference in comments (NFC) (#3550) 2021-09-08 14:18:37 -07:00
sciencewhiz
936c64ff51 [docs] Enable -linksource for javadocs (#3549)
Embeds source in javadocs.
Fixes #3547
2021-09-07 22:46:09 -07:00
Tyler Veness
1ea6549548 [build] Upgrade CMake build to googletest 1.11.0 (#3548)
This upgrade uncovered two issues:

ntcore wasn't forcing C++17, which caused a linker error with googletest
Matcher symbols:
```
undefined reference to `testing::Matcher<std::basic_string_view<char, std::char_traits<char> > >::Matcher(std::basic_string_view<char, std::char_traits<char> >)'
```

test_span.cpp wasn't including <algorithm> to use std::sort() and
std::is_sorted().
2021-09-07 13:29:31 -07:00
Tyler Veness
32d9949e4d [wpimath] Move controller tests to wpimath (#3541) 2021-09-06 17:00:13 -07:00
Ryan Hirasaki
01ba56a8a6 [hal] Replace strncpy with memcpy (#3539) 2021-09-05 20:47:40 -07:00
Tyler Veness
e109c42515 [build] Rename makeSim flag to forceGazebo to better describe what it does (#3535) 2021-09-05 17:40:54 -07:00
Noam Zaks
e4c7091647 [docs] Use a doxygen theme and add logo (#3533) 2021-09-02 21:59:16 -07:00
Tyler Veness
960b6e5897 [wpimath] Fix Javadoc warning (#3532) 2021-08-28 22:43:38 -07:00
Jan-Felix Abellera
82eef8d5ee [hal] Remove over current fault HAL functions from REV PDH (#3526) 2021-08-28 20:52:46 -07:00
Tyler Veness
aa3848b2c8 [wpimath] Move RobotDriveBase::ApplyDeadband() to MathUtil (#3529)
It's a useful function outside of the drive classes.

For backwards compatibility, deprecate (rather than remove) RobotDriveBase.applyDeadband()
2021-08-28 20:52:05 -07:00
Tyler Veness
3b5d0d141a [wpimath] Add LinearFilter::BackwardFiniteDifference() (#3528)
This is an alternative to #2344 that handles arbitrary order derivatives
of arbitrary precision. The downside is that since it's part of
LinearFilter, it can't utilize the units type system in the same way to
make Calculate()'s input type different from its output type.
2021-08-28 20:50:18 -07:00
Tyler Veness
c8fc715fe2 [wpimath] Upgrade drake files to v0.33.0 (#3531) 2021-08-28 20:49:19 -07:00
Tyler Veness
e5fe3a8e16 [build] Treat javadoc warnings as errors in CI and fix warnings (#3530) 2021-08-28 20:48:47 -07:00
Tyler Veness
e0c6cd3dcc [wpimath] Add an operator for composing two Transform2ds (#3527) 2021-08-23 20:22:48 -07:00
PJ Reiniger
2edd510ab7 [sim] Add sim wrappers for sensors that use SimDevice (#3517) 2021-08-20 23:19:59 -07:00
Tyler Veness
2b3e2ebc11 [hal] Fix HAL Notifier thread priority setting (#3522)
The HAL Notifier thread is started when the first Notifier is created
and stopped when the last Notifier is destroyed. Currently,
HAL_SetNotifierThreadPriority() will cause a segfault if the Notifier thread
hasn't been started yet (that is, if no Notifier have been created yet).

This change makes HAL_SetNotifierThreadPriority() store the RT and
priority setting. If the thread has already been started, it will set
the priority immediately. If it hasn't, HAL_InitializeNotifier() will
set the priority when it starts the thread.
2021-08-20 23:19:25 -07:00
PJ Reiniger
ab4cb59326 [gitignore] Update gitignore to ignore bazel / clion files (#3524) 2021-08-20 23:18:37 -07:00
PJ Reiniger
57c8615af3 [build] Generate spotless patch on failure (#3523) 2021-08-20 23:18:10 -07:00
Tyler Veness
b903173211 Replace std::cout and std::cerr with fmt::print() (#3519) 2021-08-19 20:31:14 -07:00
Thad House
10cc8b89c4 [hal] [wpilib] Add initial support for the REV PDH (#3503) 2021-08-14 11:44:56 -07:00
Tyler Veness
5d9ae3cdb4 [hal] Set HAL Notifier thread as RT by default (#3482)
This PR gives the Notifier HAL thread RT priority 40 in RobotBase after
HAL initialization and before the user code is run. This drastically
improves scheduling jitter for TimedRobot's AddPeriodic() functions (in
3512's experience).

It's too risky to set user code as RT because badly behaved code
will lock up the Rio (potentially requiring safe mode to recover).

This needs the user program to be setuid admin to succeed.
2021-08-14 11:42:35 -07:00
Tyler Veness
192d251ee8 [wpilibcIntegrationTests] Properly disable DMA integration tests (#3514)
"DISABLED_" must be a prefix, not a suffix.
2021-08-14 10:01:12 -07:00
Starlight220
031962608b [wpilib] Add PS4Controller, remove Hand from GenericHID/XboxController (#3345)
- GenericHID is now concrete, and has only getRawAxis/Button(int) functionality
- getXxx() has been moved into Joystick as that's the only place where it makes sense
- Hand (and therefore getXxx(Hand)) has been removed, replaced by specific getLeft/RightXxx() methods in XboxController and the new PS4Controller class
- C++ ::Button:: and ::Axis:: enums have been converted to identically-namespaced static constexpr ints
2021-08-14 10:00:46 -07:00
Tyler Veness
25f6f478a5 [wpilib] Rename DriverStation::IsOperatorControl() to IsTeleop() (#3505) 2021-08-11 23:04:43 -07:00
PJ Reiniger
e80f09f849 [wpilibj] Add unit tests (#3501) 2021-08-11 23:04:14 -07:00
Tyler Veness
c159f91f06 [wpilib] Only read DS control word once in IterativeRobotBase (#3504) 2021-08-11 18:05:07 -07:00
Thad House
eb790a74d2 Add rio development docs documenting myRobot deploy tasks (#3508)
Co-authored-by: sciencewhiz <sciencewhiz@users.noreply.github.com>
2021-08-11 18:04:20 -07:00
Matteo Kimura
e47451f5a0 [wpimath] Replace auto with Eigen types (#3511)
This fixes a bug regarding temporary Eigen values caused by the usage of auto.
2021-08-11 06:58:19 -07:00
Tyler Veness
252b8c83bf Remove Java formatting from build task in CI (#3507)
This saves time in CI spent performing the same source-level checks in
every build job. Checkstyle, PMD, and Spotless are now run once in the
"Lint and Format" job.

The -PskipPMD flag was replaced with a -PskipJavaFormat flag that
disables Checkstyle, PMD, and Spotless.
2021-08-07 20:39:14 -07:00
Tyler Veness
09666ff294 Shorten Gazebo CI build (#3506)
Only build the Gazebo simulation projects instead of all of WPILib.
2021-08-07 20:37:57 -07:00
sciencewhiz
baf2e501dc Update myRobot to use 2021 java (#3509) 2021-08-07 20:36:11 -07:00
Tyler Veness
5ac60f0a20 [wpilib] Remove IterativeRobotBase mode init prints (#3500)
They don't provide much utility for the end user. A print at the call to
HAL_ObserveUserProgramStarting() was added in their place so it's still
clear when constructors have finished running.
2021-08-05 23:54:50 -07:00
Tyler Veness
fb2ee8ec34 [wpilib] Add TimedRobot functions for running code on mode exit (#3499)
Currently, we have functions like TeleopInit() for running code on mode
entry, but no such functions for running code on mode exit, and it's
cumbersome to add those in user code without making a custom robot
class. This PR adds exit functions to TimedRobot.

Some example use cases include DisabledExit() for operations when the
robot enables (whether that be into teleop, autonomous, or test) and
AutonomousExit() for disabling feedback controllers.
2021-08-05 19:08:29 -07:00
PJ Reiniger
94e0db7963 [wpilibc] Add more unit tests (#3494) 2021-08-05 19:04:51 -07:00
sciencewhiz
b253246959 [wpilibj] Add units to parameter names (NFC) (#3497) 2021-08-05 18:04:20 -07:00
Thad House
1ac73a247e [hal] Rename PowerDistributionPanel to PowerDistribution (#3466)
Makes HAL more generic for the PDP, to enable the Rev PDH in the future.
2021-08-04 20:31:17 -07:00
sciencewhiz
2014115bca [examples] frisbeebot: Fix typo and reflow comments (NFC) (#3498) 2021-08-01 07:17:51 -07:00
liorsagy
4a944dc397 [examples] Consistently use 0 for controller port (#3496) 2021-07-31 20:39:50 -07:00
Tyler Veness
3838cc4ec4 Use unicode characters in docs equations (#3487)
javac and javadoc needed the encoding set to UTF-8.
2021-07-29 22:42:43 -07:00
Aditya Tomar
85748f2e6f [examples] Add C++ TankDrive example (#3493)
This is a basic C++ example that demonstrates a simple differential drive implementation using “tank”-style controls through the DifferentialDrive class and an ordinary joystick.
2021-07-28 21:52:14 -07:00
Tyler Veness
d7b8aa56dc [wpilibj] Rename DriverStation In[Mode] functions to follow style guide (#3488) 2021-07-26 07:29:54 -07:00
Tyler Veness
16e096cf86 [build] Fix CMake Windows CI (#3490) 2021-07-26 07:28:52 -07:00
Tyler Veness
50af74c38f [wpimath] Clean up NumericalIntegration and add Discretization tests (#3489)
* Rename Butcher tableau sections in NumericalIntegration such that
  top-left is c, top-right is A, and bottom-right is b
* Move edu.wpi.first.math.Discretization to
  edu.wpi.first.math.system.Discretization
* Sort Java Discretization to match C++ function order
* Add tests for Java Discretization
  * Required adding Runge-Kutta time-varying impl to tests
* Move C++ Runge-Kutta time-varying impl to tests only
  * Users don't need it
2021-07-25 07:42:59 -07:00
Tyler Veness
bfc209b120 Automate fmt update (#3486)
Also refactored upstream_utils to make writing and maintaining new
upstream repo extractions easier.
2021-07-23 09:01:44 -07:00
Austin Shalit
e7f9331e4b [build] Update to Doxygen 1.9.1 (#3008) 2021-07-22 18:33:15 -07:00
Tyler Veness
ab8e8aa2a1 [wpimath] Update drake with upstream (#3484)
Our patches for the DARE and [[noreturn]] attributes were merged
upstream. We missed their monthly release window by a day, so we'll use
a commit hash for now.
2021-07-22 17:48:48 -07:00
Lucas
1ef826d1da [wpimath] Fix IOException path in WPIMath JNI (#3485)
The current 2021.3.1 release refers to `java/lang/IOException` which causes the following exception when using `toPathweaverJson` or `fromPathweaverJson`:

```
java.lang.NoClassDefFoundError: java/lang/IOException
    at edu.wpi.first.math.WPIMathJNI.fromPathweaverJson(Native Method)
    at edu.wpi.first.wpilibj.trajectory.TrajectoryUtil.fromPathweaverJson(TrajectoryUtil.java:79)
```
2021-07-22 17:48:33 -07:00
Tyler Veness
52bddaa97b [wpimath] Disable iostream support for units and enable fmtlib (#3481)
Supersedes #2497.
2021-07-13 13:41:07 -05:00
Tyler Veness
e4dc3908bb [wpiutil] Upgrade to fmtlib 8.0.1 (#3483) 2021-07-13 13:39:14 -05:00
Tyler Veness
1daadb812f [wpimath] Implement Dormand-Prince integration method (#3476)
Also refactored RKF45 implementation to match the new style, which is
easier to read.

The tests were switched from RKF45 to RKDP since it's more accurate.
2021-07-11 09:42:33 -05:00
Tyler Veness
9c2723391b [cscore] Add [[nodiscard]] to GrabFrame functions (#3479)
Closes #3086.
2021-07-11 09:41:12 -05:00
Tyler Veness
7a8796414c [wpilib] Add Notifier integration tests (#3480)
Closes #2610.
2021-07-11 09:39:42 -05:00
Tyler Veness
f8f13c536f [wpilibcExamples] Prefix decimal numbers with 0 (#3478) 2021-07-11 09:38:13 -05:00
Tyler Veness
1adb69c0fd [ntcore] Use "NetworkTables" instead of "Network Tables" in NT specs (#3477)
Closes #3280.
2021-07-11 09:37:27 -05:00
Tyler Veness
5f5830b960 Upload wpiformat diff if one exists (#3474)
This means users will be able to apply it locally with "git apply".
2021-07-09 21:42:20 -05:00
Tyler Veness
9fb4f35bb6 [wpimath] Add tests for DARE overload with Q, R, and N matrices (#3472)
The autodiff headers weren't used by the tests, so they were removed.
2021-07-09 21:41:33 -05:00
Tyler Veness
c002e6f926 Run wpiformat (#3473)
A recent PR had an earlier version of wpiformat ran on it with more
lenient rules.
2021-07-09 20:49:13 -05:00
Thad House
c154e5262e [wpilib] Make solenoids exclusive use, PCM act like old sendable compressor (#3464) 2021-07-09 15:11:12 -07:00
Thad House
6ddef1cca6 [hal] JNI setDIO: use a boolean and not a short (#3469) 2021-07-08 23:42:31 -05:00
Tyler Veness
9d68d95825 Remove extra newlines after open curly braces (NFC) (#3471) 2021-07-08 23:41:30 -05:00
Tyler Veness
a4233e1a16 [wpimath] Add script for updating Drake (#3470)
Common functionality between the Drake and Eigen update scripts was
refactored into a library.
2021-07-08 22:36:01 -05:00
Prateek Machiraju
39373c6d2d Update README.md for new GCC version requirement (#3467) 2021-07-02 19:06:30 -07:00
Prateek Machiraju
d29acc90a2 [wpigui] Add option to reset UI on exit (#3463)
Also add wpiutil as a dependency for wpigui.
2021-06-26 22:48:54 -07:00
Peter Johnson
a371235b0d [ntcore] Fix dangling pointer in logger (#3465)
This is a breaking change (it changes LogMessage::filename from const
char* to std::string) but there should be few users of it.
2021-06-26 22:47:52 -07:00
Tyler Veness
53b4891a5e [wpilibcintegrationtests] Fix deprecated Preferences usage (#3461) 2021-06-23 21:58:27 -07:00
Prateek Machiraju
646ded9123 [wpimath] Remove incorrect discretization in pose estimators (#3460) 2021-06-23 21:57:52 -07:00
Peter Johnson
ea0b8f48e6 Fix some deprecation warnings due to fmtlib upgrade (#3459) 2021-06-23 21:57:32 -07:00
Prateek Machiraju
2067d7e300 [wpilibjexamples] Add wpimathjni, wpiutiljni to library path (#3455) 2021-06-22 06:33:24 -07:00
Tyler Veness
866571ab41 [wpiutil] Upgrade to fmtlib 8.0.0 (#3457) 2021-06-21 20:57:42 -07:00
Thad House
4e1fa03087 [build] Skip PDB copy on windows build servers (#3458) 2021-06-21 20:56:42 -07:00
Peter Johnson
b45572167d [build] Change CI back to 18.04 docker images (#3456)
This reverts commit d068fb321f (#3420).

The 18.04 docker images now use GCC 8, which was the original reason for
updating.  20.04 uses a much more recent libc, so staying with 18.04
enables more Linux platforms to use the binaries.
2021-06-20 23:03:29 -07:00
Tyler Veness
57a160f1b3 [wpilibc] Fix LiveWindow deprecation warning in RobotBase skeleton template (#3454) 2021-06-19 20:45:56 -07:00
Thad House
29ae8640d9 [HLT] Implement duty cycle cross connect tests (#3453) 2021-06-19 20:11:52 -07:00
Thad House
ee6377e54b [HLT] Add relay and analog cross connects (#3452) 2021-06-19 13:03:58 -07:00
Peter Johnson
b0f1ae7ea3 [build] CMake: Build the HAL even if WITH_CSCORE=OFF (#3449)
Also handle the case of WITH_WPILIB=OFF WITH_SIMULATION_MODULES=ON.
2021-06-19 09:30:49 -07:00
Tyler Veness
7aae2b72dc Replace std::to_string() with fmt::format() (#3451) 2021-06-19 09:30:01 -07:00
Thad House
73fcbbd748 [HLT] Add relay digital cross connect tests (#3450) 2021-06-19 01:21:56 -07:00
Thad House
e7bedde835 [HLT] Add PWM tests that use DMA as the back end (#3447)
Both a decent DMA test, and slightly more reliable PWM test.
2021-06-19 01:21:07 -07:00
Peter Johnson
7253edb1e1 [wpilibc] Timer: Fix deprecated warning (#3446) 2021-06-18 21:00:26 -07:00
Tyler Veness
efa28125c6 [wpilibc] Add message to RobotBase on how to read stacktrace (#3444)
Also make stacktrace info an error instead of a warning in both C++ and Java.
2021-06-17 23:52:48 -07:00
Thad House
9832fcfe14 [hal] Fix DIO direction getter (#3445)
Unset means input, where the code was assuming set means input.
2021-06-17 23:03:00 -07:00
Ryan Hirasaki
49c71f9f2d [wpilibj] Clarify robot quit message (#3364)
Co-authored-by: David Vo <auscompgeek@users.noreply.github.com>
2021-06-16 13:24:06 -07:00
Noam Zaks
791770cf6e [wpimath] Move controller from wpilibj to wpimath (#3439) 2021-06-16 07:45:51 -07:00
Noam Zaks
9ce9188ff6 [wpimath] Add ReportWarning to MathShared (#3441) 2021-06-16 00:52:24 -07:00
Peter Johnson
362066a9b7 [wpilib] Deprecate getInstance() in favor of static functions (#3440)
Co-authored-by: Noam Zaks <imnoamzaks@gmail.com>
2021-06-15 23:06:03 -07:00
Thad House
26ff9371d9 Initial commit of cross connect integration test project (#3434)
Adding as a separate project so current integration tests stay working.
2021-06-14 20:08:11 -07:00
Thad House
4a36f86c81 [hal] Add support for DMA to Java (#3158) 2021-06-14 19:56:42 -07:00
Peter Johnson
85144e47ff [commands] Unbreak build (#3438) 2021-06-14 07:35:21 -07:00
Peter Johnson
b417d961ec Split Sendable into NT and non-NT portions (#3432)
The non-NT portion has been moved to wpiutil.
The NT portion has been moved to ntcore (as NTSendable).

SendableBuilder similarly split and moved.

SendableRegistry moved to wpiutil.

In C++, SendableHelper also moved to wpiutil.

This enables use of Sendable from wpimath and also enables
moving several classes from wpilib to wpimath.
2021-06-13 16:38:05 -07:00
Starlight220
ef4ea84cb5 [commands] Change grouping decorator impl to flatten nested group structures (#3335) 2021-06-13 16:05:14 -07:00
Prateek Machiraju
b422665a3c [examples] Invert right side of drive subsystems (#3437)
The right motors of a DifferentialDrive are no longer automatically
inverted (#3340) so it needs to be done explicitly.
2021-06-13 15:43:16 -07:00
Thad House
186dadf14d [hal] Error if attempting to set DIO output on an input port (#3436) 2021-06-13 15:00:43 -07:00
Tyler Veness
04e64db945 Remove redundant C++ lambda parentheses (NFC) (#3433) 2021-06-12 08:06:45 -07:00
Peter Johnson
f60994ad24 [wpiutil] Rename Java package to edu.wpi.first.util (#3431)
This is more consistent with wpimath being edu.wpi.first.math.
2021-06-12 01:17:09 -07:00
Peter Johnson
cfa1ca96f2 [wpilibc] Make ShuffleboardValue non-copyable (#3430)
This avoids the possibility of it being accidentally sliced by users.
2021-06-11 20:16:35 -07:00
Tyler Veness
4d9ff76433 Fix documentation warnings generated by JavaDoc (NFC) (#3428)
Some C++ Doxygen comments were updated to reflect any wording changes.

See `rg "(@return|@param \w+) TODO" | less` for list of incomplete docs.
2021-06-10 20:46:47 -07:00
Peter Johnson
9e1b7e0464 [build] Fix clang-tidy and clang-format (#3429)
Use the official ubuntu packages on 20.04; don't use ubuntu-latest.
2021-06-10 20:46:21 -07:00
Tyler Veness
a77c6ff3a2 [build] Upgrade clang-format and clang-tidy (NFC) (#3422) 2021-06-10 11:13:09 -07:00
Tyler Veness
099fde97d5 [wpilib] Improve PDP comments (NFC) (#3427)
Also remove HAL doxygen comments from sources;
these functions already had more descriptive comments in their
corresponding headers.
2021-06-10 00:02:51 -07:00
Tyler Veness
f8fc2463ee [wpilibc, wpiutil] Clean up includes (NFC) (#3426) 2021-06-10 00:00:06 -07:00
Tyler Veness
e246b78846 [wpimath] Clean up member initialization in feedforward classes (#3425) 2021-06-09 23:59:31 -07:00
Tyler Veness
c1e128bd5a Disable frivolous PMD warnings and enable PMD in ntcore (#3419)
Some valid warnings like throwing NullPointerException or using a for
loop instead of System.arraycopy() were fixed.

Abstract classes marked with PMD.AbstractClassWithoutAbstractMethod were
made concrete because they already had protected constructors.

Fixes #1697.
2021-06-09 07:01:00 -07:00
Tyler Veness
8284075ee4 Run "Lint and Format" CI job on push as well as pull request (#3412)
This makes the formatter run when pushing to local forks before a pull
request is made.

This is not run on the main branch.
2021-06-08 23:22:40 -07:00
Tyler Veness
f7db09a128 [wpimath] Move C++ filters into filter folder to match Java (#3417) 2021-06-08 21:21:01 -07:00
Tyler Veness
f9c3d54bd1 [wpimath] Reset error covariance in pose estimator ResetPosition() (#3418)
This also fixes a member function name inconsistency between languages
and adds missing documentation to C++'s KalmanFilterLatencyCompensator.

Fixes #3229.
2021-06-08 21:20:43 -07:00
Tyler Veness
0773f4033e [hal] Ensure HAL status variables are initialized to zero (#3421)
HAL functions don't set the status variable on success, so it's possible
to use the status variable in an uninitialized state.
2021-06-08 21:18:59 -07:00
Peter Johnson
d068fb321f [build] Upgrade CI to use 20.04 docker images (#3420) 2021-06-08 12:27:22 -07:00
Peter Johnson
8d054c940c [wpiutil] Remove STLExtras.h
This is a very inefficient header, and it's good to remove to discourage
its use.  Only a handful of use cases remained, and of only array_lengthof.
2021-06-06 21:35:50 -07:00
Peter Johnson
80f1d79218 [wpiutil] Split function_ref to a separate header 2021-06-06 21:35:50 -07:00
Peter Johnson
64f5413253 Use wpi::span instead of wpi::ArrayRef across all libraries (#3414)
- Remove ArrayRef.h
- Add SpanExtras.h for a couple of convenience functions
2021-06-06 19:51:14 -07:00
Peter Johnson
2abbbd9e70 [build] clang-tidy: Remove bugprone-exception-escape (#3415)
This generates warnings for using fmt::print() in main(), which is a
case we're okay with.
2021-06-06 17:47:14 -07:00
Tyler Veness
a5c471af7e [wpimath] Add LQR template specialization for 2x2 system
A differential drive has this dimensionality (2 velocity states and 2
voltage inputs).
2021-06-06 16:45:12 -07:00
Tyler Veness
edd2f0232c [wpimath] Add DARE solver for Q, R, and N with LQR ctor overloads
This is useful for implementing implicit model following.
2021-06-06 16:45:12 -07:00
Peter Johnson
b2c3b2dd8e Use std::string_view and fmtlib across all libraries (#3402)
- Twine, StringRef, Format, and NativeFormatting have been removed
- Logging now uses fmtlib style formatting
- Nearly all uses of wpi::outs/errs have been replaced with fmt::print() or
std::puts()/std::fputs() (for unformatted strings).
- A wpi/fmt/raw_ostream.h header has been added to enable
fmt::print() with wpi::raw_ostream
2021-06-06 16:13:58 -07:00
Peter Johnson
4f1cecb8e7 [wpiutil] Remove Path.h (#3413)
This was missed in the std::filesystem change.
2021-06-06 15:50:28 -07:00
Prateek Machiraju
b336eac343 [build] Publish halsim_ws_core to Maven 2021-06-06 15:04:25 -07:00
Prateek Machiraju
2a09f6fa45 [build] Also build sim modules as static libraries
This allows sim modules to be statically linked into an executable to
create a "perfectly static" simulated desktop program. The entry point
was changed to be unique when building static libraries to avoid symbol
collisions.
2021-06-06 15:04:25 -07:00
Thad House
0e702eb799 [hal] Add a unified PCM object (#3331) 2021-06-05 22:36:39 -07:00
Tyler Veness
dea841103d [wpimath] Add fmtlib formatter overloads for Eigen::Matrix and units (#3409)
This allows using Eigen matrices or units natively with fmt::format() or
fmt::print().
2021-06-05 21:10:41 -07:00
Tyler Veness
82856cf816 [wpiutil] Improve wpi::circular_buffer iterators (#3410)
The implementation of wpi::circular_buffer has been effectively replaced
with a dynamically sized copy of wpi::static_circular_buffer with a
resize() member function.
2021-06-05 21:08:12 -07:00
Tyler Veness
8aecda03ed [wpilib] Fix a documentation typo (#3408)
"indicated" was misspelled.
2021-06-05 13:35:03 -07:00
Thad House
5c817082a0 [wpilib] Remove InterruptableSensorBase and replace with interrupt classes (#2410) 2021-06-05 11:25:21 -07:00
Tyler Veness
15c521a7fe [wpimath] Fix drivetrain system identification (#3406)
The units for angular Kv and Ka were inconsistent with the derivation. A
second factory function overload was added for angular units that uses a
trackwidth to convert to the other form.

Notice how section 15.2 of https://file.tavsys.net/control/controls-engineering-in-frc.pdf
defines the angular feedforward as u = Kv,angular v instead of u = Kv,angular + omega.
The units cancel for elements of A but not B, so just the B matrix was incorrect in our code.

This breaks existing C++ code since the units are part of the function
signature.
2021-06-05 11:22:05 -07:00
Thad House
989de4a1bf [build] Force all linker warnings to be fatal for rio builds (#3407)
This will make sure we catch any bugs for missing runtime dependencies before they become bigger problems.
2021-06-05 11:20:09 -07:00
Tyler Veness
d9eeb45b03 [wpilibc] Add units to Ultrasonic class API (#3403) 2021-06-01 21:54:56 -07:00
Peter Johnson
fe570e000c [wpiutil] Replace llvm filesystem with C++17 filesystem (#3401)
Use ghc::filesystem as fill on older GCC (e.g. RoboRIO).
This can be removed once all GCC platforms have upgraded to 8.1 or later.

File open functionality has been retained from LLVM but moved to "fs" namespace
and tweaked for improved consistency with std::filesystem (e.g. error_code is
passed by reference instead of returned).

Also update WPILibC's Filesystem functions to return std::string.
2021-06-01 21:50:35 -07:00
Tyler Veness
01dc0249de [wpimath] Move SlewRateLimiter from wpilib to wpimath (#3399)
Timer was replaced with wpi::Now() to avoid a dependency on other wpilib
classes.
2021-05-31 10:35:54 -07:00
Tyler Veness
93523d572e [wpilibc] Clean up integration tests (#3400)
The command and shuffleboard integration tests were removed because
their unit tests counterparts already provide adequate coverage. Java
already removed these.
2021-05-31 10:21:34 -07:00
Peter Johnson
4f7a4464df [wpiutil] Rewrite StringExtras for std::string_view (#3394)
Remove unused functions and add StringRef-like convenience functions.
Minimize header dependencies.
2021-05-28 23:42:58 -07:00
Tyler Veness
e09293a15e [wpilibc] Transition C++ classes to units::second_t (#3396)
A lot of these are breaking changes. frc::Timer was replaced with the
contents of frc2::Timer. The others were in-place argument changes or
removing deprecated non-unit overloads.
2021-05-28 22:06:59 -07:00
Prateek Machiraju
827b17a52b [build] Create run tasks for Glass and OutlineViewer (#3397) 2021-05-28 22:04:58 -07:00
Peter Johnson
a610379965 [wpiutil] Avoid MSVC warning on span include (#3393) 2021-05-26 23:14:04 -07:00
Peter Johnson
4e2c3051be [wpilibc] Use std::string_view instead of Twine (#3380)
Use fmtlib where needed for string formatting into std::string_view.
2021-05-26 17:44:18 -07:00
Peter Johnson
50915cb7ed [wpilibc] MotorSafety::GetDescription(): Return std::string (#3390)
This is only called in an error condition, so it's not necessary to over
optimize it.
2021-05-26 07:25:32 -07:00
Tyler Veness
f4e2d26d58 [wpilibc] Move NullDeleter from frc/Base.h to wpi/NullDeleter.h (#3387)
frc/Base.h was also deleted because it's now empty.
2021-05-26 07:24:53 -07:00
Peter Johnson
cb0051ae60 [wpilibc] SimDeviceSim: use fmtlib (#3389)
Also clean up several sim classes to use the channel constructor.
2021-05-26 07:23:13 -07:00
Tyler Veness
a238cec12b [wpiutil] Deprecate wpi::math constants in favor of wpi::numbers (#3383)
The constants were moved from std::math to std::numbers before
ratification in C++20.
2021-05-26 00:09:36 -07:00
Tyler Veness
393bf23c0c [ntcore, cscore, wpiutil] Standardize template impl files on .inc extension (NFC) (#3124) 2021-05-25 22:19:30 -07:00
Tyler Veness
e7d9ba135c [sim] Disable flaky web server integration tests (#3388)
The digital output test sometimes fails on Linux and the digital input
test sometimes fails on macOS.
2021-05-25 20:56:35 -07:00
Tyler Veness
0a0003c110 [wpilibjExamples] Fix name of Java swerve drive pose estimator example (#3382) 2021-05-25 20:55:24 -07:00
Tyler Veness
7e1b27554c [wpilibc] Use default copies and moves when possible (#3381)
The removal of ErrorBase allowed the defaults to be used in more places.
2021-05-25 20:54:39 -07:00
Tyler Veness
fb2a56e2d6 [wpilibc] Remove START_ROBOT_CLASS macro (#3384) 2021-05-25 20:53:26 -07:00
Tyler Veness
84218bfb45 [wpilibc] Remove frc namespace shim (#3385) 2021-05-25 20:52:50 -07:00
Tyler Veness
dd78243406 [wpilibc] Remove C++ compiler version static asserts (#3386)
frc/Base.h isn't the first header included basically anywhere, so the
compiler will fail on C++17 things before the asserts in this header are
processed.
2021-05-25 20:52:23 -07:00
Tyler Veness
484cf9c0e8 [wpimath] Suppress the -Wmaybe-uninitialized warning in Eigen (#3378)
GCC 11 emits a false positive when compiling Eigen and breaks the
build.

Fixes #3363.
2021-05-25 10:05:41 -07:00
Peter Johnson
a04d1b4f97 [wpilibc] DriverStation: Remove ReportError and ReportWarning
Change use cases to directly call FRC_ReportError.
2021-05-25 10:04:32 -07:00
Peter Johnson
831c10bdfc [wpilibc] Errors: Use fmtlib 2021-05-25 10:04:32 -07:00
Peter Johnson
87603e400d [wpiutil] Import fmtlib (#3375)
HEAD as of 5/23/2021 (dd8f38fcbbb6eedecd4d451b03ca7d817e8ae67d).
2021-05-24 23:59:35 -07:00
Peter Johnson
4426216725 [wpiutil] Add ArrayRef/std::span/wpi::span implicit conversions 2021-05-23 15:27:40 -07:00
Peter Johnson
bc15b953b4 [wpiutil] Add std::span implementation
Imported from https://github.com/tcbrindle/span with ifdef's removed
(as we require C++17).
2021-05-23 15:27:40 -07:00
Peter Johnson
6d20b12043 [wpiutil] StringRef, Twine, raw_ostream: Add std::string_view support (#3373) 2021-05-23 15:26:28 -07:00
Peter Johnson
2385c2a430 [wpilibc] Remove Utility.h (#3376)
Change last 2 uses of wpi_assert to throw error instead.
2021-05-23 15:25:08 -07:00
Tyler Veness
87384ea684 [wpilib] Fix PIDController continuous range error calculations (#3170)
The inputs should all be errors, so the range should be symmetric.

Fixes #3168.
Fixes #3304.
2021-05-21 23:52:30 -07:00
Tyler Veness
04dae799a2 [wpimath] Add SimpleMotorFeedforward::Calculate(velocity, nextVelocity) overload (#3183)
This is often more convenient than using the overload with velocity and
acceleration.

Fixes #3160.
2021-05-21 23:44:10 -07:00
Tyler Veness
0768c39036 [wpilib] DifferentialDrive: Remove right side inversion (#3340)
Also refactor drive inverse kinematics into separate functions.
This allows composing them with operations separate from the drive
class.
2021-05-21 22:34:16 -07:00
Tyler Veness
8dd8d4d2d4 [wpimath] Fix redundant nested math package introduced by #3316 (#3368) 2021-05-21 22:29:52 -07:00
Dalton Smith
49b06beedf [examples] Add Field2d to RamseteController example (#3371) 2021-05-21 22:28:29 -07:00
Tyler Veness
4c562a4457 [wpimath] Fix typo in comment of update_eigen.py (#3369)
NonMPL2.h clearly doesn't contain MPL2 code.
2021-05-21 21:39:33 -07:00
Tyler Veness
fdbbf11887 [wpimath] Add script for updating Eigen 2021-05-20 18:52:11 -07:00
Tyler Veness
f1e64b349a [wpimath] Move Eigen unsupported folder into eigeninclude
This fixes relative includes in development versions of Eigen.
2021-05-20 18:52:11 -07:00
Ryan Hirasaki
224f3a05cf [sim] Fix build error when building with GCC 11.1 (#3361) 2021-05-19 14:39:18 -07:00
Peter Johnson
ff56d6861d [wpilibj] Fix SpeedController deprecated warnings (#3360)
set() and other functions also need to be repeated on the MotorController
interface to avoid deprecation warnings from vscode.
2021-05-16 19:13:54 -07:00
sciencewhiz
1873fbefba [examples] Fix Swerve and Mecanum examples (#3359)
Fix encoder allocation and default command.
Fixes #3349
2021-05-15 21:39:00 -07:00
sciencewhiz
80b479e502 [examples] Fix SwerveBot example to use unique encoder ports (#3358)
Fixes #3089
2021-05-15 14:15:18 -07:00
PJ Reiniger
1f7c9adeeb [wpilibjExamples] Fix pose estimator examples (#3356) 2021-05-14 11:10:47 -07:00
Peter Johnson
9ebc3b058d [outlineviewer] Change default size to 600x400 (#3353) 2021-05-11 23:34:16 -07:00
Prateek Machiraju
e21b443a45 [build] Gradle: Make C++ examples runnable (#3348) 2021-05-11 19:54:53 -07:00
Peter Johnson
da590120c4 [wpilibj] Add MotorController.setVoltage default (#3347)
This avoids a vscode deprecation warning.
2021-05-11 19:53:55 -07:00
Peter Johnson
561d53885e [build] Update opencv to 4.5.2, imgui/implot to latest (#3344)
Also update native-utils to 2022.0.0 to start pulling 2022 artifacts.
2021-05-10 18:59:14 -07:00
Peter Johnson
44ad67ca8c [wpilibj] Preferences: Add missing Deprecated annotation (#3343) 2021-05-09 18:20:42 -07:00
Peter Johnson
3fe8fc75aa [wpilibc] Revert "Return reference from GetInstance" (#3342)
This reverts commit a79faace1b.

This change will be superseded in a non-breaking way by changing to static functions and deprecating GetInstance() entirely.
2021-05-09 18:16:07 -07:00
Peter Johnson
3cc2da3328 Merge branch '2022' 2021-05-09 14:15:40 -07:00
Tyler Veness
a3cd90dd71 [wpimath] Fix classpath used by generate_numbers.py (#3339) 2021-05-09 00:01:03 -07:00
Noam Zaks
d6cfdd3bae [wpilib] Preferences: Deprecate Put* in favor of Set* (#3337)
This naming is more consistent with other APIs.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-05-06 08:25:37 -07:00
Tyler Veness
ba08baabb9 [wpimath] Update Drake DARE solver to v0.29.0 (#3336)
This version incorporated the patch we were manually applying, so we're
synced back up with upstream now except for some minor #include changes
to reduce header bloat.
2021-05-05 09:16:55 -07:00
Tyler Veness
497b712f67 [wpilib] Make IterativeRobotBase::m_period private with getter 2021-05-04 13:41:36 -07:00
Tyler Veness
f00dfed7ac [wpilib] Remove IterativeRobot base class
TimedRobot supersedes it (see commit 81498e6 for reasoning).
2021-05-04 13:41:36 -07:00
Thad House
3c08461685 [hal] Use last error reporting instead of PARAMETER_OUT_OF_RANGE (#3328)
Makes the error messages much more specific to each error.
2021-05-01 13:22:08 -07:00
Tyler Veness
5ef2b4fdc0 [wpilibj] Fix @deprecated warning for SerialPort constructor (#3329)
The javadoc @deprecated tag didn't have corresponding @Deprecated
attribute.
2021-05-01 13:20:53 -07:00
Thad House
23d2326d1d [hal] Report previous allocation location for indexed resource duplicates (#3322) 2021-05-01 10:28:30 -07:00
Thad House
e338f9f190 [build] Fix wpilibc runCpp task (#3327) 2021-05-01 10:26:33 -07:00
Noam Zaks
c8ff626fe2 [wpimath] Move Java classes to edu.wpi.first.math (#3316) 2021-05-01 08:53:30 -07:00
Noam Zaks
4e424d51f4 [wpilibj] DifferentialDrivetrainSim: Rename constants to match the style guide (#3312) 2021-05-01 07:09:23 -07:00
Thad House
6b50323b07 [cscore] Use Lock2DSize if possible for Windows USB cameras (#3326)
Can remove a memory copy in many cases. This also fixes a bug where any mjpeg cameras on windows wouldn't work if the fast path was taken.
2021-05-01 07:07:37 -07:00
Tyler Veness
65c148536d [wpilibc] Fix "control reaches end of non-void function" warning (#3324) 2021-05-01 07:05:21 -07:00
Peter Johnson
f99f62bee4 [wpiutil] uv Handle: Use malloc/free instead of new/delete (#3325)
This avoids asan warnings for deleting a different pointer type.
2021-05-01 07:04:14 -07:00
Tyler Veness
365f5449ca [wpimath] Fix MecanumDriveKinematics (#3266) 2021-04-30 15:50:16 -07:00
Starlight220
ff52f207cc [glass, wpilib] Rewrite Mechanism2d (#3281)
Substantially improves Mechanism2d by moving it to NetworkTables and adding
a robot API to create the mechanism elements, instead of requiring a JSON file.

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
2021-04-30 13:43:59 -07:00
Tyler Veness
ee0eed143a [wpimath] Add DCMotor factory function for Romi motors (#3319) 2021-04-29 09:59:35 -07:00
Thad House
5127380727 [hal] Add HAL_GetLastError to enable better error messages from HAL calls (#3320)
This uses thread local storage so a full error string can be provided, not just an error code.
2021-04-29 09:56:54 -07:00
Noam Zaks
ced654880c [glass, outlineviewer] Update Mac icons to macOS 11 style (#3313) 2021-04-25 17:30:45 -07:00
Peter Johnson
936d3b9f83 [templates] Add Java template for educational robot (#3309)
Educational robot is a very minimal template designed for educational use
(rather than competition).
2021-04-24 20:22:39 -07:00
Jeff Hutchison
6e31230adc [examples] Fix odometry update in SwerveControllerCommand example (#3310)
The Drive Subsystem was supplying an incorrectly constructed
Rotation2d to the odometry update method. Rotation2d constructor
was being called with heading in degrees, not radians as required.
2021-04-24 20:07:04 -07:00
Peter Johnson
05ebe93180 Merge branch 'main' into 2022 2021-04-19 18:45:31 -07:00
Prateek Machiraju
aaf24e2552 [wpilib] Fix initial heading behavior in HolonomicDriveController (#3290) 2021-04-18 21:00:11 -07:00
Peter Johnson
8d961dfd25 [wpilibc] Remove ErrorBase (#3306)
Replace with new exception-based error reporting, consistent with Java.
This also builds stacktraces into the reporting/exceptions.
2021-04-18 20:35:29 -07:00
Peter Johnson
659b37ef9d [wpiutil] StackTrace: Include offset on Linux (#3305) 2021-04-18 20:34:39 -07:00
Peter Johnson
0abf6c9045 [wpilib] Move motor controllers to motorcontrol package (#3302)
Also deprecate SpeedController in favor of motorcontrol.MotorController and
SpeedControllerGroup in favor of motorcontrol.MotorControllerGroup.

The MotorController interface is derived from the SpeedController interface
so that code such as SpeedController x = new VictorSP(1) continues to
compile (just with a warning).

SpeedControllerGroup and MotorControllerGroup are independent classes;
both implement the MotorController interface.
2021-04-17 11:27:16 -07:00
Tyler Veness
4630191fa4 [wpiutil] circular_buffer: Use value initialization instead of passing zero (#3303)
This enables use of types that have a no-args constructor rather than one that takes an explicit zero value.
For numeric types, value initialization will result in a zero value, so this is not a functional change.
2021-04-15 11:50:07 -07:00
Peter Johnson
b7b178f49c [wpilib] Remove Potentiometer interface 2021-04-13 22:40:55 -07:00
Peter Johnson
687066af3d [wpilib] Remove GyroBase 2021-04-13 22:40:55 -07:00
Peter Johnson
6b168ab0c8 [wpilib] Remove PIDController, PIDOutput, PIDSource
Move them to the old commands vendordep so that PIDCommand and PIDSubsystem
continue to work.

This also removes Filter and LinearDigitalFilter.
2021-04-13 22:40:55 -07:00
Tyler Veness
948625de9d [wpimath] Document conversion from filter cutoff frequency to time constant (#3299) 2021-04-12 11:12:52 -07:00
Modelmat
3848eb8b16 [wpilibc] Fix flywhel -> flywheel typo in FlywheelSim (#3298) 2021-04-12 11:12:04 -07:00
Peter Johnson
3abe0b9d49 [cscore] Move java package to edu.wpi.first.cscore (#3294)
This is more consistent with the other Java packages, and also is more
correct, as we own the first.wpi.edu domain but not the full wpi.edu domain.
2021-04-10 11:42:41 -07:00
Peter Johnson
d7fabe81fe [wpilib] Remove RobotDrive (#3295)
This has been deprecated for several years, and its functionality has been
completely superseded by other drive classes (DifferentialDrive et al).
2021-04-10 10:28:32 -07:00
Peter Johnson
1dc81669c2 [wpilib] Remove GearTooth (#3293)
This sensor has had zero usage for many years and was last in the KOP
over a decade ago.  There are much better rotation sensors available,
and it's no longer worth maintaining this class.
2021-04-10 10:28:05 -07:00
Peter Johnson
01d0e12603 [wpilib] Revert move of RomiGyro into main wpilibc/j (#3296)
This reverts commit 69e8d0b65d (#3143).

We haven't released a version with this yet, and plan to make a vendor
library instead.
2021-04-10 10:27:44 -07:00
Peter Johnson
397e569aaf [ntcore] Remove "using wpi" from nt namespace
This removes the nt::ArrayRef, nt::StringRef, and nt::Twine aliases.
2021-04-08 22:35:28 -07:00
Peter Johnson
79267f9e60 [ntcore] Remove NetworkTable -> nt::NetworkTable shim 2021-04-08 22:35:28 -07:00
Peter Johnson
48ebe5736a [ntcore] Remove deprecated Java interfaces and classes 2021-04-08 22:35:28 -07:00
Peter Johnson
c2064c78b2 [ntcore] Remove deprecated ITable interfaces 2021-04-08 22:35:28 -07:00
Peter Johnson
36608a283b [ntcore] Remove deprecated C++ APIs 2021-04-08 22:35:28 -07:00
Starlight220
a1c87e1e15 [glass] LogView: Add "copy to clipboard" button (#3274) 2021-04-06 13:19:49 -07:00
Prateek Machiraju
fa7240a501 [wpimath] Fix typo in quintic spline basis matrix 2021-04-03 16:03:38 -07:00
Prateek Machiraju
ffb4d38e24 [wpimath] Add derivation for spline basis matrices 2021-04-03 16:03:38 -07:00
Starlight220
f57c188f2e [wpilib] Add AnalogEncoder(int) ctor (#3273) 2021-04-02 08:26:41 -07:00
Prateek Machiraju
8471c4fb26 [wpilib] FieldObject2d: Add setTrajectory() method (#3277) 2021-04-01 22:08:07 -07:00
Peter Johnson
c97acd18e7 [glass] Field2d enhancements (#3234)
- Add raw support for pose lists > 255/3 in length
- Improve drag selection, especially with closely overlapping objects
- Drag selection of corner also highlights center of object with smaller circle
- Multiple styles (box, line, closed line, track)
- Configurable line and arrow settings (color, weight)
- Add tooltip for object name, index, x, y, rotation
- Context menu for pose edit/add/remove
- View/edit in feet or inches as well as meters
- Configurable object selectability

Implementation: use vector of Pose2d internally, use units
2021-03-27 13:34:44 -07:00
Prateek Machiraju
ffb590bfcc [wpilib] Fix Compressor sendable properties (#3269) 2021-03-26 21:20:54 -07:00
Peter Johnson
6137f98eb5 [hal] Rename SimValueCallback2 to SimValueCallback (#3212) 2021-03-21 23:22:04 -07:00
Peter Johnson
a6f6539691 [hal] Move registerSimPeriodic functions to HAL package (#3211)
This enables the static lists to be private.
2021-03-21 23:21:47 -07:00
Peter Johnson
10c038d9bf [glass] Plot: Fix window creation after removal (#3264)
Previously the following sequence was broken:
- Add two plot windows (creates Plot<0> and Plot<1>)
- Delete Plot<0>
- Try to create a plot window

This failed because it would try to create Plot<1>, which already existed.
It was necessary to also destroy Plot<1> before another plot could be added.

This change fixes this case by trying all 0-N cases.
2021-03-21 18:06:18 -07:00
Peter Johnson
2d2eaa3eff [wpigui] Ensure window will be initially visible (#3256)
Only set the initial window position if the window X/Y postion is within one
of the connected monitor work areas.
2021-03-21 12:39:33 -07:00
Prateek Machiraju
4d28b1f0cd [wpimath] Use JNI for trajectory serialization (#3257) 2021-03-21 12:38:23 -07:00
Peter Johnson
3de800a607 [wpimath] TrajectoryUtil.h: Comment formatting (NFC) (#3262) 2021-03-21 11:40:15 -07:00
Peter Johnson
eff5923778 [glass] Plot: Don't overwrite series ID (#3260) 2021-03-21 11:14:25 -07:00
Peter Johnson
a79faace1b [wpilibc] Return reference from GetInstance (#3247)
Improves consistency across all classes.

Affects Preferences, LiveWindow, and CameraServer.

Old commands Scheduler::GetInstance() was not updated as this is already
deprecated.
2021-03-21 11:13:49 -07:00
Peter Johnson
9550777b9d [wpilib] PWMSpeedController: Use PWM by composition (#3248)
This cleans up the user experience by removing lower-level functions from the
interface.

Also remove MotorSafety from "raw" PWM.
2021-03-21 11:12:49 -07:00
Peter Johnson
c8521a3c33 [glass] Plot: Set reasonable default window size (#3261) 2021-03-21 10:50:41 -07:00
Peter Johnson
d71eb2cf39 [glass] Plot: Show full source name as tooltip and in popup (#3255) 2021-03-20 20:59:31 -07:00
Peter Johnson
160fb740f4 [hal] Use std::lround() instead of adding 0.5 and truncating (#3012) 2021-03-19 14:24:46 -07:00
Peter Johnson
48e9f39513 [wpilibj] Remove wpilibj package CameraServer (#3213) 2021-03-19 13:51:53 -07:00
Peter Johnson
8afa596fdf [wpilib] Remove deprecated Sendable functions and SendableBase (#3210) 2021-03-19 13:41:11 -07:00
Prateek Machiraju
d3e45c297c [wpimath] Make C++ geometry classes immutable (#3249) 2021-03-19 13:38:54 -07:00
Peter Johnson
2c98939c18 [glass] StringChooser: Don't call SameLine() at end 2021-03-19 13:15:26 -07:00
Peter Johnson
a18a7409fb [glass] NTStringChooser: Clear value of deleted entries 2021-03-19 13:15:26 -07:00
Peter Johnson
2f19cf4524 [glass] NetworkTablesHelper: listen to delete events 2021-03-19 13:15:26 -07:00
Peter Johnson
da96707dca Merge branch 'main' into 2022 2021-03-19 09:22:02 -07:00
Peter Johnson
c3a8bdc240 [build] Fix clang-tidy action (#3246)
Manually install python3.8, as actions/setup-python now needs Ubuntu 20.04.
2021-03-19 08:59:14 -07:00
Peter Johnson
21624ef273 Add ImGui OutlineViewer (#3220) 2021-03-16 22:05:41 -07:00
Peter Johnson
1032c9b917 [wpiutil] Unbreak wpi::Format on Windows (#3242)
This function relies on the behavior of snprintf returning an error value
when the buffer is too small.  By default, _snprintf_s aborts on Windows
instead of returning an error value.

This caused Glass to fail when trying to print a large NT value to a string.
2021-03-16 22:04:55 -07:00
Peter Johnson
2e07902d76 [glass] NTField2D: Fix name lookup (#3233)
This was causing incorrect detection of duplicate names.
2021-03-12 16:54:26 -08:00
Peter Johnson
6e23e1840a [wpilibc] Remove WPILib.h (#3235)
It's been deprecated for several years, is often broken as it's not tested
frequently, and dramatically increases compile times.
2021-03-12 15:58:47 -08:00
Prateek Machiraju
3e22e45066 [wpilib] Make KoP drivetrain simulation weight 60 lbs (#3228) 2021-03-07 22:54:40 -08:00
Peter Johnson
79d1bd6c8f [glass] NetworkTablesSetting: Allow disable of server option (#3227) 2021-03-07 21:24:59 -08:00
Prateek Machiraju
fe341a16f5 [examples] Use more logical elevator setpoints in GearsBot (#3198) 2021-03-07 16:00:00 -08:00
Peter Johnson
62abf46b3f [glass] NetworkTablesSettings: Don't block GUI (#3226)
On some systems, StopClient et al can take a long time to execute.
Instead run these on a separate thread to avoid blocking the GUI.

Also add option to get IP from DS (default on).
2021-03-07 15:40:05 -08:00
Peter Johnson
a95a5e0d9b [glass] Move NetworkTablesSettings to libglassnt (#3224) 2021-03-06 22:19:00 -08:00
Prateek Machiraju
d6f6ceaba5 [build] Run Spotless formatter (NFC) (#3221)
The original PR (#2934) was created before we moved to Spotless so the
formatting check was never run.
2021-03-04 08:24:05 -08:00
Blake Bourque
0922f8af59 [commands] CommandScheduler.requiring(): Note return can be null (NFC) (#2934) 2021-03-03 23:56:57 -08:00
Prateek Machiraju
6812302ff9 [examples] Make DriveDistanceOffboard example work in sim (#3199)
Adds some basic functionality to the ExampleMotorController so that
controller inputs show up in LiveWindow widgets in simulation.
2021-03-03 23:38:13 -08:00
Prateek Machiraju
f3f86b8e78 [wpimath] Add pose estimator overload for vision + std dev measurement (#3200) 2021-03-03 23:37:18 -08:00
Matt Soucy
1a2680b9e5 [wpilibj] Change CommandBase.withName() to return CommandBase (#3209)
Doing this retains the Sendable portion of the type.
2021-03-03 23:35:37 -08:00
Starlight220
435bbb6a8c [command] RamseteCommand: Output 0 if interrupted (#3216) 2021-02-28 22:06:34 -08:00
Tyler Veness
3cf44e0a53 [hal] Add function for changing HAL Notifier thread priority (#3218) 2021-02-28 22:05:26 -08:00
Prateek Machiraju
40b367513f [wpimath] Units.java: Add kg-lb conversions (#3203) 2021-02-27 10:12:41 -08:00
Prateek Machiraju
9f563d584a [glass] NT: Fix return value in StringToDoubleArray (#3208) 2021-02-26 08:43:12 -08:00
Peter Johnson
af4adf5379 [glass] Auto-size plots to fit window (#3193)
Plots can still be set to have a fixed height, in which case the remaining
space is distributed amongst the auto-sized plots.
2021-02-21 16:38:06 -08:00
Peter Johnson
2560146da3 [sim] GUI: Add option to show prefix in Other Devices (#3186)
Also disable rename popup for this window.
2021-02-21 16:35:49 -08:00
Peter Johnson
eae3a6397a gitignore: Ignore .cache directory (#3196)
This is used by newer clangd versions.
2021-02-21 16:35:01 -08:00
Starlight220
959611420b [wpilib] Require non-zero positive value for PIDController.period (#3175) 2021-02-16 18:07:29 -08:00
Prateek Machiraju
9522f2e8c7 [wpimath] Add methods to concatenate trajectories (#3139)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-02-16 18:06:36 -08:00
Zachary Orr
e42a0b6cf0 [wpimath] Rotation2d comment formatting (NFC) (#3162) 2021-02-16 18:06:01 -08:00
Claudius Tewari
d1c7032dec [wpimath] Fix order of setting gyro offset in pose estimators (#3176)
The gyro offset should be determined from the desired initial pose, not the current pose. This fix reflects the behavior of the odometry classes and the C++ holonomic pose estimators.
2021-02-16 18:04:38 -08:00
Starlight220
d241bc81ae [sim] Add DoubleSolenoidSim and SolenoidSim classes (#3177) 2021-02-16 18:03:57 -08:00
Tyler Veness
cb7f39afa1 [wpilibc] Add RobotController::GetBatteryVoltage() to C++ (#3179)
This function already exists in Java.
2021-02-16 18:03:25 -08:00
Thad House
99b5ad9ebb [wpilibj] Fix warnings that are not unused variables or deprecation (#3161)
Fix all warnings given by intellisense that are not unused variables or deprecation.
2021-02-12 22:22:11 -08:00
Thad House
c14b237757 [build] Fixup doxygen generated include dirs to match what users would need (#3154) 2021-02-12 22:17:39 -08:00
Starlight220
d447c7dc32 [sim] Add SimDeviceSim ctor overloads (#3134)
Better parallelism with SimDevice.create(), so teams don't have to mess with concatenating the index/channel themselves.
2021-02-12 22:17:13 -08:00
Austin Shalit
247420c9c1 [build] Remove jcenter repo (#3157) 2021-02-12 22:15:52 -08:00
Peter Johnson
04b112e004 [build] Include debug info in plugin published artifacts (#3149) 2021-02-12 22:15:16 -08:00
Prateek Machiraju
be0ce99007 [examples] Use PWMSparkMax instead of PWMVictorSPX (#3156)
This accurately reflects the motor controllers that are distributed in
the Kit of Parts.
2021-02-12 22:14:56 -08:00
Zhiquan Yeo
69e8d0b65d [wpilib] Move RomiGyro into main wpilibc/j (#3143) 2021-02-12 22:14:29 -08:00
Tyler Veness
94e685e1bd [wpimath] Add custom residual support to EKF (#3148)
Fixes #3145.

Co-authored-by: Declan Freeman-Gleason <declanfreemangleason@gmail.com>
2021-02-12 22:13:36 -08:00
Peter Johnson
5899f3dd28 [sim] GUI: Make keyboard settings loading more robust (#3167)
Check values during load and operation to avoid potential crashes due to
ini file errors or corruption.
2021-02-12 22:12:20 -08:00
Prateek Machiraju
f82aa1d564 [wpilib] Fix HolonomicDriveController atReference() behavior (#3163)
The atReference() method previously used the rotation error between the
desired trajectory state and the current pose. This was a bug because we
allow teams to use custom rotation setpoints and that wasn't being taken
into account.
2021-02-12 22:11:57 -08:00
Tyler Veness
fe5c2cf4b7 [wpimath] Remove ControllerUtil.java (#3169)
This was already removed from C++ in the offseason and replaced with
MathUtil.inputModulus(). We just neglected to do that for Java; it was
never intended to see a season release. Its implementation is incorrect
compared to inputModulus() as well.

See https://github.com/wpilibsuite/allwpilib/issues/3168 for discussion.
2021-02-12 22:10:58 -08:00
Thad House
43d40c6e9e [wpiutil] Suppress unchecked cast in CombinedRuntimeLoader (#3155)
Because of Java's type system, it is actually literally impossible to check for this cast at runtime. So instead, the only option is to suppress it. Only suppressed for the specific function.
2021-02-07 08:20:33 -08:00
Tyler Veness
3d44d8f79c [wpimath] Fix argument order in UKF docs (NFC) (#3147) 2021-02-01 23:36:32 -08:00
Peter Johnson
ba6fe8ff2e [cscore] Add USB camera change event (#3123) 2021-01-31 18:52:48 -08:00
Peter Johnson
5337258888 [build] Tweak OpenCV cmake search paths to work better on Linux (#3144)
With this change, cmake finds OpenCV Java on Ubuntu with no additional search options.
2021-01-31 18:52:21 -08:00
Peter Johnson
29bf9d6ef1 [cscore] Add polled support to listener
Change Java VideoListener to use polling.
2021-01-31 17:06:37 -08:00
Peter Johnson
483beb6361 [ntcore] Move CallbackManager to wpiutil 2021-01-31 17:06:37 -08:00
Prateek Machiraju
fdaec77594 [examples] Instantiate m_ramseteController in example (#3142) 2021-01-31 17:04:16 -08:00
Peter Johnson
8494a5761b Rename default branch to main (#3140) 2021-01-30 13:46:56 -08:00
Prateek Machiraju
45590eea22 [wpigui] Hardcode window scale to 1 on macOS (#3135)
This fixes an issue with scaling on Retina displays where the frame
buffer size was double that of the window size, resulting in a content
scale factor of 2. This scale factor caused elements to appear too
large, even on the smallest zoom setting.

This change does not affect external monitors on macOS because the
reported content scale was 1 anyway.
2021-01-28 21:52:13 -08:00
Prateek Machiraju
834a64920b [build] Publish libglass and libglassnt to Maven (#3127) 2021-01-25 21:42:38 -08:00
Tyler Veness
2c2ccb3618 [wpimath] Fix Rotation2d equality operator (#3128) 2021-01-25 21:41:34 -08:00
Prateek Machiraju
fb5c8c39ae [wpigui] clang-tidy: readability-braces-around-statements 2021-01-25 09:25:39 -08:00
Prateek Machiraju
f7d39193a4 [wpigui] Fix copyright in pfd and wpigui_metal.mm 2021-01-25 09:25:39 -08:00
Tyler Veness
aec796b212 [ntcore] Fix conditional jump on uninitialized value (#3125)
`m_last_flush` should be initialized before it's used at
Dispatcher.cpp:243.
2021-01-25 08:15:08 -08:00
Peter Johnson
fb13bb2393 [sim] GUI: Add right click popup for keyboard joystick settings (#3119) 2021-01-23 09:10:58 -08:00
Prateek Machiraju
c517ec6779 [build] Update thirdparty-imgui to 1.79-2 (#3118) 2021-01-22 19:48:49 -08:00
David Vo
e8cbf2a717 [wpimath] Fix typo in SwerveDrivePoseEstimator doc (NFC) (#3112) 2021-01-21 09:31:37 -08:00
Prateek Machiraju
e9c86df468 [wpimath] Add tests for swerve module optimization (#3100) 2021-01-20 20:44:37 -08:00
Modelmat
6ba8c289c5 [examples] Remove negative of ArcadeDrive(fwd, ..) in the C++ Getting Started Example (#3102) 2021-01-20 20:43:34 -08:00
Peter Johnson
3f1672e89f [hal] Add SimDevice createInt() and createLong() (#3110) 2021-01-20 20:42:39 -08:00
Prateek Machiraju
15be5cbf1f [examples] Fix segfault in GearsBot C++ example (#3111)
This fixes a dangling this pointer in the DriveStraight and
SetDistanceToBox commands by directly capturing the
drivetrain pointer by value instead.
2021-01-20 20:38:45 -08:00
Evan Pratten
4cf0e5e6db Add quick links to API documentation in README (#3082) 2021-01-19 23:00:54 -08:00
Tyler Veness
6b1898f12e Fix RT priority docs (NFC) (#3098)
The ranges and which value was specified as highest were incorrect on
some of them. On Linux, the range is 1 to 99 with 99 being highest.

From `man 7 sched`:
```
Processes scheduled under one of the real-time policies (SCHED_FIFO,
SCHED_RR) have a sched_priority value in the range 1 (low) to 99 (high).
```

Also clean up the relevant javadoc and doxygen comments.
2021-01-19 22:59:18 -08:00
David Vo
b3426e9c0d [wpimath] Fix missing whitespace in pose estimator doc (#3097) 2021-01-19 22:58:08 -08:00
Modelmat
38c1a1f3e0 [examples] Fix feildRelative -> fieldRelative typo in XControllerCommand examples (#3104)
* MecanumControllerCommand
* SwerveControllerCommand
2021-01-19 22:57:41 -08:00
Peter Johnson
4488e25f16 [glass] Shorten SmartDashboard window names (#3096)
Instead of "/SmartDashboard/name" they now default to "name (SmartDashboard)".
This allows for smaller windows while preserving the name without requiring
user customization.
2021-01-17 20:33:42 -08:00
CoolSpy3
cfdb3058ee [wpilibj] Update SimDeviceSimTest (#3095) 2021-01-17 13:48:25 -08:00
Mark Vedder
64adff5fea [examples] Fix typo in ArcadeDrive constructor parameter name (#3092)
Removed extra 'p' in "Supplier" in the parameter name `zaxisRotateSuppplier` of the  ArcadeDrive constructor of the Romi Reference example.
2021-01-16 20:27:29 -08:00
Thad House
6efc58e3db [build] Fix issues with build on windows, deprecations, and native utils (#3090) 2021-01-16 20:26:52 -08:00
Tyler Veness
f393989a5b [wpimath, wpiutil] Add wpi::array for compile time size checking (#3087)
The wpimath APIs use std::array, which doesn't do size checking. Passing
an array with the wrong size can result in uninitialized elements
instead of a compilation error.

This is a breaking change but is worthwhile to avoid hard-to-debug errors.
2021-01-16 20:26:17 -08:00
Prateek Machiraju
d6ed20c1e4 [build] Set macOS deployment target to 10.14 (#3088) 2021-01-14 21:20:38 -08:00
Tyler Veness
7c524014c8 [hal] Add [[nodiscard]] to HAL_WaitForNotifierAlarm() (#3085)
As this is a C-compatible header, add a WPI_NODISCARD macro for
compiler-specific C-compatible nodiscard attributes.
2021-01-14 20:00:55 -08:00
Matt
406d055f07 [wpilib] Fixup wouldHitLowerLimit in elevator and arm simulation classes. (#3076)
Closes #3050.
2021-01-14 00:28:00 -08:00
sciencewhiz
04a90b5dd1 [examples] Don't continually set setpoint in PotentiometerPID Examples (#3084) 2021-01-13 20:09:08 -08:00
Prateek Machiraju
8c5bfa0132 [sim] GUI: Add max value setting for keyboard joysticks (#3083) 2021-01-12 19:57:04 -08:00
Peter Johnson
bc80c55353 [hal] Add SimValue reset() function (#3064)
This enables correct behavior for resetting incremental sensor values like
encoder counts or gyro accumulated angle with WebSockets.
2021-01-12 00:38:58 -08:00
Peter Johnson
9c3b51ca0f [wpilib] Document simulation APIs (#3079)
- Remove sim checkstyle suppression
- Add [[nodiscard]] to C++ register callback functions
- Add a couple of missing sim functions

Co-authored-by: Peter Johnson <johnson.peter@gmail.com>
Co-authored-by: Starlight220 <yotamshlomi@gmail.com>
2021-01-11 21:55:45 -08:00
Prateek Machiraju
26584ff145 [wpimath] Add model description to LinearSystemId Javadocs (#3080) 2021-01-11 20:08:55 -08:00
Prateek Machiraju
42c3d52863 [examples] Sync Java and C++ trajectories in sim example (#3081)
This also shifts the trajectory up and to the right so that the robot is
always visible in the Field GUI during traversal. Some drive constants
and trajectory constraints were also synced between the two languages.
2021-01-11 20:08:22 -08:00
Dustin Spicuzza
64e72f7103 [wpilibc] Add missing function RoboRioSim::ResetData (#3073) 2021-01-10 22:50:25 -08:00
Matt
e955037980 [wpimath] Add optimize() to SwerveModuleState (#3065)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-01-10 22:49:46 -08:00
Peter Johnson
fb99910c23 [hal] Add SimInt and SimLong wrappers for int/long SimValue (#3066) 2021-01-09 23:26:19 -08:00
CoolSpy3
e620bd4d3f [doc] Add machine-readable websocket specification (#3059)
Co-authored-by: Vasista Vovveti <vasistavovveti@gmail.com>
2021-01-09 23:24:57 -08:00
Peter Johnson
a44e761d9e [glass] Add support for plot Y axis labels 2021-01-08 11:37:35 -08:00
Peter Johnson
ea1974d576 [wpigui] Update imgui and implot to latest 2021-01-08 11:37:35 -08:00
Matt
85a0bd43c2 [wpimath] Add RKF45 integration (#3047)
This is more stable than Runge-Kutta for systems with large elements in their A or B matrices.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2021-01-06 21:40:25 -08:00
Prateek Machiraju
278e0f126e [glass] Use .controllable to set widgets' read-only state (#3035)
This modifies the mecanum drive, differential drive, speed controller,
and PID controller widgets to only be writeable when .controllable is
set to true.
2021-01-05 18:33:05 -08:00
Tyler Veness
d8652cfd4f [wpimath] Make Java DCMotor API consistent with C++ and fix motor calcs (#3046)
The stall torque, stall current, and free current are now multiplied by
the number of motors instead of just the stall torque. This produces the
same values for Kt and Kv regardless of the number of motors; the motor
resistance still affects the system response.

For an elevator model, the response should be the same as before since a
factor of "number of motors" shows up in the same place in the
acceleration calculation, but the current calculation will also be
correct now.
2021-01-05 18:28:57 -08:00
Peter Johnson
377b7065aa [build] Add toggleOffOn to Java spotless (#3053)
This allows custom formatting where desired (e.g. of table values).

Also upgrade spotless to 5.5.0.
2021-01-05 17:56:45 -08:00
Prateek Machiraju
1e9c79c587 [sim] Use plant output to retrieve simulated position (#3043)
Using the plant output means that measurement noise can be incorporated.
SingleJointedArmSim (in C++ and Java) and ElevatorSim (in C++) used the
state instead of the measurement.

Closes #3042
2021-01-05 17:55:44 -08:00
Peter Johnson
78147aa342 [sim] GUI: Fix Keyboard Joystick (#3052)
This was broken by #3010.

Also fix a few unknown key cases and a nullptr return that could cause a crash.
2021-01-05 17:55:11 -08:00
Peter Johnson
cd4a2265b9 [ntcore] Fix NetworkTableEntry::GetRaw() (#3051)
It was calling value->GetString() instead of GetRaw(), which would assert.
2021-01-04 22:07:50 -08:00
Austin Shalit
767ac1de10 [build] Use deploy key for doc publish (#3048)
This allows us to limit the scope of personal access tokens
2021-01-04 15:21:47 -08:00
Austin Shalit
d762215d13 [build] Add publish documentation script (#3040) 2021-01-04 13:59:19 -08:00
sciencewhiz
1fd09593cf [examples] Add missing TestInit method to GettingStarted Example (#3039) 2021-01-02 22:00:25 -08:00
Zhiquan Yeo
e45a0f6ce2 [examples] Add RomiGyro to the Romi Reference example (#3037) 2021-01-02 21:59:57 -08:00
sciencewhiz
94f8525721 Update imaging link and fix typo (#3038) 2021-01-02 19:57:39 -08:00
Zhiquan Yeo
d73cf64e54 [examples] Update RomiReference to match motor directions (#3036)
Flip the TeleopArcadeDrive axis directions so that positive
values for x-axis speed result in the Romi driving forward (in the
direction of the Raspberry Pi USB ports).
2021-01-02 17:21:07 -08:00
Peter Johnson
f945462bab Bump copyright year to 2021 (#3033) 2021-01-01 21:54:00 -08:00
Tyler Veness
b05946175b [wpimath] Catch Drake JNI exceptions and rethrow them (#3032)
This gives an informative error in Java instead of crashing the JVM.
2021-01-01 17:09:50 -08:00
Tyler Veness
62f0f8190d [wpimath] Deduplicate angle modulus functions (#2998)
frc::NormalizeAngle(), units::math::NormalizeAngle(), and
frc::GetModulusError() were replaced with frc::InputModulus() and
frc::AngleModulus().

They were placed in wpimath/src/main/native/include/frc/MathUtil.h for
C++ and wpimath/src/main/java/edu/wpi/first/wpiutil/math/MathUtil.java
for Java.
2021-01-01 16:22:00 -08:00
Prateek Machiraju
bf8c0da4be [glass] Add "About" popup with version number (#3031) 2021-01-01 15:59:00 -08:00
Prateek Machiraju
dfdd6b3891 [build] Increase Gradle heap size in Gazebo build (#3028)
Builds have been intermittently failing due to Gradle running out of memory.
2021-01-01 10:29:55 -08:00
Peter Johnson
f5e0fc3e9a Finish clang-tidy cleanups (#3003)
* Add .clang-tidy configuration.
* A separate .clang-tidy is used for hal includes to suppress modernize-use-using
  (as these are C headers).
* Add NOLINT where necessary for a clean run.
* Add clang-tidy job to lint-format workflow.  This workflow is now only run on PRs.
  To reduce runtime, clang-tidy is only run on files changed in the PR.

Two wpilibc changes; both are unlikely to break user code:
* BuiltInAccelerometer: Make SetRange() final
* Counter: Make SetMaxPeriod() final

After these cleanups, the only file that does not run cleanly is
cscore_raw_cv.h due to it not being standalone.
2021-01-01 10:27:49 -08:00
Peter Johnson
d741101fe3 [sim] Revert accidental commit of WSProvider_PDP.h (#3027) 2021-01-01 00:44:31 -08:00
Starlight220
e1620799c7 [examples] Add C++ RomiReference example (#2969)
Co-authored-by: Prateek Machiraju <prateek.machiraju@gmail.com>
Co-authored-by: sciencewhiz <sciencewhiz@users.noreply.github.com>
2020-12-31 20:37:20 -08:00
Prateek Machiraju
749c7adb13 [command] Fix use-after-free in CommandScheduler (#3024) 2020-12-31 20:35:17 -08:00
Peter Johnson
921a733911 [sim] Add WS providers for AddressableLED, PCM, and Solenoid (#3026)
Co-authored-by: PJ Reiniger <pj.reiniger@gmail.com>
2020-12-31 20:34:34 -08:00
Austin Shalit
26d0004fe1 [build] Split Actions into different yml files (#3025) 2020-12-31 20:33:39 -08:00
Austin Shalit
948af6d5b5 [wpilib] PWMSpeedController.get(): Apply Inversion (#3016)
This makes get() return the value actually sent to the motor.

This is a breaking change.
2020-12-31 14:35:10 -08:00
Peter Johnson
670a187a3c [wpilibc] SuppliedValueWidget.h: Forward declare ShuffleboardContainer (#3021)
This is needed to break the include loop between SuppliedValueWidget.h and ShuffleboardContainer.h.
2020-12-31 12:35:56 -08:00
Peter Johnson
be9f725023 [ntcore] NetworkTableValue: Use std::forward instead of std::move (#3022)
Because these are forwarding references, they could unexpectedly move a
passed lvalue.  Using std::forward() makes a copy if an lvalue is passed.
2020-12-31 12:35:02 -08:00
Peter Johnson
daf3f4cb1a [cscore] cscore_raw_cv.h: Fix error in PutFrame() (#3019) 2020-12-31 12:34:37 -08:00
Peter Johnson
5acda4cc71 [wpimath] ElevatorFeedforward.h: Add time.h include 2020-12-31 12:18:06 -08:00
Peter Johnson
8452af606b [wpimath] units/radiation.h: Add mass.h include 2020-12-31 12:18:06 -08:00
Peter Johnson
630d449520 [hal] ErrorsInternal.h: Add stdint.h include 2020-12-31 12:18:06 -08:00
Peter Johnson
7372cf7d99 [cscore] Windows NetworkUtil.cpp: Add missing include 2020-12-31 12:18:06 -08:00
Peter Johnson
b7e46c558f Include .h from .inc/.inl files (NFC) (#3017)
This helps both IDEs and linting tools.

Also add some missing braces.
2020-12-31 11:26:53 -08:00
jpokornyiii
bf8f8710ea [examples] Update Romi template and example (#2996)
Updated the RomiReference example to have autonomous example.
Updated RomiReference and both Romi templates to use Encoder.getDistance().
Removed motor inversion.
2020-12-30 22:45:04 -08:00
Austin Shalit
6ffe5b775d [glass] Ensure NetworkTableTree parent context menu has an id (#3015) 2020-12-30 22:43:35 -08:00
Austin Shalit
be0805b85b [build] Update to WPILibVersioningPlugin 4.1.0 (#3014) 2020-12-30 22:40:38 -08:00
Austin Shalit
65b2359b27 [build] Add spotless for other files (#3007)
Adds spotless formatting for Gradle, xml, md, and gitignore files.

yml linting is not performed as it requires a dependency on npm.
2020-12-30 16:17:20 -08:00
Prateek Machiraju
8651aa73e8 [examples] Enable NT Flush in Field2d examples (#3013) 2020-12-30 16:12:15 -08:00
Austin Shalit
78b542737a [build] Add Gazebo build to Actions CI (#3004) 2020-12-30 11:38:49 -08:00
Peter Johnson
fccf86532f [sim] DriverStationGui: Fix two bugs (#3010)
- Slicing of GlfwKeyboardJoystick
- Potential null pointer deref
2020-12-30 11:37:54 -08:00
Peter Johnson
1857417601 [sim] WSProvider_Joystick: Fix off-by-1 in incoming buttons (#3011) 2020-12-30 11:37:20 -08:00
Prateek Machiraju
ee7114a58c [glass] Add drive class widgets (#2975)
This adds widgets for DifferentialDrive and MecanumDrive.
2020-12-30 08:51:55 -08:00
Prateek Machiraju
00fa91d0d6 [glass] Use ImGui style for gyro widget colors (#3009)
This ensures that the colors are properly visible in light mode or any
other custom user styles.
2020-12-30 08:42:26 -08:00
Peter Johnson
b7a25bfc33 ThirdPartyNotices: Add portable file dialogs license (#3005) 2020-12-29 22:46:44 -08:00
Austin Shalit
a2e46b9a1b [glass] modernize-use-nullptr (NFC) (#3006) 2020-12-29 22:46:11 -08:00
Peter Johnson
a751fa22d2 [build] Apply spotless for java formatting (#1768)
Update checkstyle config to be compatible with spotless.

Co-authored-by: Austin Shalit <austinshalit@gmail.com>
2020-12-29 22:45:16 -08:00
Tyler Veness
e563a0b7db [wpimath] Make LinearSystemLoop move-constructible and move-assignable (#2967) 2020-12-29 20:50:26 -08:00
Austin Shalit
49085ca943 [glass] Add context menus to remove and add NetworkTables values (#2979) 2020-12-29 20:49:29 -08:00
Peter Johnson
560a850a2b [glass] Add NetworkTables Log window (#2997)
This moves NetworkTable log messages out of the console (which is hidden on some platforms).
2020-12-29 20:47:58 -08:00
PJ Reiniger
66782e2317 [sim] Create Left/Right drivetrain current accessors (#3001) 2020-12-29 20:46:51 -08:00
Peter Johnson
b60eb1544b clang-tidy: bugprone-virtual-near-miss
A few virtual functions are called by constructors or destructors, which is
dangerous in C++ (as an overridden virtual impl won't be called, only the
one in the current class).  Fix by either marking the function final or
not calling at all (if possible).
2020-12-29 14:26:19 -08:00
Peter Johnson
cbe59fa3bf clang-tidy: google-explicit-constructor 2020-12-29 14:26:19 -08:00
Peter Johnson
c97c6dc065 clang-tidy: google-readability-casting (NFC) 2020-12-29 14:26:19 -08:00
Peter Johnson
32fa97d68d clang-tidy: modernize-use-nullptr (NFC) 2020-12-29 14:26:19 -08:00
Peter Johnson
aee4603269 clang-tidy: modernize-pass-by-value 2020-12-29 14:26:19 -08:00
Peter Johnson
29c7da5f1a clang-tidy: modernize-make-unique 2020-12-29 14:26:19 -08:00
Peter Johnson
6131f4e32b clang-tidy: modernize-concat-nested-namespaces (NFC) 2020-12-29 14:26:19 -08:00
Peter Johnson
67e03e625d clang-tidy: modernize-use-equals-default 2020-12-29 14:26:19 -08:00
Peter Johnson
b124f9101b clang-tidy: modernize-use-default-member-init 2020-12-29 14:26:19 -08:00
Peter Johnson
d11a3a6380 clang-tidy: modernize-use-override (NFC)
Add NOLINT to CommandTestBase due to gmock not adding "override" keyword,
which causes warnings on clang.
2020-12-29 14:26:19 -08:00
Peter Johnson
4cc0706b06 clang-tidy: modernize-use-using (NFC)
Excludes C-compatible headers
2020-12-29 14:26:19 -08:00
Tyler Veness
885f5a9781 [wpilibc] Speed up ScopedTracerTest (#2999)
ScopedTracerTest now uses simulation time instead of wall clock time, so
it doesn't have to actually wait 1.5 seconds.
2020-12-29 10:30:23 -08:00
sciencewhiz
60b5964577 [wpilibj] Fix typos (NFC) (#3000) 2020-12-29 10:29:39 -08:00
Austin Shalit
6e1919414e [build] Bring naming checkstyle rules up to date with Google Style guide (#1781)
Also update Checkstyle to 8.38.

Google changed their style guide from the last time we imported it. This PR brings in those naming changes. The change they made is allowing single letter member, parameter, and local variable names. They also added a lambda naming scheme and I thought it would be good to bring that in too.
2020-12-29 09:27:48 -08:00
Tyler Veness
8c8ec5e63e [wpilibj] Suppress unchecked cast warnings (#2995) 2020-12-28 17:13:34 -08:00
Peter Johnson
b8413ddd5b [wpiutil] Add noexcept to timestamp static functions (#2994)
This silences a clang-tidy warning.
2020-12-28 17:12:51 -08:00
Austin Shalit
5d976b6e18 [glass] Load NetworkTableView settings on first draw (#2993)
Before this change, user settings were not loaded until after the first time they opened the settings context menu.
2020-12-28 15:29:25 -08:00
Tyler Veness
2b4317452b Replace NOLINT(runtime/explicit) comments with NOLINT (NFC) (#2992)
cpplint.py can accept either, but clang-tidy requires NOLINT.
2020-12-28 15:10:31 -08:00
Peter Johnson
1c3011ba4b [glass] Fix handling of "/" NetworkTables key (#2991) 2020-12-28 14:36:30 -08:00
Peter Johnson
574a42f3b4 [hal] Fix UnsafeManipulateDIO status check (#2987) 2020-12-28 13:04:21 -08:00
Matt
9005cd59e5 [wpilib] Clamp input voltage in sim classes (#2955) 2020-12-28 13:03:31 -08:00
Peter Johnson
dd494d4ab7 [glass] NetworkTablesModel::Update(): Avoid use-after-move (#2988) 2020-12-28 13:02:24 -08:00
Peter Johnson
7cca469a12 [wpimath] NormalizeAngle: Make inline, remove unnamed namespace (#2986) 2020-12-28 13:00:26 -08:00
Peter Johnson
2aed432b4b Add braces to C++ single-line loops and conditionals (NFC) (#2973)
This makes code easier to read and more consistent between C++ and Java.
Also update clang-format settings to always add a line break (even if no braces are used).
2020-12-28 12:58:06 -08:00
Peter Johnson
0291a3ff56 [wpiutil] StringRef: Add noexcept to several constructors (#2984) 2020-12-28 11:34:50 -08:00
Peter Johnson
5d7315280a [wpimath] Update UnitsTest.cpp copyright (#2985) 2020-12-28 10:40:20 -08:00
Matt
254931b9a8 [wpimath] Remove LinearSystem from LinearSystemLoop (#2968)
The system wasn't being used internally, and as LinearSystem is stateless, it doesn't need to be held by LinearSystemLoop.
2020-12-28 10:35:51 -08:00
Prateek Machiraju
aa89744c95 Update OtherVersions.md to include wpimath info (#2983)
This also updates occurrences of 2020 to 2021.
2020-12-28 10:34:19 -08:00
Peter Johnson
1cda3f5ad7 [glass] Fix styleguide (#2976) 2020-12-26 14:31:24 -08:00
Peter Johnson
8f1f64ffb6 Remove year from file copyright message (NFC) (#2972)
Also update copyright to include "and other WPILib contributors" and clarify
license referral language to not be restricted to FIRST teams.
2020-12-26 14:12:05 -08:00
Peter Johnson
2bc0a7795c [examples] Fix wpiformat warning about utility include (#2971) 2020-12-26 09:34:21 -08:00
Peter Johnson
4204da6ad4 [glass] Add application icon 2020-12-25 22:08:37 -08:00
Peter Johnson
7ac39b10f7 [wpigui] Add icon support 2020-12-25 22:08:37 -08:00
Matt
6b567e0066 [wpimath] Add support for varying vision standard deviations in pose estimators (#2956)
Exposes the R passed to vision correct to users.
2020-12-24 16:05:07 -08:00
Tyler Veness
df299d6edd [wpimath] Add UnscentedKalmanFilter::Correct() overload (#2966)
This adds an overload of UnscentedKalmanFilter::Correct() that takes a
custom measurement covariance but uses default mean and residual
calculation functions.

Closes #2965.
2020-12-24 16:00:36 -08:00
Prateek Machiraju
4e34f05238 [examples] Use ADXRS450_GyroSim class in simulation example (#2964)
This class did not exist when the original example was written. This
also changes the C++ example to use ADXRS450_Gyro for the sake of
consistency.
2020-12-24 15:42:46 -08:00
Tyler Veness
9962f6fd79 [wpilib] Give Field2d a default Sendable name (#2953) 2020-12-24 12:26:03 -08:00
Peter Johnson
f9d492f4b1 [sim] GUI: Show "Other Devices" window by default (#2961) 2020-12-24 12:24:36 -08:00
Peter Johnson
a8bb2ef1c3 [sim] Fix ADXRS450_GyroSim and DutyCycleEncoderSim (#2963)
These were broken by #2952.

Also fix Java ADXRS450_Gyro angle/rate SimValue names.
2020-12-24 12:23:38 -08:00
Peter Johnson
240c629cda [sim] Try to guess "Map Gamepad" setting (#2960)
Looks to see if the joystick name starts with "Xbox" or contains "pad".
2020-12-23 20:38:28 -08:00
Tyler Veness
952567dd3c [wpilibc] Add missing move constructors and assignment operators (#2959)
- Field2d
- FieldObject2d
- AnalogGyro
2020-12-23 20:36:51 -08:00
Peter Johnson
10b396b4c2 [sim] Various WebSockets fixes and enhancements (#2952)
This is a breaking change to the WebSockets layer to align it with
recent specification documentation work.

To support this, HAL SimValue changed readonly to a direction enum.
This allows specifying bidirectional in addition to input and output.

The SimValue change is specifically designed to avoid API and ABI breakage.
This is completely transparent in C++; in Java a new callback class was added,
and the old readonly functions have been marked deprecated.

A new SimValue creation function for enums allows specifying double values
for each enum value, not just strings.  This allows mapping enum values to
doubles in the WebSockets layer.

A ":" in the SimDevice name now maps it to different WebSocket types (e.g.
"Accel:Name" becomes type "Accel", device "Name").  The type is hidden
in the GUI.

Other WebSockets changes:
* Implemented match_time and game_data
* Added joystick rumble data
* Added builtin accelerometer support
* SimValue enums are mapped to string and double value on WS interface
* Added WebSockets protocol specification
* Added READMEs
2020-12-23 15:54:11 -08:00
sciencewhiz
699bbe21a4 [examples] Fix comments in Gearsbot to match implementation (NFC) (#2957) 2020-12-22 22:26:54 -08:00
Prateek Machiraju
27b67deca6 [glass] Add more widgets (#2947)
This adds the following widgets:
- Speed Controller
- Gyroscope
- Command
- Subsystem
- PIDController
- Scheduler
2020-12-22 21:07:44 -08:00
Peter Johnson
581b7ec553 [wpilib] Add option to flush NetworkTables every iterative loop
This functionality is disabled by default, but can be enabled by the user
program by calling setNetworkTablesFlushEnabled.
2020-12-21 09:53:45 -08:00
Peter Johnson
acfbb1a44a [ntcore] DispatcherBase::Flush: Use wpi::Now()
This is faster on some platforms than steady_clock, and will more
consistently support simulation timing.
2020-12-21 09:53:45 -08:00
Peter Johnson
d85a6d8fe4 [ntcore] Reduce limit on flush and update rate to 5 ms 2020-12-21 09:53:45 -08:00
Tyler Veness
20fbb5c63b [sim] Fix stringop truncation warning from GCC 10 (#2945)
If the strncpy() bound is equal to the destination size and the source
string is longer than 256 bytes, strncpy() won't write a null terminator
for the destination string.
2020-12-17 21:51:57 -08:00
Peter Johnson
1051a06a76 [glass] Show NT timestamps in seconds (#2944) 2020-12-17 07:29:00 -08:00
Peter Johnson
98dfc26208 [glass] Fix plots (#2943) 2020-12-17 07:27:29 -08:00
Peter Johnson
1ba0a2cedd [sim] GUI: Add keyboard virtual joystick support (#2940)
This allows joystick testing without a physical joystick.
Comes with a default set of keyboard mappings, but these are fully customizable by the user.
Up to 4 virtual joysticks are supported.

Default keyboard mappings:

    Joystick 0: axis 0: AD, axis 1: WS, axis 2: ER, buttons ZXCV, POV on numeric keypad
    Joystick 1: axis 0: JL, axis 1: IK, buttons M,./
    Joystick 2: axis 0: left/right arrow, axis 1: up/down arrow, buttons insert/home/pgup/del/end/pgdn

Also adds support for DS-style hotkeys of []\ enable, Enter disable, and spacebar disable.
All of these are disabled by default and must be explicitly enabled by the user.
2020-12-17 00:20:12 -08:00
Tyler Veness
4afb13f98b [examples] Replace M_PI with wpi::math::pi (#2938) 2020-12-17 00:15:02 -08:00
Zhiquan Yeo
b27d33675d [examples] Enhance Romi templates (#2931)
Add motors and encoders so they are more usable out of the box.
2020-12-10 21:38:27 -08:00
Peter Johnson
00b9ae77f9 [sim] Change default WS port number to 3300 (#2932) 2020-12-10 20:39:14 -08:00
Prateek Machiraju
65219f3093 [examples] Update Field2d position in periodic() (#2928)
This ensures that the robot position will be updated in dashboards like Glass when running on real hardware.
2020-12-10 20:36:20 -08:00
Peter Johnson
f78d1d4340 [sim] Process WS Encoder reset internally (#2927)
Currently, Encoder.reset() must make a round trip to the sensor and back
in order for the count to be updated for the user program.  As the sim layer
also resets the internal encoder count, this creates a race condition (a WS
message with a new count can be "in flight" during a reset and update the
count).

This changes the WS layer to not put reset on the wire, but instead keep an
offset count internal to the robot program.  The value on the wire is not
reset, but rather all sends and receives are adjusted as necessary to the
internal robot count.

This approach is straightforward, but does result in the value on the wire
not matching the value in the user program.  A future improvement will fix
this, but this change fixes the immediate race condition problem.
2020-12-10 20:30:12 -08:00
Peter Johnson
941edca597 [hal] Add Java SimDeviceDataJNI.getSimDeviceName (#2924)
This was mistakenly omitted from the Java interface.
2020-12-08 20:42:46 -08:00
Matt
a699435ede [wpilibj] Fix FlywheelSim argument order in constructor (#2922) 2020-12-07 22:34:17 -08:00
Prateek Machiraju
66d6417189 [examples] Add tasks to run Java examples (#2920)
Example: ./gradlew :wpilibjExamples:runstatespacedifferentialdrivesimulation
2020-12-07 22:33:17 -08:00
Prateek Machiraju
558e37c412 [examples] Add simple differential drive simulation example (#2918)
This provides an example of using the differential drive simulator without needing to use the command-based library.
2020-12-07 22:32:42 -08:00
Thad House
4f40d991ea [glass] Switch name of Glass back to glass (#2919)
On Unix systems, most executables are lowercase.
2020-12-07 22:32:15 -08:00
Prateek Machiraju
549af99007 [build] Update native-utils to 2021.0.6 (#2914)
This fixes the Glass publishing classifier
2020-12-05 23:58:42 -08:00
Thad House
b336930093 [glass] Change basename of glass to Glass (#2915)
Was glassApp, which makes building an extraction setup much harder.
2020-12-05 23:56:12 -08:00
Prateek Machiraju
c9a0edfb8b [glass] Package macOS application bundle 2020-12-05 23:23:35 -08:00
Prateek Machiraju
2c5668af46 [wpigui] Add platform-specific preferences save 2020-12-05 23:23:35 -08:00
Peter Johnson
751dea32ae [wpilibc] Try to work around ABI break introduced in #2901 (#2917)
The change to SendableBuilder to add GetTable() added a virtual function
early in the class definition.  This is an ABI break for vendor libraries.
Attempt to workaround this breakage by moving GetTable() to the end of the
class definition.
2020-12-05 23:19:15 -08:00
Thad House
cd8f4bfb1f [build] Package up msvc runtime into maven artifact (#2913)
This will make is so we can get the right artifact to the installer, and we can do it automatically and its guaranteed to match what built the artifacts.
2020-12-05 20:14:03 -08:00
Tyler Veness
a6cfcc6866 [wpilibc] Move SendableChooser Doxygen comments to header (NFC) (#2911) 2020-12-05 20:04:44 -08:00
Tyler Veness
b8c4f603db [wpimath] Upgrade to Eigen 3.3.9 (#2910)
It fixes some compilation errors with C++20.
2020-12-05 20:03:47 -08:00
Prateek Machiraju
0075e4b391 [wpilibj] Fix NPE in Field2d (#2909) 2020-12-05 08:46:54 -08:00
Peter Johnson
125af556ce [simulation] Fix halsim_gui ntcore and wpiutil deps (#2908)
They were being linked out of order, so ntcore wasn't being linked.
2020-12-04 23:30:17 -08:00
Matt
963ad5c255 [wpilib] Add noise to Differential Drive simulator (#2903)
Co-authored-by: Prateek Machiraju <prateek.machiraju@gmail.com>
2020-12-04 18:46:50 -08:00
Peter Johnson
387f56cb7b [examples] Add Romi reference Java example and templates (#2905) 2020-12-04 17:34:54 -08:00
Prateek Machiraju
b3deda38c9 [examples] Zero motors on disabledInit() in sim physics examples (#2906)
This ensures that mechanisms will stop moving if the robot is disabled while motors are in motion
2020-12-04 17:34:16 -08:00
Peter Johnson
2a5ca77454 [glass] Add glass: an application for display of robot data
This reuses many pieces of the current simulation GUI.  The common pieces have
been refactored into the libglass library.

The libglass library is designed to be usable for other standalone data
visualization applications (e.g. viewing data logs).

The name "glass" comes from "glass cockpit", as the application features
several multi-function displays that can be adjusted to display robot
information as needed.
2020-12-04 00:36:55 -08:00
Peter Johnson
727940d847 [wpilib] Move Field2d to SmartDashboard 2020-12-04 00:36:55 -08:00
Peter Johnson
8cd42478e1 [wpilib] SendableBuilder: Make GetTable() visible 2020-12-04 00:36:55 -08:00
Prateek Machiraju
c11d34b26c [command] Use addCommands in command group templates (#2900)
This makes the Java templates consistent with the C++ templates as well as the documentation

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
2020-12-01 20:52:45 -08:00
Peter Johnson
339d7445b3 [sim] Add HAL hooks for simulationPeriodic (#2881)
This allows vendor libs to hook into the begin or end of simulationPeriodic().
2020-11-30 23:55:36 -08:00
Peter Johnson
d16f05f2c8 [wpilib] Fix SmartDashboard update order (#2896)
We need to execute listener tasks first, then execute value updates.
Otherwise local changes can fight with dashboard-made changes.
2020-11-30 19:24:12 -08:00
Peter Johnson
5427b32a40 [wpiutil] unique_function: Restrict implicit conversion (#2899)
Only implicitly convert from invocable objects.  This avoids potential
ambiguity in higher-level overloaded functions.
2020-11-30 19:21:10 -08:00
Peter Johnson
f73701239d [ntcore] Add missing SetDefault initializer_list functions (#2898) 2020-11-30 19:20:40 -08:00
Peter Johnson
f5a6fc0703 [sim] Add initialized flag for all solenoids on a PCM (#2897)
This allows much easier/faster checking for whether any solenoid has been
initialized on a particular PCM.
2020-11-30 19:20:16 -08:00
Prateek Machiraju
bdf5ba91a4 [wpilibj] Fix typo in ElevatorSim (#2895)
This caused an illegal argument exception whenever the simulated elevator velocity was retrieved.
2020-11-29 22:28:11 -08:00
Declan Freeman-Gleason
bc8f338771 [wpilib] Add pose estimators (#2867)
Pose and state estimators can filter latency-compensated global measurements and fuse them with state-space drivetrain model information to estimate robot position. They are drop-in replacements for the existing odometry classes.

Co-authored-by: Declan Freeman-Gleason <declanfreemangleason@gmail.com>
Co-authored-by: Prateek Machiraju <prateek.machiraju@gmail.com>
Co-authored-by: Claudius Tewari <cttewari@gmail.com>
Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2020-11-28 14:35:35 -08:00
Tyler Veness
3413bfc06a [wpilib] PIDController: Recompute the error in AtSetpoint() (#2822)
This makes AtSetpoint() return false after the setpoint is changed with
SetSetpoint().

Closes #2821.

Co-authored-by: Prateek Machiraju <prateek.machiraju@gmail.com>
2020-11-28 14:33:17 -08:00
Prateek Machiraju
2056f0ce09 [wpilib] Fix bugs in Hatchbot examples (#2893)
This fixes an issue with some commands not correctly requiring their
subsytems. Furthermore, an execute() method was added to the
DriveDistance command to continuously update the voltage command.
2020-11-28 14:01:56 -08:00
Peter Johnson
5eb8cfd691 [wpilibc] Fix MatchDataSender (#2892)
The is_convertible test was always treating the input as bool.
Use is_same on T instead.
2020-11-27 22:06:08 -08:00
Thad House
e6a4254488 [build] Delete test folders after tests execute (#2891)
Also deletes object files.

Both of these things are only done on the build server (-PbuildServer flag).

This will remove all test folders, which removes lots of copies of dependencies.

This also fixes an issue where gtest exectubables were installed for cross builds, even though they should not have been.
2020-11-27 21:44:47 -08:00
Prateek Machiraju
d478ad00d0 [imgui] Allow usage of imgui_stdlib (#2889)
This bumps the version number of thirdparty-imgui in Gradle and adds
imgui_stdlib.cpp into the sources in CMake, as well as adding a new
include directory.
2020-11-26 19:28:24 -08:00
Prateek Machiraju
53eda861de [build] Add unit-testing infrastructure to examples (#2863)
This also adds CMake capabilities to the command-based libraries as well
as wpilibExamples.
2020-11-26 11:47:35 -08:00
Prateek Machiraju
cc1d86ba63 [sim] Add title to simulator GUI window (#2888) 2020-11-26 11:46:14 -08:00
Prateek Machiraju
f0528f00e7 [build] CMake: Use project-specific binary and source dirs (#2886)
This ensures that allwpilib will still build correctly when added as a CMake external project.
2020-11-24 20:25:44 -08:00
Tyler Veness
5cd2ad124d [wpilibc] Add Color::operator!= (#2887) 2020-11-24 19:26:00 -08:00
Tyler Veness
6c00e7a902 [build] CI CMake: build with GUI enabled (#2884) 2020-11-24 13:37:39 -08:00
Tyler Veness
53170bbb58 Update roboRIO toolchain installation instructions (#2883)
There were conflicting instructions: install via the archive on
the releases page, and install using a gradlew command.
2020-11-23 19:48:26 -08:00
Dean Brettle
467258e050 [sim] GUI: Add option to not zero disconnected joysticks (#2876)
This allows team sim code to set the joystick values and not have them overwritten by the GUI.
2020-11-23 19:46:27 -08:00
Tyler Veness
129be23c9e Clarify JDK installation instructions in readme (#2882) 2020-11-23 19:45:14 -08:00
Prateek Machiraju
8e9290e86e [build] Add separate CMake setting for wpimath (#2885)
This allows external CMake projects to only depend on wpimath instead of
having to build the entire library.
2020-11-23 19:44:20 -08:00
Starlight220
7cf5bebf8e [wpilibj] Cache NT writes from DriverStation (#2780)
This reduces malloc traffic.
2020-11-21 14:35:43 -08:00
Prateek Machiraju
f7f9087fb5 [command] Fix timing issue in RamseteCommand (#2871)
This issue only existed on the initial iteration. When timing is paused and stepped,
initialize() and execute() get called with the same timestamp the first time, which
would result in a divide by zero. All subsequent steps advance timing and only
call execute() so the time deltas are all set correctly.
2020-11-21 10:03:01 -08:00
CoolSpy3
256e7904fd [wpilibj] SimDeviceSim: Fix sim value changed callback (#2880) 2020-11-20 21:02:23 -08:00
Tyler Veness
c8ea1b6c38 [wpilib] Add function to adjust LQR controller gain for pure time delay (#2878)
There were three options for where to put this function:

1. A free function in LinearQuadraticRegulator.h. Returning a K matrix
   means the user can't use the LinearQuadraticRegulator in a loop
   anymore.
2. A default argument added to ctors in LinearQuadraticRegulator for a
   time delay (default of 0). This has the smallest API footprint from
   the user perspective, but it bloats the already substantial
   constructor overload set of LinearQuadraticRegulator.
3. A member function in LinearQuadraticRegulator that modifies the
   internal K. This would still have to take in a LinearSystem or (A, B)
   pair because the ctor doesn't store it. Storing it internally feels
   like paying for what we don't use most of the time.

I went with option 3.

I verified the tests's expected values in Python with
scipy.linalg.fractional_matrix_power().

Closes #2877.
2020-11-20 15:28:00 -08:00
Peter Johnson
2816b06c05 [sim] HAL_GetControlWord: Fully zero output (#2873)
This ensures the padding is zero'ed.  We already do this on Athena, we just didn't in sim.
2020-11-20 15:11:11 -08:00
Tyler Veness
4c695ea088 Add toolchain installation instructions to README (#2875) 2020-11-19 13:09:09 -08:00
4068 changed files with 229928 additions and 112725 deletions

View File

@@ -14,10 +14,10 @@ AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortFunctionsOnASingleLine: Inline
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
@@ -157,7 +157,7 @@ SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
Standard: c++17
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION

75
.clang-tidy Normal file
View File

@@ -0,0 +1,75 @@
Checks:
'bugprone-assert-side-effect,
bugprone-bool-pointer-implicit-conversion,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-virtual-near-miss,
cert-dcl58-cpp,
cert-err52-cpp,
cert-err60-cpp,
cert-mem57-cpp,
cert-oop57-cpp,
cert-oop58-cpp,
clang-diagnostic-*,
-clang-diagnostic-deprecated-declarations,
-clang-diagnostic-#warnings,
-clang-diagnostic-pedantic,
clang-analyzer-*,
cppcoreguidelines-slicing,
google-build-namespaces,
google-explicit-constructor,
google-global-names-in-headers,
google-readability-avoid-underscore-in-googletest-name,
google-readability-casting,
google-runtime-operator,
llvm-twine-local,
misc-definitions-in-headers,
misc-misplaced-const,
misc-new-delete-overloads,
misc-non-copyable-objects,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-use-default-member-init,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
readability-braces-around-statements'
FormatStyle: file
CheckOptions:
- key: bugprone-dangling-handle
value: 'wpi::StringRef;wpi::Twine'

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
*.gradle text eol=lf
*.java text eol=lf
*.md text eol=lf
*.xml text eol=lf

View File

@@ -22,7 +22,8 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows]
- WPILib Version: [e.g. 2021.3.1]
- OS: [e.g. Windows 11]
- Java version [e.g. 1.10.2]
- C++ version [e.g. 17]

65
.github/workflows/cmake.yml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: CMake
on: [pull_request, push]
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
name: Linux
container: wpilib/roborio-cross-ubuntu:2022-20.04
flags: ""
- os: macOS-11
name: macOS
container: ""
flags: "-DWITH_JAVA=OFF"
name: "Build - ${{ matrix.name }}"
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
if [ "$RUNNER_OS" == "macOS" ]; then
brew install opencv
fi
- 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)
- name: test
working-directory: build
run: ctest --output-on-failure
build-vcpkg:
name: "Build - Windows"
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Prepare vcpkg
uses: lukka/run-vcpkg@v7
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
run: ctest -C "Debug" --output-on-failure
working-directory: ${{ runner.workspace }}/build

60
.github/workflows/documentation.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Documentation
on: [push, workflow_dispatch]
env:
BASE_PATH: allwpilib/docs
jobs:
publish:
name: "Documentation - Publish"
runs-on: ubuntu-latest
if: github.repository_owner == 'wpilibsuite' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-java@v1
with:
java-version: 13
- name: Install libclang-9
run: sudo apt update && sudo apt install -y libclang-cpp9 libclang1-9
- name: Set environment variables (Development)
run: |
echo "TARGET_FOLDER=$BASE_PATH/development" >> $GITHUB_ENV
if: github.ref == 'refs/heads/main'
- name: Set environment variables (Tag)
run: |
echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
echo "TARGET_FOLDER=$BASE_PATH/beta" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v')
- name: Set environment variables (Release)
run: |
echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
echo "TARGET_FOLDER=$BASE_PATH/release" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, 'alpha') && !contains(github.ref, 'beta')
- name: Build with Gradle
run: ./gradlew docs:generateJavaDocs docs:doxygen -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
- name: Install SSH Client 🔑
uses: webfactory/ssh-agent@v0.4.1
with:
ssh-private-key: ${{ secrets.GH_DEPLOY_KEY }}
- name: Deploy Java 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
SSH: true
REPOSITORY_NAME: wpilibsuite/wpilibsuite.github.io
BRANCH: main
CLEAN: true
FOLDER: docs/build/docs/javadoc
TARGET_FOLDER: ${{ env.TARGET_FOLDER }}/java
- name: Deploy C++ 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
SSH: true
REPOSITORY_NAME: wpilibsuite/wpilibsuite.github.io
BRANCH: main
CLEAN: true
FOLDER: docs/build/docs/doxygen/html
TARGET_FOLDER: ${{ env.TARGET_FOLDER }}/cpp

15
.github/workflows/gazebo.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Gazebo
on: [pull_request, push]
jobs:
build:
name: "Build"
runs-on: ubuntu-latest
container: wpilib/gazebo-ubuntu:18.04
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Build with Gradle
run: ./gradlew simulation:frc_gazebo_plugins:build simulation:halsim_gazebo:build -PbuildServer -PforceGazebo

View File

@@ -1,5 +1,5 @@
name: "Validate Gradle Wrapper"
on: [push, pull_request]
on: [pull_request, push]
jobs:
validation:

View File

@@ -1,4 +1,4 @@
name: CI
name: Gradle
on: [pull_request, push]
@@ -8,7 +8,7 @@ jobs:
fail-fast: false
matrix:
include:
- container: wpilib/roborio-cross-ubuntu:2021-18.04
- container: wpilib/roborio-cross-ubuntu:2022-18.04
artifact-name: Athena
build-options: "-Ponlylinuxathena"
- container: wpilib/raspbian-cross-ubuntu:10-18.04
@@ -31,24 +31,26 @@ jobs:
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v')
- name: Build with Gradle
run: ./gradlew build -PbuildServer ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
run: ./gradlew build -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.artifact-name }}
path: build/allOutputs
build-host:
env:
MACOSX_DEPLOYMENT_TARGET: 10.14
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
- os: windows-2019
artifact-name: Win64
architecture: x64
- os: windows-latest
- os: windows-2019
artifact-name: Win32
architecture: x86
- os: macos-latest
- os: macOS-11
artifact-name: macOS
architecture: x64
name: "Build - ${{ matrix.artifact-name }}"
@@ -69,23 +71,23 @@ jobs:
keychain-password: ${{ secrets.APPLE_KEYCHAIN_PASSWORD }}
if: |
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
- name: Set Keychain Lock Timeout
run: security set-keychain-settings -lut 3600
if: |
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
- name: Set release environment variable
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
shell: bash
if: startsWith(github.ref, 'refs/tags/v')
- name: Build with Gradle
run: ./gradlew build -PbuildServer ${{ env.EXTRA_GRADLE_ARGS }}
run: ./gradlew build -PbuildServer -PskipJavaFormat ${{ env.EXTRA_GRADLE_ARGS }}
- name: Sign Libraries with Developer ID
run: ./gradlew build -PbuildServer -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ env.EXTRA_GRADLE_ARGS }}
run: ./gradlew build -PbuildServer -PskipJavaFormat -PdeveloperID=${{ secrets.APPLE_DEVELOPER_ID }} ${{ env.EXTRA_GRADLE_ARGS }}
if: |
matrix.artifact-name == 'macOS' && (github.repository_owner == 'wpilibsuite' &&
(github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')))
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
- uses: actions/upload-artifact@v2
with:
name: ${{ matrix.artifact-name }}
@@ -101,6 +103,8 @@ jobs:
- uses: actions/setup-java@v1
with:
java-version: 13
- name: Install libclang-9
run: sudo apt update && sudo apt install -y libclang-cpp9 libclang1-9
- name: Set release environment variable
run: echo "EXTRA_GRADLE_ARGS=-PreleaseMode" >> $GITHUB_ENV
if: startsWith(github.ref, 'refs/tags/v')
@@ -111,84 +115,6 @@ jobs:
name: Documentation
path: docs/build/outputs
build-cmake:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
name: Linux
container: wpilib/roborio-cross-ubuntu:2020-18.04
flags: ""
- os: macos-latest
name: macOS
container: ""
flags: "-DWITH_JAVA=OFF"
name: "Build - CMake ${{ matrix.name }}"
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
if [ "$RUNNER_OS" == "macOS" ]; then
brew install opencv
fi
- name: configure
run: mkdir build && cd build && cmake -DWITH_GUI=OFF ${{ matrix.flags }} ..
- name: build
working-directory: build
run: make -j3
- name: test
working-directory: build
run: make test
build-cmake-vcpkg:
name: "Build - CMake Windows"
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Prepare vcpkg
uses: lukka/run-vcpkg@v4
with:
vcpkgArguments: opencv
vcpkgDirectory: ${{ runner.workspace }}/vcpkg/
vcpkgGitCommitId: 544f8e4593764f78faa94bac2adb81cca5232943
vcpkgTriplet: x64-windows
- name: Configure & Build
uses: lukka/run-cmake@v3
with:
buildDirectory: ${{ runner.workspace }}/build/
cmakeAppendedArgs: -DWITH_JAVA=OFF
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
useVcpkgToolchainFile: true
- name: Run Tests
run: ctest -C "Debug"
working-directory: ${{ runner.workspace }}/build/
wpiformat:
name: "wpiformat"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Fetch all history and metadata
run: |
git fetch --prune --unshallow
git checkout -b pr
git branch -f master origin/master
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install clang-format
run: sudo apt-get update -q && sudo apt-get install clang-format-10
- name: Install wpiformat
run: pip3 install wpiformat
- name: Run
run: wpiformat -clang 10
- name: Check Output
run: git --no-pager diff --exit-code HEAD
combine:
name: Combine
needs: [build-docker, build-host, build-documentation]
@@ -212,15 +138,15 @@ jobs:
- name: Combine
if: |
!startsWith(github.ref, 'refs/tags/v') &&
github.ref != 'refs/heads/master'
github.ref != 'refs/heads/main'
run: cd combiner && ./gradlew publish -Pallwpilib
- name: Combine (Master)
if: |
github.repository_owner == 'wpilibsuite' &&
github.ref == 'refs/heads/master'
github.ref == 'refs/heads/main'
run: cd combiner && ./gradlew publish -Pallwpilib
env:
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
- name: Combine (Release)
@@ -229,7 +155,7 @@ jobs:
startsWith(github.ref, 'refs/tags/v')
run: cd combiner && ./gradlew publish -Pallwpilib -PreleaseRepoPublish
env:
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
RUN_AZURE_ARTIFACTORY_RELEASE: "TRUE"
ARTIFACTORY_PUBLISH_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
ARTIFACTORY_PUBLISH_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
- uses: actions/upload-artifact@v2

100
.github/workflows/lint-format.yml vendored Normal file
View File

@@ -0,0 +1,100 @@
name: Lint and Format
on:
pull_request:
push:
branches-ignore:
- main
jobs:
wpiformat:
name: "wpiformat"
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-20.04
steps:
- uses: actions/checkout@v2
- 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.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
run: wpiformat -clang 12
- name: Check output
run: git --no-pager diff --exit-code HEAD
- name: Generate diff
run: git diff HEAD > wpiformat-fixes.patch
if: ${{ failure() }}
- uses: actions/upload-artifact@v2
with:
name: wpiformat fixes
path: wpiformat-fixes.patch
if: ${{ failure() }}
tidy:
name: "clang-tidy"
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-20.04
steps:
- uses: actions/checkout@v2
- 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.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install clang-tidy
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-tidy-12 clang-format-12
- name: Install wpiformat
run: pip3 install wpiformat
- name: Create compile_commands.json
run: ./gradlew generateCompileCommands -Ptoolchain-optional-roboRio
- name: List changed files
run: wpiformat -list-changed-files
- name: Run clang-tidy
run: wpiformat -clang 12 -no-format -tidy-changed -compile-commands=build/compile_commands/linuxx86-64 -vv
javaformat:
name: "Java format"
runs-on: ubuntu-latest
container: wpilib/ubuntu-base:18.04
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Run Java format
run: ./gradlew javaFormat spotbugsMain spotbugsTest spotbugsDev
- name: Check output
run: git --no-pager diff --exit-code HEAD
- name: Generate diff
run: git diff HEAD > javaformat-fixes.patch
if: ${{ failure() }}
documentation:
name: "Documentation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-java@v1
with:
java-version: 13
- name: Install libclang-9
run: sudo apt update && sudo apt install -y libclang-cpp9 libclang1-9
- name: Build with Gradle
run: ./gradlew docs:zipDocs -PbuildServer -PdocWarningsAsErrors ${{ env.EXTRA_GRADLE_ARGS }}

49
.github/workflows/sanitizers.yml vendored Normal file
View File

@@ -0,0 +1,49 @@
name: Sanitizers
on: [pull_request, push]
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- name: asan
cmake-flags: "-DCMAKE_BUILD_TYPE=Asan"
ctest-env: ""
ctest-flags: "-E 'wpiutil|ntcore|wpilibc'"
- name: tsan
cmake-flags: "-DCMAKE_BUILD_TYPE=Tsan"
ctest-env: "TSAN_OPTIONS=second_deadlock_stack=1"
ctest-flags: "-E 'ntcore|cscore|cameraserver|wpilibc|wpilibNewCommands'"
- name: ubsan
cmake-flags: "-DCMAKE_BUILD_TYPE=Ubsan"
ctest-env: ""
ctest-flags: ""
name: "${{ matrix.name }}"
runs-on: ubuntu-latest
container: wpilib/roborio-cross-ubuntu:2022-20.04
steps:
- uses: actions/checkout@v2
- name: Install Dependencies
run: |
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt install -y gcc-11 g++-11
sudo update-alternatives \
--install /usr/bin/gcc gcc /usr/bin/gcc-11 11 \
--slave /usr/bin/g++ g++ /usr/bin/g++-11
sudo update-alternatives --set gcc /usr/bin/gcc-11
- name: Set up Python 3.8
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install jinja
run: python -m pip install jinja2
- name: configure
run: mkdir build && cd build && cmake ${{ matrix.cmake-flags }} ..
- name: build
working-directory: build
run: cmake --build . -j$(nproc)
- name: test
working-directory: build
run: ${{ matrix.ctest-env }} ctest --output-on-failure ${{ matrix.ctest-flags }}

7
.gitignore vendored
View File

@@ -222,5 +222,12 @@ compile_commands.json
# clang configuration and clangd cache
.clang
.clangd/
.cache/
imgui.ini
# Bazel
/.ijwb/
/bazel-*
user.bazelrc
coverage_report/

View File

@@ -9,9 +9,15 @@ cppSrcFileInclude {
\.cpp$
}
modifiableFileExclude {
\.patch$
gradlew
}
generatedFileExclude {
FRCNetComm\.java$
simulation/gz_msgs/src/include/simulation/gz_msgs/msgs\.h$
fieldImages/src/main/native/resources/
}
repoRootNameOverride {
@@ -23,6 +29,7 @@ includeOtherLibs {
^cameraserver/
^cscore
^drake/
^fmt/
^hal/
^imgui
^implot

View File

@@ -1,6 +1,3 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) {year} FIRST. All Rights Reserved.{padding}*/
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

View File

@@ -1,6 +1,6 @@
{
"enableCppIntellisense": true,
"currentLanguage": "cpp",
"projectYear": "2020",
"projectYear": "intellisense",
"teamNumber": 0
}

View File

@@ -1,25 +1,33 @@
# Disable in-source builds to prevent source tree corruption.
if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")
if(" ${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL " ${CMAKE_CURRENT_BINARY_DIR}")
message(FATAL_ERROR "
FATAL: In-source builds are not allowed.
You should create a separate directory for build files.
")
endif()
if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
set(CMAKE_SYSTEM_VERSION 10.0.18362.0 CACHE STRING INTERNAL FORCE)
set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION 10.0.18362.0 CACHE STRING INTERNAL FORCE)
endif()
project(allwpilib)
cmake_minimum_required(VERSION 3.3.0)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
message(STATUS "Platform version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
set(WPILIB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
INCLUDE(CPack)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${CMAKE_BINARY_DIR}/jar)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${WPILIB_BINARY_DIR}/bin)
set(CMAKE_JAVA_TARGET_OUTPUT_DIR ${WPILIB_BINARY_DIR}/jar)
# use, i.e. don't skip the full RPATH for the build tree
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
@@ -44,7 +52,10 @@ ENDIF("${isSystemDir}" STREQUAL "-1")
option(BUILD_SHARED_LIBS "Build with shared libs (needed for JNI)" ON)
option(WITH_JAVA "Include java and JNI in the build" ON)
option(WITH_CSCORE "Build cscore (needs OpenCV)" ON)
option(WITH_WPILIB "Build hal, wpilibc/j, wpimath, and myRobot (needs OpenCV)" ON)
option(WITH_WPIMATH "Build wpimath" ON)
option(WITH_WPILIB "Build hal, wpilibc/j, and myRobot (needs OpenCV)" ON)
option(WITH_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)
option(WITH_SIMULATION_MODULES "Build simulation modules" ON)
@@ -54,6 +65,7 @@ option(WITH_EXTERNAL_HAL "Use a separately built HAL" OFF)
set(EXTERNAL_HAL_FILE "" CACHE FILEPATH "Location to look for an external HAL CMake File")
# Options for using a package manager (vcpkg) for certain dependencies.
option(USE_VCPKG_FMTLIB "Use vcpkg fmtlib" OFF)
option(USE_VCPKG_LIBUV "Use vcpkg libuv" OFF)
option(USE_VCPKG_EIGEN "Use vcpkg eigen" OFF)
@@ -106,6 +118,13 @@ FATAL: Cannot build simulation modules with wpilib disabled.
")
endif()
if (NOT WITH_WPIMATH AND WITH_WPILIB)
message(FATAL_ERROR "
FATAL: Cannot build wpilib without wpimath.
Enable wpimath by setting WITH_WPIMATH=ON
")
endif()
set( wpilib_dest wpilib)
set( include_dest wpilib/include )
set( main_lib_dest wpilib/lib )
@@ -126,6 +145,8 @@ if (USE_VCPKG_EIGEN)
set (EIGEN_VCPKG_REPLACE "find_package(Eigen3 CONFIG)")
endif()
find_package(LIBSSH 0.7.1)
if (WITH_FLAT_INSTALL)
set(WPIUTIL_DEP_REPLACE "include($\{SELF_DIR\}/wpiutil-config.cmake)")
set(NTCORE_DEP_REPLACE "include($\{SELF_DIR\}/ntcore-config.cmake)")
@@ -134,6 +155,8 @@ set(CAMERASERVER_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cameraserver-config.cmak
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(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
@@ -142,11 +165,82 @@ set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
set(WPIMATH_DEP_REPLACE "find_dependency(wpimath)")
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
set(WPILIBNEWCOMMANDS_DEP_REPLACE "find_dependency(wpilibNewCommands)")
set(WPILIBOLDCOMMANDS_DEP_REPLACE "find_dependency(wpilibOldCommands)")
endif()
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
set(SELF_DIR "$\{SELF_DIR\}")
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(isMultiConfig)
if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
endif()
if(NOT "Tsan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Tsan)
endif()
if(NOT "Ubsan" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Ubsan)
endif()
else()
set(allowedBuildTypes Asan Tsan Ubsan Debug Release RelWithDebInfo MinSizeRel)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()
set(CMAKE_C_FLAGS_ASAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Asan build type or configuration." FORCE)
set(CMAKE_CXX_FLAGS_ASAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Asan build type or configuration." FORCE)
set(CMAKE_EXE_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
"Linker flags to be used to create executables for Asan build type." FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_ASAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=address" CACHE STRING
"Linker lags to be used to create shared libraries for Asan build type." FORCE)
set(CMAKE_C_FLAGS_TSAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Tsan build type or configuration." FORCE)
set(CMAKE_CXX_FLAGS_TSAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=thread -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Tsan build type or configuration." FORCE)
set(CMAKE_EXE_LINKER_FLAGS_TSAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread" CACHE STRING
"Linker flags to be used to create executables for Tsan build type." FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_TSAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=thread" CACHE STRING
"Linker lags to be used to create shared libraries for Tsan build type." FORCE)
set(CMAKE_C_FLAGS_UBSAN
"${CMAKE_C_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C compiler for Ubsan build type or configuration." FORCE)
set(CMAKE_CXX_FLAGS_UBSAN
"${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer" CACHE STRING
"Flags used by the C++ compiler for Ubsan build type or configuration." FORCE)
set(CMAKE_EXE_LINKER_FLAGS_UBSAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined -fno-sanitize-recover=all" CACHE STRING
"Linker flags to be used to create executables for Ubsan build type." FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_UBSAN
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -fsanitize=undefined" CACHE STRING
"Linker lags to be used to create shared libraries for Ubsan build type." FORCE)
if (WITH_TESTS)
enable_testing()
add_subdirectory(googletest)
@@ -156,9 +250,24 @@ endif()
add_subdirectory(wpiutil)
add_subdirectory(ntcore)
if (WITH_WPIMATH)
add_subdirectory(wpimath)
endif()
if (WITH_GUI)
add_subdirectory(fieldImages)
add_subdirectory(imgui)
add_subdirectory(wpigui)
add_subdirectory(glass)
add_subdirectory(outlineviewer)
if (LIBSSH_FOUND)
add_subdirectory(roborioteamnumbersetter)
endif()
endif()
if (WITH_WPILIB OR WITH_SIMULATION_MODULES)
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
add_subdirectory(hal)
endif()
if (WITH_CSCORE)
@@ -166,20 +275,25 @@ if (WITH_CSCORE)
set(CAMERASERVER_DEP_REPLACE ${CAMERASERVER_DEP_REPLACE_IMPL})
add_subdirectory(cscore)
add_subdirectory(cameraserver)
if (WITH_WPILIB)
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
add_subdirectory(hal)
add_subdirectory(wpimath)
add_subdirectory(wpilibj)
add_subdirectory(wpilibc)
add_subdirectory(myRobot)
endif()
if (WITH_WPILIB)
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
add_subdirectory(wpilibj)
add_subdirectory(wpilibc)
add_subdirectory(wpilibNewCommands)
if (WITH_OLD_COMMANDS)
add_subdirectory(wpilibOldCommands)
endif()
if (WITH_EXAMPLES)
add_subdirectory(wpilibcExamples)
endif()
add_subdirectory(myRobot)
endif()
if (WITH_SIMULATION_MODULES AND NOT WITH_EXTERNAL_HAL)
add_subdirectory(simulation)
endif()
configure_file(wpilib-config.cmake.in ${CMAKE_BINARY_DIR}/wpilib-config.cmake )
install(FILES ${CMAKE_BINARY_DIR}/wpilib-config.cmake DESTINATION ${wpilib_config_dir})
configure_file(wpilib-config.cmake.in ${WPILIB_BINARY_DIR}/wpilib-config.cmake )
install(FILES ${WPILIB_BINARY_DIR}/wpilib-config.cmake DESTINATION ${wpilib_config_dir})

View File

@@ -1,6 +1,6 @@
# Contributing to WPILib
So you want to contribute your changes back to WPILib. Great! We have a few contributing rules that will help you make sure your changes will be accepted into the project. Please remember to follow the rules in the [code of conduct](https://github.com/wpilibsuite/allwpilib/blob/master/CODE_OF_CONDUCT.md), and behave with Gracious Professionalism.
So you want to contribute your changes back to WPILib. Great! We have a few contributing rules that will help you make sure your changes will be accepted into the project. Please remember to follow the rules in the [code of conduct](https://github.com/wpilibsuite/allwpilib/blob/main/CODE_OF_CONDUCT.md), and behave with Gracious Professionalism.
- [General Contribution Rules](#general-contribution-rules)
- [What to Contribute](#what-to-contribute)
@@ -41,11 +41,13 @@ WPILib uses modified Google style guides for both C++ and Java, which can be fou
While the library should be fully formatted according to the styles, additional elements of the style guide were not followed when the library was initially created. All new code should follow the guidelines. If you are looking for some easy ramp-up tasks, finding areas that don't follow the style guide and fixing them is very welcome.
When writing math expressions in documentation, use https://www.unicodeit.net/ to convert LaTeX to a Unicode equivalent that's easier to read. Not all expressions will translate (e.g., superscripts of superscripts) so focus on making it readable by someone who isn't familiar with LaTeX. If content on multiple lines needs to be aligned in Doxygen/Javadoc comments (e.g., integration/summation limits, matrices packed with square brackets and superscripts for them), put them in @verbatim/@endverbatim blocks in Doxygen or `<pre>` tags in Javadoc so they render with monospace font.
## Submitting Changes
### Pull Request Format
Changes should be submitted as a Pull Request against the master branch of WPILib. For most changes, commits will be squashed upon merge. For particularly large changes, multiple commits are ok, but assume one commit unless asked otherwise. We may ask you to break a PR into multiple standalone PRs or commits for rebase within one PR to separate unrelated changes. No change will be merged unless it is up to date with the current master. We do this to make sure that the git history isn't too cluttered.
Changes should be submitted as a Pull Request against the main branch of WPILib. For most changes, commits will be squashed upon merge. For particularly large changes, multiple commits are ok, but assume one commit unless asked otherwise. We may ask you to break a PR into multiple standalone PRs or commits for rebase within one PR to separate unrelated changes. No change will be merged unless it is up to date with the current main branch. We do this to make sure that the git history isn't too cluttered.
### Merge Process

View File

@@ -1,4 +1,4 @@
Copyright (c) 2009-2019 FIRST
Copyright (c) 2009-2022 FIRST and other WPILib contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -8,12 +8,12 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the FIRST nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
* Neither the name of FIRST, WPILib, nor the names of other WPILib
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY FIRST AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

View File

@@ -1,27 +1,27 @@
## Publishing Third Party Dependencies
Currently the 3rd party deps are imgui, opencv, and google test
For publishing these dependencies, the version needs to be manually updated in the publish.gradle file of their respective repository.
Then, in the azure build for the dependency you want to build for, manually start a pipeline build (As of current, this is the `Run Pipeline` button).
A variable needs to be added called `RUN_AZURE_ARTIFACTORY_RELEASE`, with a value of `true`. Then when the pipeline gets started, the final build outputs will be updated to artifactory.
To use newer versions of C++ dependencies, in `shared/config.gradle`, update the version related to the specific dependency.
For Java dependencies, there is likely a file related to the specific dependency in the shared folder. Update the version in there.
Note, changing artifact locations (This includes changing the artifact year currently, I have an issue open to change this) requires updating the `native-utils` plugin
## Publishing allwpilib
allwpilib publishes to the development repo on every push to master. To publish a release build, upload a new tag, and a release will automatically be built and published.
## Publishing desktop tools
Desktop tools publish to the development repo on every push to master. To publish a release build, upload a new tag, and a release will automatically be built and published.
## Publishing VS Code
Before publishing, make sure to update the gradlerio version in `vscode-wpilib/resources/gradle/version.txt` Also make sure the gradle wrapper version matches the wrapper required by gradlerio.
Upon pushing a tag, a release will be built, and the files will be uploaded to the releases on GitHub. For publishing to the marketplace, you need a Microsoft account and to be added as a maintainer.
## Publishing GradleRIO
Before publishing, make sure to update the version in build.gradle. Publishing must happen locally, using the command `./gradlew publishPlugin`. This does require your API key for publishing to be set.
## Building the installer
Update the GradleRIO version in gradle.properties, and in the scripts folder in vscode, update the vscode extension. Then push, it will build the installer on azure.
## Publishing Third Party Dependencies
Currently the 3rd party deps are imgui, opencv, and google test
For publishing these dependencies, the version needs to be manually updated in the publish.gradle file of their respective repository.
Then, in the azure build for the dependency you want to build for, manually start a pipeline build (As of current, this is the `Run Pipeline` button).
A variable needs to be added called `RUN_AZURE_ARTIFACTORY_RELEASE`, with a value of `true`. Then when the pipeline gets started, the final build outputs will be updated to artifactory.
To use newer versions of C++ dependencies, in `shared/config.gradle`, update the version related to the specific dependency.
For Java dependencies, there is likely a file related to the specific dependency in the shared folder. Update the version in there.
Note, changing artifact locations (This includes changing the artifact year currently, I have an issue open to change this) requires updating the `native-utils` plugin
## Publishing allwpilib
allwpilib publishes to the development repo on every push to main. To publish a release build, upload a new tag, and a release will automatically be built and published.
## Publishing desktop tools
Desktop tools publish to the development repo on every push to main. To publish a release build, upload a new tag, and a release will automatically be built and published.
## Publishing VS Code
Before publishing, make sure to update the gradlerio version in `vscode-wpilib/resources/gradle/version.txt` Also make sure the gradle wrapper version matches the wrapper required by gradlerio.
Upon pushing a tag, a release will be built, and the files will be uploaded to the releases on GitHub. For publishing to the marketplace, you need a Microsoft account and to be added as a maintainer.
## Publishing GradleRIO
Before publishing, make sure to update the version in build.gradle. Publishing must happen locally, using the command `./gradlew publishPlugin`. This does require your API key for publishing to be set.
## Building the installer
Update the GradleRIO version in gradle.properties, and in the scripts folder in vscode, update the vscode extension. Then push, it will build the installer on azure.

View File

@@ -9,7 +9,7 @@ We provide two repositories. These repositories are:
* (Development) https://frcmaven.wpi.edu/artifactory/development/
The release repository is where official WPILib releases are pushed.
The development repository is where development releases of every commit to [master](https://github.com/wpilibsuite/allwpilib/tree/master) is pushed.
The development repository is where development releases of every commit to [main](https://github.com/wpilibsuite/allwpilib/tree/main) is pushed.
## Artifact classifiers
We provide two base types of artifacts.
@@ -69,15 +69,36 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* wpiutil
* wpigui
* imgui
* ntcore
* wpiutil
* wpimath
* wpiutil
* glass/libglass
* wpiutil
* wpimath
* wpigui
* glass/libglassnt
* wpiutil
* ntcore
* wpimath
* wpigui
* hal
* wpiutil
* halsim
* imgui
* wpiutil
* ntcore
* wpiutil
* ntcore
* wpimath
* wpigui
* libglass
* libglassnt
* cscore
* opencv
@@ -101,6 +122,7 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* cameraserver
* ntcore
* cscore
* wpimath
* wpiutil
* wpilibNewCommands
@@ -109,9 +131,10 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* cameraserver
* ntcore
* cscore
* wpimath
* wpiutil
* wpilibNewCommands
* wpilibOldCommands
* wpilibc
* hal
* cameraserver
@@ -119,6 +142,7 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* cscore
* wpiutil
### Third Party Artifacts
This repository provides the builds of the following third party software.
@@ -128,3 +152,4 @@ All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
* googletest
* imgui
* opencv
* libssh

View File

@@ -11,8 +11,10 @@ Development builds are the per-commit build hosted everytime a commit is pushed
In order to build a project using a development build, find the build.gradle file and open it. Then, add the following code below the plugin section and replace YEAR with the year of the development version.
```groovy
wpi.maven.useLocal = false
wpi.maven.useDevelopment = true
wpi.wpilibVersion = 'YEAR.+'
wpi.versions.wpilibVersion = 'YEAR.+'
wpi.versions.wpimathVersion = 'YEAR.+
```
The top of your ``build.gradle`` file should now look similar to the code below. Ignore any differences in versions.
@@ -21,11 +23,13 @@ Java
```groovy
plugins {
id "java"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
id "edu.wpi.first.GradleRIO" version "2022.1.1"
}
wpi.maven.useLocal = false
wpi.maven.useDevelopment = true
wpi.wpilibVersion = '2020.+'
wpi.versions.wpilibVersion = '2022.+'
wpi.versions.wpimathVersion = '2022.+'
```
C++
@@ -33,11 +37,13 @@ C++
plugins {
id "cpp"
id "google-test-test-suite"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
id "edu.wpi.first.GradleRIO" version "2022.1.1"
}
wpi.maven.useLocal = false
wpi.maven.useDevelopment = true
wpi.wpilibVersion = '2020.+'
wpi.versions.wpilibVersion = '2022.+'
wpi.versions.wpimathVersion = '2022.+'
```
## Local Build
@@ -48,11 +54,13 @@ Java
```groovy
plugins {
id "java"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
id "edu.wpi.first.GradleRIO" version "2022.1.1"
}
wpi.maven.useLocal = false
wpi.maven.useFrcMavenLocalDevelopment = true
wpi.wpilibVersion = 'YEAR.424242.+'
wpi.versions.wpilibVersion = 'YEAR.424242.+'
wpi.versions.wpimathVersion = 'YEAR.424242.+'
```
C++
@@ -60,9 +68,26 @@ C++
plugins {
id "cpp"
id "google-test-test-suite"
id "edu.wpi.first.GradleRIO" version "2020.3.2"
id "edu.wpi.first.GradleRIO" version "2022.1.1"
}
wpi.maven.useLocal = false
wpi.maven.useFrcMavenLocalDevelopment = true
wpi.wpilibVersion = 'YEAR.424242.+'
wpi.versions.wpilibVersion = 'YEAR.424242.+'
wpi.versions.wpimathVersion = 'YEAR.424242.+'
```
# roboRIO Development
This repo contains a myRobot project built in way to do full project development without needing to do a full publish into GradleRIO. These also only require building the minimum amount of binaries for the roboRIO, so the builds are much faster as well.
The setup only works if the roboRIO is USB connected. If an alternate IP address is preferred, the `address` block in myRobot\build.gradle can be changed to point to another address.
The following 3 tasks can be used for deployment:
* `:myRobot:deployShared` deploys the C++ project using shared dependencies. Prefer this one for most C++ development.
* `:myRobot:deployStatic` deploys the C++ project with all dependencies statically linked.
* `:myRobot:deployJava` deploys the Java project and all required dependencies. Also installs the JRE if not currently installed.
Deploying any of these to the roboRIO will disable the current startup project until it is redeployed.
From here, ssh into the roboRIO using the `admin` account (`lvuser` will fail to run in many cases). In the admin home directory, a file for each deploy type will exist (`myRobotCpp`, `myRobotCppStatic` and `myRobotJavaRun`). These can be run to start up the corresponding project.

View File

@@ -35,8 +35,10 @@ The following build options are available:
* This option will build C++ unit tests. These can be run via `make test`.
* `WITH_CSCORE` (ON Default)
* This option will cause cscore to be built. Turning this off will implicitly disable cameraserver, the hal and wpilib as well, irrespective of their specific options. If this is off, the OpenCV build requirement is removed.
* `WITH_WPIMATH` (ON Default)
* This option will build the wpimath library. This option must be on to build wpilib.
* `WITH_WPILIB` (ON Default)
* This option will build the hal, wpilibc/j, and wpimath during the build. The HAL is the simulator hal, unless the external hal options are used. The cmake build has no capability to build for the RoboRIO.
* This option will build the hal and wpilibc/j during the build. The HAL is the simulator hal, unless the external hal options are used. The cmake build has no capability to build for the RoboRIO.
* `WITH_SIMULATION_MODULES` (ON Default)
* This option will build simulation modules, including wpigui and the HALSim plugins.
* `WITH_EXTERNAL_HAL` (OFF Default)
@@ -48,7 +50,7 @@ The following build options are available:
## Build Setup
The WPILib CMake build does not allow in source builds. Because the `build` directory is used by Gradle, we recommend a `buildcmake` directory in the root. This folder is included in the gitignore.
The WPILib CMake build does not allow in source builds. Because the `build` directory is used by Gradle, we recommend a `build-cmake` directory in the root. This folder is included in the gitignore.
Once you have a build folder, run CMake configuration in that build directory with the following command.

View File

@@ -1,6 +1,8 @@
# WPILib Project
![CI](https://github.com/wpilibsuite/allwpilib/workflows/CI/badge.svg)
[![C++ Documentation](https://img.shields.io/badge/documentation-c%2B%2B-blue)](https://first.wpi.edu/wpilib/allwpilib/docs/development/cpp/)
[![Java Documentation](https://img.shields.io/badge/documentation-java-orange)](https://first.wpi.edu/wpilib/allwpilib/docs/development/java/)
Welcome to the WPILib project. This repository contains the HAL, WPILibJ, and WPILibC projects. These are the core libraries for creating robot programs for the roboRIO.
@@ -31,18 +33,25 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen
## Requirements
- [JDK 11](https://adoptopenjdk.net/)
- Note that the JRE is insufficient; the full JDK is required
- On Ubuntu, run `sudo apt install openjdk-11-jdk`
- On Windows, install the JDK 11 .msi from the link above
- On macOS, install the JDK 11 .pkg from the link above
- C++ compiler
- On Linux, install GCC
- On Windows, install [Visual Studio Community 2019](https://visualstudio.microsoft.com/vs/community/) and select the C++ programming language during installation (Gradle can't use the build tools for Visual Studio 2019)
- On Linux, install GCC 8 or greater
- On Windows, install [Visual Studio Community 2022 or 2019](https://visualstudio.microsoft.com/vs/community/) and select the C++ programming language during installation (Gradle can't use the build tools for Visual Studio)
- On macOS, install the Xcode command-line build tools via `xcode-select --install`
- [ARM compiler toolchain](https://github.com/wpilibsuite/roborio-toolchain/releases)
- For 2020 and beyond, use GCC version 7 or greater
- ARM compiler toolchain
- Run `./gradlew installRoboRioToolchain` after cloning this repository
- If the WPILib installer was used, this toolchain is already installed
- Raspberry Pi toolchain (optional)
- Run `./gradlew installRaspbianToolchain` after cloning this repository
## Setup
Clone the WPILib repository. If the toolchains are not installed, install them, and make sure they are available on the system PATH.
Clone the WPILib repository and follow the instructions above for installing any required tooling.
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/master/README.md) for wpiformat setup instructions.
See the [styleguide README](https://github.com/wpilibsuite/styleguide/blob/main/README.md) for wpiformat setup instructions.
## Building
@@ -62,6 +71,8 @@ The gradlew wrapper only exists in the root of the main project, so be sure to r
There are a few tasks other than `build` available. To see them, run the meta-task `tasks`. This will print a list of all available tasks, with a description of each task.
If opening from a fresh clone, generated java dependencies will not exist. Most IDEs will not run the generation tasks, which will cause lots of IDE errors. Manually run `./gradlew compileJava` from a terminal to run all the compile tasks, and then refresh your IDE's configuration (In VS Code open settings.gradle and save).
### Faster builds
`./gradlew build` builds _everything_, which includes debug and release builds for desktop and all installed cross compilers. Many developers don't need or want to build all of this. Therefore, common tasks have shortcuts to only build necessary components for common development and testing tasks.
@@ -86,10 +97,10 @@ If you have installed the FRC Toolchain to a directory other than the default, o
### Gazebo simulation
If you also want simulation to be built, add -PmakeSim. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of Gazebo should work, even on Windows if you build Gazebo from source. Correct means CMake needs to be able to find gazebo-config.cmake. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
If you also want to force building Gazebo simulation support, add -PforceGazebo. This requires gazebo_transport. We have tested on 14.04 and 15.05, but any correct install of Gazebo should work, even on Windows if you build Gazebo from source. Correct means CMake needs to be able to find gazebo-config.cmake. See [The Gazebo website](https://gazebosim.org/) for installation instructions.
```bash
./gradlew build -PmakeSim
./gradlew build -PforceGazebo
```
If you prefer to use CMake directly, the you can still do so.
@@ -111,7 +122,9 @@ wpiformat can be executed anywhere in the repository via `py -3 -m wpiformat` on
#### Java Code Quality Tools
The Java code quality tools (checkstyle, pmd, etc.) can be run with the `./gradlew javaFormat` task.
The Java code quality tools Checkstyle, PMD, and Spotless can be run via `./gradlew javaFormat`. SpotBugs can be run via the `spotbugsMain`, `spotbugsTest`, and `spotbugsDev` tasks. These tools will all be run automatically by the `build` task. To disable this behavior, pass the `-PskipJavaFormat` flag.
If you only want to run the Java autoformatter, run `./gradlew spotlessApply`.
### CMake
@@ -138,6 +151,8 @@ The integration test directories for C++ and Java contain test code that runs on
The hal directory contains more C++ code meant to run on the roboRIO. HAL is an acronym for "Hardware Abstraction Layer", and it interfaces with the NI Libraries. The NI Libraries contain the low-level code for controlling devices on your robot. The NI Libraries are found in the ni-libraries folder.
The upstream_utils directory contains scripts for updating copies of thirdparty code in the repository.
The [styleguide repository](https://github.com/wpilibsuite/styleguide) contains our style guides for C++ and Java code. Anything submitted to the WPILib project needs to follow the code style guides outlined in there. For details about the style, please see the contributors document [here](CONTRIBUTING.md#coding-guidelines).
# Contributing to WPILib

View File

@@ -27,10 +27,13 @@ JSON for Modern C++ wpiutil/src/main/native/include/wpi/json.h
libuv wpiutil/src/main/native/include/uv.h
wpiutil/src/main/native/include/uv/
wpiutil/src/main/native/libuv/
fmtlib wpiutil/src/main/native/fmtlib/
sigslot wpiutil/src/main/native/include/wpi/Signal.h
wpiutil/src/test/native/cpp/sigslot/
tcpsockets wpiutil/src/main/native/cpp/TCP{Stream,Connector,Acceptor}.cpp
wpiutil/src/main/native/include/wpi/TCP*.h
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-*
@@ -40,6 +43,9 @@ units wpimath/src/main/native/include/units/
Eigen wpimath/src/main/native/eigeninclude/
wpimath/src/main/native/include/unsupported/
StackWalker wpiutil/src/main/native/windows/StackWalker.*
TCB span wpiutil/src/main/native/include/wpi/span.h
wpiutil/src/test/native/cpp/span/
GHC filesystem wpiutil/src/main/native/include/wpi/ghc/
Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineParameterizer.java
wpilibj/src/main/java/edu/wpi/first/wpilibj/trajectory/TrajectoryParameterizer.java
wpilibc/src/main/native/include/spline/SplineParameterizer.h
@@ -231,6 +237,32 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
MPacks License
==============================================================================
The MIT License (MIT)
Copyright (c) 2015-2021 Nicholas Fraser and the MPack authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
==============================================================================
Bootstrap License
==============================================================================
@@ -845,3 +877,95 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=====================
Portable File Dialogs
=====================
Copyright © 2018—2020 Sam Hocevar <sam@hocevar.net>
This library is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What the **** You Want
to Public License, Version 2, as published by the WTFPL Task Force.
See http://www.wtfpl.net/ for more details.
======================
Boost Software License
======================
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
======
fmtlib
======
Copyright (c) 2012 - present, Victor Zverovich
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- Optional exception to the license ---
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into a machine-executable object form of such
source code, you may redistribute such embedded portions in such object form
without including the above copyright and permission notices.
==============
GHC filesystem
==============
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -4,88 +4,88 @@ trigger:
batch: true
branches:
include:
- master
- master
stages:
- stage: Build
jobs:
- job: IntegrationTests
displayName: Integration Tests
pool:
vmImage: 'Ubuntu 16.04'
- stage: Build
jobs:
- job: IntegrationTests
displayName: Integration Tests
pool:
vmImage: 'ubuntu-latest'
container:
image: wpilib/roborio-cross-ubuntu:2021-18.04
container:
image: wpilib/roborio-cross-ubuntu:2022-18.04
timeoutInMinutes: 0
timeoutInMinutes: 0
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'copyWpilibJIntegrationTestJarToOutput copyWpilibCTestLibrariesToOutput'
options: '-Ponlylinuxathena -PbuildServer'
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ""
gradleWrapperFile: "gradlew"
gradleOptions: "-Xmx3072m"
publishJUnitResults: false
testResultsFiles: "**/TEST-*.xml"
tasks: "copyWpilibJIntegrationTestJarToOutput copyWpilibCTestLibrariesToOutput"
options: "-Ponlylinuxathena -PbuildServer -PskipJavaFormat"
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Integration Tests'
targetPath: 'build/integrationTestFiles'
- task: PublishPipelineArtifact@0
inputs:
artifactName: "Integration Tests"
targetPath: "build/integrationTestFiles"
- stage: TestBench
displayName: Test Bench
jobs:
- job: Cpp
displayName: C++
pool: RoboRioConnections
timeoutInMinutes: 30
workspace:
clean: all
steps:
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Integration Tests'
targetPath: 'build/integrationTestFiles'
- stage: TestBench
displayName: Test Bench
jobs:
- job: Cpp
displayName: C++
pool: RoboRioConnections
timeoutInMinutes: 30
workspace:
clean: all
steps:
- task: DownloadPipelineArtifact@0
inputs:
artifactName: "Integration Tests"
targetPath: "build/integrationTestFiles"
- task: ShellScript@2
displayName: Run C++ Tests
inputs:
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
args: 'cpp -A "--gtest_output=xml:/home/admin/testResults/cppreport.xml"'
- task: ShellScript@2
displayName: Run C++ Tests
inputs:
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
args: 'cpp -A "--gtest_output=xml:/home/admin/testResults/cppreport.xml"'
- task: PublishTestResults@2
displayName: Publish C++ Test Results
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '*.xml'
testRunTitle: 'C++ Test Report'
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'
- task: PublishTestResults@2
displayName: Publish C++ Test Results
inputs:
testResultsFormat: "JUnit"
testResultsFiles: "*.xml"
testRunTitle: "C++ Test Report"
searchFolder: "$(System.DefaultWorkingDirectory)/test-reports"
- job: Java
pool: RoboRioConnections
timeoutInMinutes: 30
workspace:
clean: all
steps:
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Integration Tests'
targetPath: 'build/integrationTestFiles'
- job: Java
pool: RoboRioConnections
timeoutInMinutes: 30
workspace:
clean: all
steps:
- task: DownloadPipelineArtifact@0
inputs:
artifactName: "Integration Tests"
targetPath: "build/integrationTestFiles"
- task: ShellScript@2
displayName: Run Java Tests
inputs:
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
args: 'java'
- task: ShellScript@2
displayName: Run Java Tests
inputs:
scriptPath: test-scripts/deploy-and-run-test-on-robot.sh
args: "java"
- task: PublishTestResults@2
displayName: Publish Java Test Results
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '*.xml'
testRunTitle: 'Java Test Report'
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'
- task: PublishTestResults@2
displayName: Publish Java Test Results
inputs:
testResultsFormat: "JUnit"
testResultsFiles: "*.xml"
testRunTitle: "Java Test Report"
searchFolder: "$(System.DefaultWorkingDirectory)/test-reports"

View File

@@ -1,27 +1,31 @@
import edu.wpi.first.toolchain.*
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.hubspot.jinjava:jinjava:2.6.0'
}
}
plugins {
id 'base'
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.0.2'
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.1.0'
id 'edu.wpi.first.wpilib.repositories.WPILibRepositoriesPlugin' version '2020.2'
id 'edu.wpi.first.NativeUtils' apply false
id 'edu.wpi.first.GradleJni' version '0.10.1'
id 'edu.wpi.first.GradleVsCode' version '0.11.0'
id 'edu.wpi.first.GradleJni' version '1.0.0'
id 'edu.wpi.first.GradleVsCode'
id 'idea'
id 'visual-studio'
id 'net.ltgt.errorprone' version '1.1.1' apply false
id 'com.github.johnrengelman.shadow' version '5.2.0' apply false
id 'net.ltgt.errorprone' version '2.0.2' apply false
id 'com.github.johnrengelman.shadow' version '7.1.2' apply false
id 'com.diffplug.spotless' version '6.1.2' apply false
id 'com.github.spotbugs' version '5.0.4' apply false
}
if (project.hasProperty('buildServer')) {
wpilibVersioning.buildServerMode = true
wpilibVersioning.useAllTags = true
}
if (project.hasProperty('releaseMode')) {
wpilibVersioning.releaseMode = true
wpilibVersioning.useAllTags = true
}
wpilibVersioning.buildServerMode = project.hasProperty('buildServer')
wpilibVersioning.releaseMode = project.hasProperty('releaseMode')
allprojects {
repositories {
@@ -106,6 +110,13 @@ subprojects {
}
}
// Enables UTF-8 support in Javadoc
tasks.withType(Javadoc) {
options.addStringOption("charset", "utf-8")
options.addStringOption("docencoding", "utf-8")
options.addStringOption("encoding", "utf-8")
}
// Sign outputs with Developer ID
if (project.hasProperty("developerID")) {
tasks.withType(AbstractLinkTask) { task ->
@@ -117,8 +128,12 @@ subprojects {
String path = task.getLinkedFile().getAsFile().get().getAbsolutePath()
exec {
workingDir rootDir
def args = ["sh", "-c", "codesign --force --strict --timestamp --options=runtime " +
"--verbose -s ${project.findProperty("developerID")} ${path}"]
def args = [
"sh",
"-c",
"codesign --force --strict --timestamp --options=runtime " +
"--verbose -s ${project.findProperty("developerID")} ${path}"
]
commandLine args
}
}
@@ -132,5 +147,5 @@ ext.getCurrentArch = {
}
wrapper {
gradleVersion = '6.0.1'
gradleVersion = '7.3.3'
}

View File

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

View File

@@ -1,48 +0,0 @@
import groovy.transform.CompileStatic
import javax.inject.Inject
import jaci.gradle.deploy.artifact.MavenArtifact
import jaci.gradle.deploy.context.DeployContext
import org.gradle.api.Project
import jaci.gradle.ActionWrapper
import java.util.function.Function
@CompileStatic
class JREArtifact extends MavenArtifact {
Function<DeployContext, Boolean> buildRequiresJre = (Function<DeployContext, Boolean>){ true }
void setJreDependency(String dep) {
dependency = project.dependencies.add(configuration(), dep)
}
@Inject
JREArtifact(String name, Project project) {
super(name, project)
configuration = project.configurations.create(configuration())
onlyIf = { DeployContext ctx ->
(buildRequiresJre.apply(ctx) && jreMissing(ctx)) || project.hasProperty("force-redeploy-jre")
}
predeploy << new ActionWrapper({ DeployContext ctx ->
ctx.logger.log('Deploying RoboRIO JRE (this will take a while)...')
})
directory = '/tmp'
filename = 'frcjre.ipk'
postdeploy << new ActionWrapper({ DeployContext ctx ->
ctx.logger.log('Installing JRE...')
ctx.execute('opkg remove frc2020-openjdk*; opkg install /tmp/frcjre.ipk; rm /tmp/frcjre.ipk')
ctx.logger.log('JRE Deployed!')
})
}
String configuration() {
return name + 'frcjre'
}
boolean jreMissing(DeployContext ctx) {
return ctx.execute('if [[ -f "/usr/local/frc/JRE/bin/java" ]]; then echo OK; else echo MISSING; fi').result.contains("MISSING")
}
}

View File

@@ -6,6 +6,8 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import org.gradle.api.tasks.Delete
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
@@ -44,7 +46,7 @@ import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import edu.wpi.first.nativeutils.tasks.ExportsGenerationTask
import edu.wpi.first.nativeutils.exports.ExportsGenerationTask
@CompileStatic
class SingleNativeBuild implements Plugin<Project> {
@@ -87,6 +89,14 @@ class SingleNativeBuild implements Plugin<Project> {
subs << component
}
}
Delete deleteObjects = null
if (project.hasProperty('buildServer')) {
deleteObjects = project.tasks.create('deleteObjects', Delete)
project.tasks.named('build').configure { Task t ->
t.dependsOn deleteObjects
return
}
}
subs.each {
((NativeLibrarySpec) it).binaries.each { oBinary ->
if (oBinary.buildable == false) {
@@ -136,6 +146,10 @@ class SingleNativeBuild implements Plugin<Project> {
tree.include '**/*.o'
tree.include '**/*.obj'
link.source tree
if (project.hasProperty('buildServer')) {
deleteObjects.dependsOn link
deleteObjects.delete tree
}
} else if (binary instanceof StaticLibraryBinarySpec) {
def sBinary = (StaticLibraryBinarySpec) binary
ObjectFilesToBinary assemble = (ObjectFilesToBinary) sBinary.tasks.createStaticLib
@@ -145,6 +159,10 @@ class SingleNativeBuild implements Plugin<Project> {
tree.include '**/*.o'
tree.include '**/*.obj'
assemble.source tree
if (project.hasProperty('buildServer')) {
deleteObjects.dependsOn assemble
deleteObjects.delete tree
}
}
}
}

View File

@@ -0,0 +1,48 @@
import groovy.transform.CompileStatic
import javax.inject.Inject
import edu.wpi.first.deployutils.deploy.artifact.MavenArtifact
import edu.wpi.first.deployutils.deploy.context.DeployContext
import org.gradle.api.Project
import edu.wpi.first.deployutils.ActionWrapper
import edu.wpi.first.deployutils.deploy.target.RemoteTarget
import edu.wpi.first.deployutils.PredicateWrapper
import java.util.function.Function
@CompileStatic
public class WPIJREArtifact extends MavenArtifact {
private final String configName;
public String getConfigName() {
return configName;
}
@Inject
public WPIJREArtifact(String name, RemoteTarget target) {
super(name, target);
String configName = name + "frcjre";
this.configName = configName;
Project project = target.getProject();
getConfiguration().set(project.getConfigurations().create(configName));
getDependency().set(project.getDependencies().add(configName, "edu.wpi.first.jdk:roborio-2022:11.0.12u5-1"));
setOnlyIf(new PredicateWrapper({ DeployContext ctx ->
return jreMissing(ctx) || project.hasProperty("force-redeploy-jre");
}));
getDirectory().set("/tmp");
getFilename().set("frcjre.ipk");
getPostdeploy().add(new ActionWrapper({ DeployContext ctx ->
ctx.getLogger().log("Installing JRE...");
ctx.execute("opkg remove frc2022-openjdk*; opkg install /tmp/frcjre.ipk; rm /tmp/frcjre.ipk");
ctx.getLogger().log("JRE Deployed!");
}));
}
private boolean jreMissing(DeployContext ctx) {
return ctx.execute("if [[ -f \"/usr/local/frc/JRE/bin/java\" ]]; then echo OK; else echo MISSING; fi").getResult().contains("MISSING");
}
}

View File

@@ -12,6 +12,7 @@ repoRootNameOverride {
}
includeOtherLibs {
^fmt/
^hal/
^networktables/
^opencv2/

View File

@@ -9,7 +9,7 @@ find_package( OpenCV REQUIRED )
if (WITH_JAVA)
find_package(Java REQUIRED)
include(UseJava)
set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
#find java files, copy them locally
@@ -53,8 +53,8 @@ else()
set (cameraserver_config_dir share/cameraserver)
endif()
configure_file(cameraserver-config.cmake.in ${CMAKE_BINARY_DIR}/cameraserver-config.cmake )
install(FILES ${CMAKE_BINARY_DIR}/cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
configure_file(cameraserver-config.cmake.in ${WPILIB_BINARY_DIR}/cameraserver-config.cmake )
install(FILES ${WPILIB_BINARY_DIR}/cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
install(EXPORT cameraserver DESTINATION ${cameraserver_config_dir})
file(GLOB multiCameraServer_src multiCameraServer/src/main/native/cpp/*.cpp)

View File

@@ -20,9 +20,9 @@ dependencies {
ext {
sharedCvConfigs = [cameraserver : [],
cameraserverBase: [],
cameraserverDev : [],
cameraserverTest: []]
cameraserverBase: [],
cameraserverDev : [],
cameraserverTest: []]
staticCvConfigs = [:]
useJava = true
useCpp = true
@@ -32,14 +32,32 @@ apply from: "${rootDir}/shared/opencv.gradle"
nativeUtils.exportsConfigs {
cameraserver {
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
x86ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
x64ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
}
}

View File

@@ -27,7 +27,7 @@ repositories {
}
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.google.code.gson:gson:2.8.9'
implementation project(':wpiutil')
implementation project(':ntcore')
@@ -52,10 +52,10 @@ model {
}
}
binaries.all { binary ->
lib project: ':cameraserver', library: 'cameraserver', linkage: 'static'
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
lib project: ':cscore', library: 'cscore', linkage: 'static'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
lib project: ':cameraserver', library: 'cameraserver', linkage: 'static'
lib project: ':ntcore', library: 'ntcore', linkage: 'static'
lib project: ':cscore', library: 'cscore', linkage: 'static'
lib project: ':wpiutil', library: 'wpiutil', linkage: 'static'
}
}
}

View File

@@ -1,55 +1,50 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.cameraserver.CameraServer;
import edu.wpi.first.cscore.VideoSource;
import edu.wpi.first.networktables.NetworkTableInstance;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
/*
JSON format:
{
"team": <team number>,
"ntmode": <"client" or "server", "client" if unspecified>
"cameras": [
{
"name": <camera name>
"path": <path, e.g. "/dev/video0">
"pixel format": <"MJPEG", "YUYV", etc> // optional
"width": <video mode width> // optional
"height": <video mode height> // optional
"fps": <video mode fps> // optional
"brightness": <percentage brightness> // optional
"white balance": <"auto", "hold", value> // optional
"exposure": <"auto", "hold", value> // optional
"properties": [ // optional
{
"name": <property name>
"value": <property value>
}
]
}
]
}
*/
JSON format:
{
"team": <team number>,
"ntmode": <"client" or "server", "client" if unspecified>
"cameras": [
{
"name": <camera name>
"path": <path, e.g. "/dev/video0">
"pixel format": <"MJPEG", "YUYV", etc> // optional
"width": <video mode width> // optional
"height": <video mode height> // optional
"fps": <video mode fps> // optional
"brightness": <percentage brightness> // optional
"white balance": <"auto", "hold", value> // optional
"exposure": <"auto", "hold", value> // optional
"properties": [ // optional
{
"name": <property name>
"value": <property value>
}
]
}
]
}
*/
public final class Main {
private static String configFile = "/boot/frc.json";
@@ -61,23 +56,18 @@ public final class Main {
public JsonObject config;
}
public static int team;
public static boolean server;
public static List<CameraConfig> cameras = new ArrayList<>();
private static int team;
private static boolean server;
private static List<CameraConfig> cameras = new ArrayList<>();
private Main() {
}
private Main() {}
/**
* Report parse error.
*/
/** Report parse error. */
public static void parseError(String str) {
System.err.println("config error in '" + configFile + "': " + str);
}
/**
* Read single camera configuration.
*/
/** Read single camera configuration. */
public static boolean readCameraConfig(JsonObject config) {
CameraConfig cam = new CameraConfig();
@@ -103,10 +93,7 @@ public final class Main {
return true;
}
/**
* Read configuration file.
*/
@SuppressWarnings("PMD.CyclomaticComplexity")
/** Read configuration file. */
public static boolean readConfig() {
// parse file
JsonElement top;
@@ -160,22 +147,17 @@ public final class Main {
return true;
}
/**
* Start running the camera.
*/
/** Start running the camera. */
public static void startCamera(CameraConfig config) {
System.out.println("Starting camera '" + config.name + "' on " + config.path);
VideoSource camera = CameraServer.getInstance().startAutomaticCapture(
config.name, config.path);
VideoSource camera = CameraServer.startAutomaticCapture(config.name, config.path);
Gson gson = new GsonBuilder().create();
camera.setConfigJson(gson.toJson(config.config));
}
/**
* Main.
*/
/** Main. */
public static void main(String... args) {
if (args.length > 0) {
configFile = args[0];
@@ -202,7 +184,7 @@ public final class Main {
}
// loop forever
for (;;) {
for (; ; ) {
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {

View File

@@ -1,16 +1,15 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <string>
#include <string_view>
#include <vector>
#include <networktables/NetworkTableInstance.h>
#include <wpi/StringRef.h>
#include <wpi/StringExtras.h>
#include <wpi/fmt/raw_ostream.h>
#include <wpi/json.h>
#include <wpi/raw_istream.h>
#include <wpi/raw_ostream.h>
@@ -108,7 +107,7 @@ bool ReadConfig() {
try {
j = wpi::json::parse(is);
} catch (const wpi::json::parse_error& e) {
ParseError() << "byte " << e.byte << ": " << e.what() << '\n';
fmt::print(ParseError(), "byte {}: {}\n", e.byte, e.what());
return false;
}
@@ -130,10 +129,9 @@ bool ReadConfig() {
if (j.count("ntmode") != 0) {
try {
auto str = j.at("ntmode").get<std::string>();
wpi::StringRef s(str);
if (s.equals_lower("client")) {
if (wpi::equals_lower(str, "client")) {
server = false;
} else if (s.equals_lower("server")) {
} else if (wpi::equals_lower(str, "server")) {
server = true;
} else {
ParseError() << "could not understand ntmode value '" << str << "'\n";
@@ -146,7 +144,9 @@ bool ReadConfig() {
// cameras
try {
for (auto&& camera : j.at("cameras")) {
if (!ReadCameraConfig(camera)) return false;
if (!ReadCameraConfig(camera)) {
return false;
}
}
} catch (const wpi::json::exception& e) {
ParseError() << "could not read cameras: " << e.what() << '\n';
@@ -157,34 +157,41 @@ bool ReadConfig() {
}
void StartCamera(const CameraConfig& config) {
wpi::outs() << "Starting camera '" << config.name << "' on " << config.path
<< '\n';
auto camera = frc::CameraServer::GetInstance()->StartAutomaticCapture(
config.name, config.path);
fmt::print("Starting camera '{}' on {}\n", config.name, config.path);
auto camera =
frc::CameraServer::StartAutomaticCapture(config.name, config.path);
camera.SetConfigJson(config.config);
}
} // namespace
int main(int argc, char* argv[]) {
if (argc >= 2) configFile = argv[1];
if (argc >= 2) {
configFile = argv[1];
}
// read configuration
if (!ReadConfig()) return EXIT_FAILURE;
if (!ReadConfig()) {
return EXIT_FAILURE;
}
// start NetworkTables
auto ntinst = nt::NetworkTableInstance::GetDefault();
if (server) {
wpi::outs() << "Setting up NetworkTables server\n";
std::puts("Setting up NetworkTables server");
ntinst.StartServer();
} else {
wpi::outs() << "Setting up NetworkTables client for team " << team << '\n';
fmt::print("Setting up NetworkTables client for team {}\n", team);
ntinst.StartClientTeam(team);
}
// start cameras
for (auto&& camera : cameras) StartCamera(camera);
for (auto&& camera : cameras) {
StartCamera(camera);
}
// loop forever
for (;;) std::this_thread::sleep_for(std::chrono::seconds(10));
for (;;) {
std::this_thread::sleep_for(std::chrono::seconds(10));
}
}

View File

@@ -1,17 +1,11 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.cameraserver;
public final class DevMain {
public static void main(String[] args) {
public static void main(String[] args) {}
}
private DevMain() {
}
private DevMain() {}
}

View File

@@ -1,8 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
int main() {}

View File

@@ -1,12 +1,27 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.cameraserver;
import edu.wpi.first.cscore.AxisCamera;
import edu.wpi.first.cscore.CameraServerJNI;
import edu.wpi.first.cscore.CvSink;
import edu.wpi.first.cscore.CvSource;
import edu.wpi.first.cscore.MjpegServer;
import edu.wpi.first.cscore.UsbCamera;
import edu.wpi.first.cscore.VideoEvent;
import edu.wpi.first.cscore.VideoException;
import edu.wpi.first.cscore.VideoListener;
import edu.wpi.first.cscore.VideoMode;
import edu.wpi.first.cscore.VideoMode.PixelFormat;
import edu.wpi.first.cscore.VideoProperty;
import edu.wpi.first.cscore.VideoSink;
import edu.wpi.first.cscore.VideoSource;
import edu.wpi.first.networktables.EntryListenerFlags;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -14,45 +29,28 @@ import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import edu.wpi.cscore.AxisCamera;
import edu.wpi.cscore.CameraServerJNI;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.CvSource;
import edu.wpi.cscore.MjpegServer;
import edu.wpi.cscore.UsbCamera;
import edu.wpi.cscore.VideoEvent;
import edu.wpi.cscore.VideoException;
import edu.wpi.cscore.VideoListener;
import edu.wpi.cscore.VideoMode;
import edu.wpi.cscore.VideoMode.PixelFormat;
import edu.wpi.cscore.VideoProperty;
import edu.wpi.cscore.VideoSink;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.networktables.EntryListenerFlags;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
/**
* Singleton class for creating and keeping camera servers.
* Also publishes camera information to NetworkTables.
* Singleton class for creating and keeping camera servers. Also publishes camera information to
* NetworkTables.
*/
@SuppressWarnings("PMD.UnusedPrivateField")
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;
@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();
@@ -60,32 +58,226 @@ public final class CameraServer {
return server;
}
private final AtomicInteger m_defaultUsbDevice;
private String m_primarySourceName;
private final Map<String, VideoSource> m_sources;
private final Map<String, VideoSink> m_sinks;
private final Map<Integer, NetworkTable> m_tables; // indexed by source handle
private static final AtomicInteger m_defaultUsbDevice = new AtomicInteger();
private static String m_primarySourceName;
private static final Map<String, VideoSource> m_sources = new HashMap<>();
private static final Map<String, VideoSink> m_sinks = new HashMap<>();
private static final Map<Integer, NetworkTable> m_tables =
new HashMap<>(); // indexed by source handle
// source handle indexed by sink handle
private final Map<Integer, Integer> m_fixedSources;
private final NetworkTable m_publishTable;
private final VideoListener m_videoListener; //NOPMD
private final int m_tableListener; //NOPMD
private int m_nextPort;
private String[] m_addresses;
private static final Map<Integer, Integer> m_fixedSources = new HashMap<>();
private static final NetworkTable m_publishTable =
NetworkTableInstance.getDefault().getTable(kPublishName);
@SuppressWarnings("JavadocMethod")
// We publish sources to NetworkTables using the following structure:
// "/CameraPublisher/{Source.Name}/" - root
// - "source" (string): Descriptive, prefixed with type (e.g. "usb:0")
// - "streams" (string array): URLs that can be used to stream data
// - "description" (string): Description of the source
// - "connected" (boolean): Whether source is connected
// - "mode" (string): Current video mode
// - "modes" (string array): Available video modes
// - "Property/{Property}" - Property values
// - "PropertyInfo/{Property}" - Property supporting information
// Listener for video events
private static final VideoListener m_videoListener =
new VideoListener(
event -> {
switch (event.kind) {
case kSourceCreated:
{
// Create subtable for the camera
NetworkTable table = m_publishTable.getSubTable(event.name);
m_tables.put(event.sourceHandle, table);
table.getEntry("source").setString(makeSourceValue(event.sourceHandle));
table
.getEntry("description")
.setString(CameraServerJNI.getSourceDescription(event.sourceHandle));
table
.getEntry("connected")
.setBoolean(CameraServerJNI.isSourceConnected(event.sourceHandle));
table
.getEntry("streams")
.setStringArray(getSourceStreamValues(event.sourceHandle));
try {
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
table.getEntry("mode").setDefaultString(videoModeToString(mode));
table.getEntry("modes").setStringArray(getSourceModeValues(event.sourceHandle));
} catch (VideoException ignored) {
// Do nothing. Let the other event handlers update this if there is an error.
}
break;
}
case kSourceDestroyed:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("source").setString("");
table.getEntry("streams").setStringArray(new String[0]);
table.getEntry("modes").setStringArray(new String[0]);
}
break;
}
case kSourceConnected:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
// update the description too (as it may have changed)
table
.getEntry("description")
.setString(CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(true);
}
break;
}
case kSourceDisconnected:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("connected").setBoolean(false);
}
break;
}
case kSourceVideoModesUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("modes").setStringArray(getSourceModeValues(event.sourceHandle));
}
break;
}
case kSourceVideoModeChanged:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("mode").setString(videoModeToString(event.mode));
}
break;
}
case kSourcePropertyCreated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, true);
}
break;
}
case kSourcePropertyValueUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, false);
}
break;
}
case kSourcePropertyChoicesUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
try {
String[] choices =
CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
table
.getEntry("PropertyInfo/" + event.name + "/choices")
.setStringArray(choices);
} catch (VideoException ignored) {
// ignore
}
}
break;
}
case kSinkSourceChanged:
case kSinkCreated:
case kSinkDestroyed:
case kNetworkInterfacesChanged:
{
m_addresses = CameraServerJNI.getNetworkInterfaces();
updateStreamValues();
break;
}
default:
break;
}
},
0x4fff,
true);
private static final int m_tableListener =
NetworkTableInstance.getDefault()
.addEntryListener(
kPublishName + "/",
event -> {
String relativeKey = event.name.substring(kPublishName.length() + 1);
// get source (sourceName/...)
int subKeyIndex = relativeKey.indexOf('/');
if (subKeyIndex == -1) {
return;
}
String sourceName = relativeKey.substring(0, subKeyIndex);
VideoSource source = m_sources.get(sourceName);
if (source == null) {
return;
}
// get subkey
relativeKey = relativeKey.substring(subKeyIndex + 1);
// handle standard names
String propName;
if ("mode".equals(relativeKey)) {
// reset to current mode
event.getEntry().setString(videoModeToString(source.getVideoMode()));
return;
} else if (relativeKey.startsWith("Property/")) {
propName = relativeKey.substring(9);
} else if (relativeKey.startsWith("RawProperty/")) {
propName = relativeKey.substring(12);
} else {
return; // ignore
}
// everything else is a property
VideoProperty property = source.getProperty(propName);
switch (property.getKind()) {
case kNone:
return;
case kBoolean:
// reset to current setting
event.getEntry().setBoolean(property.get() != 0);
return;
case kInteger:
case kEnum:
// reset to current setting
event.getEntry().setDouble(property.get());
return;
case kString:
// reset to current setting
event.getEntry().setString(property.getString());
return;
default:
return;
}
},
EntryListenerFlags.kImmediate | EntryListenerFlags.kUpdate);
private static int m_nextPort = kBasePort;
private static String[] m_addresses = new String[0];
@SuppressWarnings("MissingJavadocMethod")
private static String makeSourceValue(int source) {
switch (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))) {
case kUsb:
return "usb:" + CameraServerJNI.getUsbCameraPath(source);
case kHttp: {
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
if (urls.length > 0) {
return "ip:" + urls[0];
} else {
return "ip:";
case kHttp:
{
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
if (urls.length > 0) {
return "ip:" + urls[0];
} else {
return "ip:";
}
}
}
case kCv:
return "cv:";
default:
@@ -93,13 +285,13 @@ public final class CameraServer {
}
}
@SuppressWarnings("JavadocMethod")
@SuppressWarnings("MissingJavadocMethod")
private static String makeStreamValue(String address, int port) {
return "mjpg:http://" + address + ":" + port + "/?action=stream";
}
@SuppressWarnings({"JavadocMethod", "PMD.AvoidUsingHardCodedIP"})
private synchronized String[] getSinkStreamValues(int sink) {
@SuppressWarnings("MissingJavadocMethod")
private static synchronized String[] getSinkStreamValues(int sink) {
// Ignore all but MjpegServer
if (VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink)) != VideoSink.Kind.kMjpeg) {
return new String[0];
@@ -119,7 +311,7 @@ public final class CameraServer {
values.add(makeStreamValue(CameraServerJNI.getHostname() + ".local", port));
for (String addr : m_addresses) {
if ("127.0.0.1".equals(addr)) {
continue; // ignore localhost
continue; // ignore localhost
}
values.add(makeStreamValue(addr, port));
}
@@ -128,11 +320,11 @@ public final class CameraServer {
return values.toArray(new String[0]);
}
@SuppressWarnings({"JavadocMethod", "PMD.AvoidUsingHardCodedIP"})
private synchronized String[] getSourceStreamValues(int source) {
@SuppressWarnings("MissingJavadocMethod")
private static synchronized String[] getSourceStreamValues(int source) {
// Ignore all but HttpCamera
if (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))
!= VideoSource.Kind.kHttp) {
!= VideoSource.Kind.kHttp) {
return new String[0];
}
@@ -150,7 +342,7 @@ public final class CameraServer {
int sinkSource = CameraServerJNI.getSinkSource(sink);
if (source == sinkSource
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink))
== VideoSink.Kind.kMjpeg) {
== VideoSink.Kind.kMjpeg) {
// Add USB-only passthrough
String[] finalValues = Arrays.copyOf(values, values.length + 1);
int port = CameraServerJNI.getMjpegServerPort(sink);
@@ -163,15 +355,16 @@ public final class CameraServer {
return values;
}
@SuppressWarnings({"JavadocMethod", "PMD.AvoidUsingHardCodedIP", "PMD.CyclomaticComplexity"})
private synchronized void updateStreamValues() {
@SuppressWarnings("MissingJavadocMethod")
private static synchronized void updateStreamValues() {
// Over all the sinks...
for (VideoSink i : m_sinks.values()) {
int sink = i.getHandle();
// Get the source's subtable (if none exists, we're done)
int source = Objects.requireNonNullElseGet(m_fixedSources.get(sink),
() -> CameraServerJNI.getSinkSource(sink));
int source =
Objects.requireNonNullElseGet(
m_fixedSources.get(sink), () -> CameraServerJNI.getSinkSource(sink));
if (source == 0) {
continue;
@@ -208,7 +401,7 @@ public final class CameraServer {
}
}
@SuppressWarnings("JavadocMethod")
@SuppressWarnings("MissingJavadocMethod")
private static String pixelFormatToString(PixelFormat pixelFormat) {
switch (pixelFormat) {
case kMJPEG:
@@ -228,13 +421,19 @@ public final class CameraServer {
/// Provide string description of video mode.
/// The returned string is "{width}x{height} {format} {fps} fps".
@SuppressWarnings("JavadocMethod")
@SuppressWarnings("MissingJavadocMethod")
private static String videoModeToString(VideoMode mode) {
return mode.width + "x" + mode.height + " " + pixelFormatToString(mode.pixelFormat)
+ " " + mode.fps + " fps";
return mode.width
+ "x"
+ mode.height
+ " "
+ pixelFormatToString(mode.pixelFormat)
+ " "
+ mode.fps
+ " fps";
}
@SuppressWarnings("JavadocMethod")
@SuppressWarnings("MissingJavadocMethod")
private static String[] getSourceModeValues(int sourceHandle) {
VideoMode[] modes = CameraServerJNI.enumerateSourceVideoModes(sourceHandle);
String[] modeStrings = new String[modes.length];
@@ -244,7 +443,7 @@ public final class CameraServer {
return modeStrings;
}
@SuppressWarnings({"JavadocMethod", "PMD.CyclomaticComplexity"})
@SuppressWarnings("MissingJavadocMethod")
private static void putSourcePropertyValue(NetworkTable table, VideoEvent event, boolean isNew) {
String name;
String infoName;
@@ -270,14 +469,18 @@ public final class CameraServer {
case kEnum:
if (isNew) {
entry.setDefaultDouble(event.value);
table.getEntry(infoName + "/min").setDouble(
CameraServerJNI.getPropertyMin(event.propertyHandle));
table.getEntry(infoName + "/max").setDouble(
CameraServerJNI.getPropertyMax(event.propertyHandle));
table.getEntry(infoName + "/step").setDouble(
CameraServerJNI.getPropertyStep(event.propertyHandle));
table.getEntry(infoName + "/default").setDouble(
CameraServerJNI.getPropertyDefault(event.propertyHandle));
table
.getEntry(infoName + "/min")
.setDouble(CameraServerJNI.getPropertyMin(event.propertyHandle));
table
.getEntry(infoName + "/max")
.setDouble(CameraServerJNI.getPropertyMax(event.propertyHandle));
table
.getEntry(infoName + "/step")
.setDouble(CameraServerJNI.getPropertyStep(event.propertyHandle));
table
.getEntry(infoName + "/default")
.setDouble(CameraServerJNI.getPropertyDefault(event.propertyHandle));
} else {
entry.setDouble(event.value);
}
@@ -297,203 +500,21 @@ public final class CameraServer {
}
}
@SuppressWarnings({"JavadocMethod", "PMD.UnusedLocalVariable", "PMD.ExcessiveMethodLength",
"PMD.NPathComplexity"})
private CameraServer() {
m_defaultUsbDevice = new AtomicInteger();
m_sources = new HashMap<>();
m_sinks = new HashMap<>();
m_fixedSources = new HashMap<>();
m_tables = new HashMap<>();
m_publishTable = NetworkTableInstance.getDefault().getTable(kPublishName);
m_nextPort = kBasePort;
m_addresses = new String[0];
// We publish sources to NetworkTables using the following structure:
// "/CameraPublisher/{Source.Name}/" - root
// - "source" (string): Descriptive, prefixed with type (e.g. "usb:0")
// - "streams" (string array): URLs that can be used to stream data
// - "description" (string): Description of the source
// - "connected" (boolean): Whether source is connected
// - "mode" (string): Current video mode
// - "modes" (string array): Available video modes
// - "Property/{Property}" - Property values
// - "PropertyInfo/{Property}" - Property supporting information
// Listener for video events
m_videoListener = new VideoListener(event -> {
switch (event.kind) {
case kSourceCreated: {
// Create subtable for the camera
NetworkTable table = m_publishTable.getSubTable(event.name);
m_tables.put(event.sourceHandle, table);
table.getEntry("source").setString(makeSourceValue(event.sourceHandle));
table.getEntry("description").setString(
CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(
CameraServerJNI.isSourceConnected(event.sourceHandle));
table.getEntry("streams").setStringArray(getSourceStreamValues(event.sourceHandle));
try {
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
table.getEntry("mode").setDefaultString(videoModeToString(mode));
table.getEntry("modes").setStringArray(getSourceModeValues(event.sourceHandle));
} catch (VideoException ignored) {
// Do nothing. Let the other event handlers update this if there is an error.
}
break;
}
case kSourceDestroyed: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("source").setString("");
table.getEntry("streams").setStringArray(new String[0]);
table.getEntry("modes").setStringArray(new String[0]);
}
break;
}
case kSourceConnected: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
// update the description too (as it may have changed)
table.getEntry("description").setString(
CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(true);
}
break;
}
case kSourceDisconnected: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("connected").setBoolean(false);
}
break;
}
case kSourceVideoModesUpdated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("modes").setStringArray(getSourceModeValues(event.sourceHandle));
}
break;
}
case kSourceVideoModeChanged: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("mode").setString(videoModeToString(event.mode));
}
break;
}
case kSourcePropertyCreated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, true);
}
break;
}
case kSourcePropertyValueUpdated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, false);
}
break;
}
case kSourcePropertyChoicesUpdated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
try {
String[] choices = CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
table.getEntry("PropertyInfo/" + event.name + "/choices").setStringArray(choices);
} catch (VideoException ignored) {
// ignore
}
}
break;
}
case kSinkSourceChanged:
case kSinkCreated:
case kSinkDestroyed:
case kNetworkInterfacesChanged: {
m_addresses = CameraServerJNI.getNetworkInterfaces();
updateStreamValues();
break;
}
default:
break;
}
}, 0x4fff, true);
// Listener for NetworkTable events
// We don't currently support changing settings via NT due to
// synchronization issues, so just update to current setting if someone
// else tries to change it.
m_tableListener = NetworkTableInstance.getDefault().addEntryListener(kPublishName + "/",
event -> {
String relativeKey = event.name.substring(kPublishName.length() + 1);
// get source (sourceName/...)
int subKeyIndex = relativeKey.indexOf('/');
if (subKeyIndex == -1) {
return;
}
String sourceName = relativeKey.substring(0, subKeyIndex);
VideoSource source = m_sources.get(sourceName);
if (source == null) {
return;
}
// get subkey
relativeKey = relativeKey.substring(subKeyIndex + 1);
// handle standard names
String propName;
if ("mode".equals(relativeKey)) {
// reset to current mode
event.getEntry().setString(videoModeToString(source.getVideoMode()));
return;
} else if (relativeKey.startsWith("Property/")) {
propName = relativeKey.substring(9);
} else if (relativeKey.startsWith("RawProperty/")) {
propName = relativeKey.substring(12);
} else {
return; // ignore
}
// everything else is a property
VideoProperty property = source.getProperty(propName);
switch (property.getKind()) {
case kNone:
return;
case kBoolean:
// reset to current setting
event.getEntry().setBoolean(property.get() != 0);
return;
case kInteger:
case kEnum:
// reset to current setting
event.getEntry().setDouble(property.get());
return;
case kString:
// reset to current setting
event.getEntry().setString(property.getString());
return;
default:
return;
}
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kUpdate);
}
private CameraServer() {}
/**
* Start automatically capturing images to send to the dashboard.
*
* <p>You should call this method to see a camera feed on the dashboard.
* If you also want to perform vision processing on the roboRIO, use
* getVideo() to get access to the camera images.
* <p>You should call this method to see a camera feed on the dashboard. If you also want to
* perform vision processing on the roboRIO, use getVideo() to get access to the camera images.
*
* <p>The first time this overload is called, it calls
* {@link #startAutomaticCapture(int)} with device 0, creating a camera
* named "USB Camera 0". Subsequent calls increment the device number
* <p>The first time this overload is called, it calls {@link #startAutomaticCapture(int)} with
* device 0, creating a camera named "USB Camera 0". Subsequent calls increment the device number
* (e.g. 1, 2, etc).
*
* @return The USB camera capturing images.
*/
public UsbCamera startAutomaticCapture() {
public static UsbCamera startAutomaticCapture() {
UsbCamera camera = startAutomaticCapture(m_defaultUsbDevice.getAndIncrement());
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
return camera;
@@ -502,12 +523,13 @@ public final class CameraServer {
/**
* Start automatically capturing images to send to the dashboard.
*
* <p>This overload calls {@link #startAutomaticCapture(String, int)} with
* a name of "USB Camera {dev}".
* <p>This overload calls {@link #startAutomaticCapture(String, int)} with a name of "USB Camera
* {dev}".
*
* @param dev The device number of the camera interface
* @return The USB camera capturing images.
*/
public UsbCamera startAutomaticCapture(int dev) {
public static UsbCamera startAutomaticCapture(int dev) {
UsbCamera camera = new UsbCamera("USB Camera " + dev, dev);
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
@@ -519,8 +541,9 @@ public final class CameraServer {
*
* @param name The name to give the camera
* @param dev The device number of the camera interface
* @return The USB camera capturing images.
*/
public UsbCamera startAutomaticCapture(String name, int dev) {
public static UsbCamera startAutomaticCapture(String name, int dev) {
UsbCamera camera = new UsbCamera(name, dev);
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
@@ -532,8 +555,9 @@ public final class CameraServer {
*
* @param name The name to give the camera
* @param path The device path (e.g. "/dev/video0") of the camera
* @return The USB camera capturing images.
*/
public UsbCamera startAutomaticCapture(String name, String path) {
public static UsbCamera startAutomaticCapture(String name, String path) {
UsbCamera camera = new UsbCamera(name, path);
startAutomaticCapture(camera);
CameraServerSharedStore.getCameraServerShared().reportUsbCamera(camera.getHandle());
@@ -541,12 +565,12 @@ public final class CameraServer {
}
/**
* Start automatically capturing images to send to the dashboard from
* an existing camera.
* Start automatically capturing images to send to the dashboard from an existing camera.
*
* @param camera Camera
* @return The MJPEG server serving images from the given camera.
*/
public MjpegServer startAutomaticCapture(VideoSource camera) {
public static MjpegServer startAutomaticCapture(VideoSource camera) {
addCamera(camera);
MjpegServer server = addServer("serve_" + camera.getName());
server.setSource(camera);
@@ -556,24 +580,24 @@ public final class CameraServer {
/**
* Adds an Axis IP camera.
*
* <p>This overload calls {@link #addAxisCamera(String, String)} with
* name "Axis Camera".
* <p>This overload calls {@link #addAxisCamera(String, String)} with name "Axis Camera".
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
* @return The Axis camera capturing images.
*/
public AxisCamera addAxisCamera(String host) {
public static AxisCamera addAxisCamera(String host) {
return addAxisCamera("Axis Camera", host);
}
/**
* Adds an Axis IP camera.
*
* <p>This overload calls {@link #addAxisCamera(String, String[])} with
* name "Axis Camera".
* <p>This overload calls {@link #addAxisCamera(String, String[])} with name "Axis Camera".
*
* @param hosts Array of Camera host IPs/DNS names
* @return The Axis camera capturing images.
*/
public AxisCamera addAxisCamera(String[] hosts) {
public static AxisCamera addAxisCamera(String[] hosts) {
return addAxisCamera("Axis Camera", hosts);
}
@@ -582,8 +606,9 @@ public final class CameraServer {
*
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
* @return The Axis camera capturing images.
*/
public AxisCamera addAxisCamera(String name, String host) {
public static AxisCamera addAxisCamera(String name, String host) {
AxisCamera camera = new AxisCamera(name, host);
// Create a passthrough MJPEG server for USB access
startAutomaticCapture(camera);
@@ -596,8 +621,9 @@ public final class CameraServer {
*
* @param name The name to give the camera
* @param hosts Array of Camera host IPs/DNS names
* @return The Axis camera capturing images.
*/
public AxisCamera addAxisCamera(String name, String[] hosts) {
public static AxisCamera addAxisCamera(String name, String[] hosts) {
AxisCamera camera = new AxisCamera(name, hosts);
// Create a passthrough MJPEG server for USB access
startAutomaticCapture(camera);
@@ -606,16 +632,18 @@ public final class CameraServer {
}
/**
* Adds a virtual camera for switching between two streams. Unlike the
* other addCamera methods, this returns a VideoSink rather than a
* VideoSource. Calling setSource() on the returned object can be used
* to switch the actual source of the stream.
* Adds a virtual camera for switching between two streams. Unlike the other addCamera methods,
* this returns a VideoSink rather than a VideoSource. Calling setSource() on the returned object
* can be used to switch the actual source of the stream.
*
* @param name The name to give the camera
* @return The MJPEG server serving images from the given camera.
*/
public MjpegServer addSwitchedCamera(String name) {
public static MjpegServer addSwitchedCamera(String name) {
// create a dummy CvSource
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, 160, 120, 30);
MjpegServer server = startAutomaticCapture(source);
synchronized (this) {
synchronized (CameraServer.class) {
m_fixedSources.put(server.getHandle(), source.getHandle());
}
@@ -623,15 +651,17 @@ public final class CameraServer {
}
/**
* Get OpenCV access to the primary camera feed. This allows you to
* get images from the camera for image processing on the roboRIO.
* Get OpenCV access to the primary camera feed. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
* <p>This is only valid to call after a camera feed has been added with startAutomaticCapture()
* or addServer().
*
* @return OpenCV sink for the primary camera feed
*/
public CvSink getVideo() {
public static CvSink getVideo() {
VideoSource source;
synchronized (this) {
synchronized (CameraServer.class) {
if (m_primarySourceName == null) {
throw new VideoException("no camera available");
}
@@ -644,15 +674,16 @@ public final class CameraServer {
}
/**
* Get OpenCV access to the specified camera. This allows you to get
* images from the camera for image processing on the roboRIO.
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* @param camera Camera (e.g. as returned by startAutomaticCapture).
* @return OpenCV sink for the specified camera
*/
public CvSink getVideo(VideoSource camera) {
public static CvSink getVideo(VideoSource camera) {
String name = "opencv_" + camera.getName();
synchronized (this) {
synchronized (CameraServer.class) {
VideoSink sink = m_sinks.get(name);
if (sink != null) {
VideoSink.Kind kind = sink.getKind();
@@ -670,14 +701,15 @@ public final class CameraServer {
}
/**
* Get OpenCV access to the specified camera. This allows you to get
* images from the camera for image processing on the roboRIO.
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* @param name Camera name
* @return OpenCV sink for the specified camera
*/
public CvSink getVideo(String name) {
public static CvSink getVideo(String name) {
VideoSource source;
synchronized (this) {
synchronized (CameraServer.class) {
source = m_sources.get(name);
if (source == null) {
throw new VideoException("could not find camera " + name);
@@ -687,14 +719,15 @@ public final class CameraServer {
}
/**
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
* annotated images to the dashboard.
* Create a MJPEG stream with OpenCV input. This can be called to pass custom annotated images to
* the dashboard.
*
* @param name Name to give the stream
* @param width Width of the image being sent
* @param height Height of the image being sent
* @return OpenCV source for the MJPEG stream
*/
public CvSource putVideo(String name, int width, int height) {
public static CvSource putVideo(String name, int width, int height) {
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, width, height, 30);
startAutomaticCapture(source);
return source;
@@ -704,10 +737,11 @@ public final class CameraServer {
* Adds a MJPEG server at the next available port.
*
* @param name Server name
* @return The MJPEG server
*/
public MjpegServer addServer(String name) {
public static MjpegServer addServer(String name) {
int port;
synchronized (this) {
synchronized (CameraServer.class) {
port = m_nextPort;
m_nextPort++;
}
@@ -718,8 +752,10 @@ public final class CameraServer {
* Adds a MJPEG server.
*
* @param name Server name
* @param port Server port
* @return The MJPEG server
*/
public MjpegServer addServer(String name, int port) {
public static MjpegServer addServer(String name, int port) {
MjpegServer server = new MjpegServer(name, port);
addServer(server);
return server;
@@ -730,8 +766,8 @@ public final class CameraServer {
*
* @param server Server
*/
public void addServer(VideoSink server) {
synchronized (this) {
public static void addServer(VideoSink server) {
synchronized (CameraServer.class) {
m_sinks.put(server.getName(), server);
}
}
@@ -741,8 +777,8 @@ public final class CameraServer {
*
* @param name Server name
*/
public void removeServer(String name) {
synchronized (this) {
public static void removeServer(String name) {
synchronized (CameraServer.class) {
m_sinks.remove(name);
}
}
@@ -750,11 +786,13 @@ public final class CameraServer {
/**
* Get server for the primary camera feed.
*
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
* <p>This is only valid to call after a camera feed has been added with startAutomaticCapture()
* or addServer().
*
* @return The server for the primary camera feed
*/
public VideoSink getServer() {
synchronized (this) {
public static VideoSink getServer() {
synchronized (CameraServer.class) {
if (m_primarySourceName == null) {
throw new VideoException("no camera available");
}
@@ -766,9 +804,10 @@ public final class CameraServer {
* Gets a server by name.
*
* @param name Server name
* @return The server
*/
public VideoSink getServer(String name) {
synchronized (this) {
public static VideoSink getServer(String name) {
synchronized (CameraServer.class) {
return m_sinks.get(name);
}
}
@@ -778,9 +817,9 @@ public final class CameraServer {
*
* @param camera Camera
*/
public void addCamera(VideoSource camera) {
public static void addCamera(VideoSource camera) {
String name = camera.getName();
synchronized (this) {
synchronized (CameraServer.class) {
if (m_primarySourceName == null) {
m_primarySourceName = name;
}
@@ -793,8 +832,8 @@ public final class CameraServer {
*
* @param name Camera name
*/
public void removeCamera(String name) {
synchronized (this) {
public static void removeCamera(String name) {
synchronized (CameraServer.class) {
m_sources.remove(name);
}
}

View File

@@ -1,13 +1,9 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.cameraserver;
public interface CameraServerShared {
/**
* get the main thread id func.

View File

@@ -1,56 +1,48 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.cameraserver;
public final class CameraServerSharedStore {
private static CameraServerShared cameraServerShared;
private CameraServerSharedStore() {
}
private CameraServerSharedStore() {}
/**
* get the CameraServerShared object.
* Get the CameraServerShared object.
*
* @return The CameraServerSharedObject
*/
public static synchronized CameraServerShared getCameraServerShared() {
if (cameraServerShared == null) {
cameraServerShared = new CameraServerShared() {
cameraServerShared =
new CameraServerShared() {
@Override
public void reportVideoServer(int id) {}
@Override
public void reportVideoServer(int id) {
@Override
public void reportUsbCamera(int id) {}
}
@Override
public void reportDriverStationError(String error) {}
@Override
public void reportUsbCamera(int id) {
@Override
public void reportAxisCamera(int id) {}
}
@Override
public void reportDriverStationError(String error) {
}
@Override
public void reportAxisCamera(int id) {
}
@Override
public Long getRobotMainThreadId() {
return null;
}
};
@Override
public Long getRobotMainThreadId() {
return null;
}
};
}
return cameraServerShared;
}
/**
* set the CameraServerShared object.
* Set the CameraServerShared object.
*
* @param shared The CameraServerShared object.
*/
public static synchronized void setCameraServerShared(CameraServerShared shared) {
cameraServerShared = shared;

View File

@@ -1,26 +1,24 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.vision;
import org.opencv.core.Mat;
/**
* A vision pipeline is responsible for running a group of
* OpenCV algorithms to extract data from an image.
* A vision pipeline is responsible for running a group of OpenCV algorithms to extract data from an
* image.
*
* @see VisionRunner
* @see VisionThread
*/
public interface VisionPipeline {
/**
* Processes the image input and sets the result objects.
* Implementations should make these objects accessible.
* Processes the image input and sets the result objects. Implementations should make these
* objects accessible.
*
* @param image The image to process.
*/
void process(Mat image);
}

View File

@@ -1,22 +1,18 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.vision;
import edu.wpi.first.cameraserver.CameraServerSharedStore;
import edu.wpi.first.cscore.CvSink;
import edu.wpi.first.cscore.VideoSource;
import org.opencv.core.Mat;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.cameraserver.CameraServerSharedStore;
/**
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines
* from robot code. The easiest way to use this is to run it in a {@link VisionThread}
* and use the listener to take snapshots of the pipeline's outputs.
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines from robot
* code. The easiest way to use this is to run it in a {@link VisionThread} and use the listener to
* take snapshots of the pipeline's outputs.
*
* @see VisionPipeline
* @see VisionThread
@@ -45,17 +41,16 @@ public class VisionRunner<P extends VisionPipeline> {
* @param pipeline the vision pipeline that ran
*/
void copyPipelineOutputs(P pipeline);
}
/**
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to
* the {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert
* user code when it is safe to access the pipeline's outputs.
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to the
* {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert user
* code when it is safe to access the pipeline's outputs.
*
* @param videoSource the video source to use to supply images for the pipeline
* @param pipeline the vision pipeline to run
* @param listener a function to call after the pipeline has finished running
* @param pipeline the vision pipeline to run
* @param listener a function to call after the pipeline has finished running
*/
public VisionRunner(VideoSource videoSource, P pipeline, Listener<? super P> listener) {
this.m_pipeline = pipeline;
@@ -64,15 +59,15 @@ public class VisionRunner<P extends VisionPipeline> {
}
/**
* Runs the pipeline one time, giving it the next image from the video source specified
* in the constructor. This will block until the source either has an image or throws an error.
* If the source successfully supplied a frame, the pipeline's image input will be set,
* the pipeline will run, and the listener specified in the constructor will be called to notify
* it that the pipeline ran.
* Runs the pipeline one time, giving it the next image from the video source specified in the
* constructor. This will block until the source either has an image or throws an error. If the
* source successfully supplied a frame, the pipeline's image input will be set, the pipeline will
* run, and the listener specified in the constructor will be called to notify it that the
* pipeline ran.
*
* <p>This method is exposed to allow teams to add additional functionality or have their own
* ways to run the pipeline. Most teams, however, should just use {@link #runForever} in its own
* thread using a {@link VisionThread}.</p>
* <p>This method is exposed to allow teams to add additional functionality or have their own ways
* to run the pipeline. Most teams, however, should just use {@link #runForever} in its own thread
* using a {@link VisionThread}.
*/
public void runOnce() {
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
@@ -98,11 +93,11 @@ public class VisionRunner<P extends VisionPipeline> {
}
/**
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must
* be run in a dedicated thread, and cannot be used in the main robot thread because
* it will freeze the robot program.
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must be run in a
* dedicated thread, and cannot be used in the main robot thread because it will freeze the robot
* program.
*
* <p><strong>Do not call this method directly from the main thread.</strong></p>
* <p><strong>Do not call this method directly from the main thread.</strong>
*
* @throws IllegalStateException if this is called from the main robot thread
* @see VisionThread
@@ -119,9 +114,7 @@ public class VisionRunner<P extends VisionPipeline> {
}
}
/**
* Stop a RunForever() loop.
*/
/** Stop a RunForever() loop. */
public void stop() {
m_enabled = false;
}

View File

@@ -1,18 +1,15 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.vision;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.cscore.VideoSource;
/**
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread;
* it does not prevent the program from exiting when all other non-daemon threads
* have finished running.
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread; it
* does not prevent the program from exiting when all other non-daemon threads have finished
* running.
*
* @see VisionPipeline
* @see VisionRunner
@@ -34,14 +31,12 @@ public class VisionThread extends Thread {
* equivalent to {@code new VisionThread(new VisionRunner<>(videoSource, pipeline, listener))}.
*
* @param videoSource the source for images the pipeline should process
* @param pipeline the pipeline to run
* @param listener the listener to copy outputs from the pipeline after it runs
* @param <P> the type of the pipeline
* @param pipeline the pipeline to run
* @param listener the listener to copy outputs from the pipeline after it runs
* @param <P> the type of the pipeline
*/
public <P extends VisionPipeline> VisionThread(VideoSource videoSource,
P pipeline,
VisionRunner.Listener<? super P> listener) {
public <P extends VisionPipeline> VisionThread(
VideoSource videoSource, P pipeline, VisionRunner.Listener<? super P> listener) {
this(new VisionRunner<>(videoSource, pipeline, listener));
}
}

View File

@@ -1,22 +1,19 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
/**
* Classes in the {@code edu.wpi.first.vision} package are designed to
* simplify using OpenCV vision processing code from a robot program.
* Classes in the {@code edu.wpi.first.vision} package are designed to simplify using OpenCV vision
* processing code from a robot program.
*
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous: <br>
*
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous:
* <br>
* <pre><code>
* public class Robot extends IterativeRobot
* implements VisionRunner.Listener&lt;MyFindTotePipeline&gt; {
*
* // A USB camera connected to the roboRIO.
* private {@link edu.wpi.cscore.VideoSource VideoSource} usbCamera;
* private {@link edu.wpi.first.cscore.VideoSource VideoSource} usbCamera;
*
* // A vision pipeline. This could be handwritten or generated by GRIP.
* // This has to implement {@link edu.wpi.first.vision.VisionPipeline}.
@@ -47,7 +44,7 @@
*
* {@literal @}Override
* public void robotInit() {
* usbCamera = CameraServer.getInstance().startAutomaticCapture(0);
* usbCamera = CameraServer.startAutomaticCapture(0);
* findTotePipeline = new MyFindTotePipeline();
* findToteThread = new VisionThread(usbCamera, findTotePipeline, this);
* }

View File

@@ -1,23 +1,20 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "cameraserver/CameraServer.h"
#include <atomic>
#include <vector>
#include <fmt/format.h>
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#include <wpi/DenseMap.h>
#include <wpi/ManagedStatic.h>
#include <wpi/SmallString.h>
#include <wpi/StringExtras.h>
#include <wpi/StringMap.h>
#include <wpi/mutex.h>
#include <wpi/raw_ostream.h>
#include "cameraserver/CameraServerShared.h"
#include "ntcore_cpp.h"
@@ -26,8 +23,9 @@ using namespace frc;
static constexpr char const* kPublishName = "/CameraPublisher";
struct CameraServer::Impl {
Impl();
namespace {
struct Instance {
Instance();
std::shared_ptr<nt::NetworkTable> GetSourceTable(CS_Source source);
std::vector<std::string> GetSinkStreamValues(CS_Sink sink);
std::vector<std::string> GetSourceStreamValues(CS_Source source);
@@ -40,41 +38,45 @@ struct CameraServer::Impl {
wpi::StringMap<cs::VideoSink> m_sinks;
wpi::DenseMap<CS_Sink, CS_Source> m_fixedSources;
wpi::DenseMap<CS_Source, std::shared_ptr<nt::NetworkTable>> m_tables;
std::shared_ptr<nt::NetworkTable> m_publishTable;
std::shared_ptr<nt::NetworkTable> m_publishTable{
nt::NetworkTableInstance::GetDefault().GetTable(kPublishName)};
cs::VideoListener m_videoListener;
int m_tableListener;
int m_nextPort;
int m_nextPort{CameraServer::kBasePort};
std::vector<std::string> m_addresses;
};
} // namespace
CameraServer* CameraServer::GetInstance() {
struct Creator {
static void* call() { return new CameraServer{}; }
};
struct Deleter {
static void call(void* ptr) { delete static_cast<CameraServer*>(ptr); }
};
static wpi::ManagedStatic<CameraServer, Creator, Deleter> instance;
return &(*instance);
static Instance& GetInstance() {
static Instance instance;
return instance;
}
static wpi::StringRef MakeSourceValue(CS_Source source,
wpi::SmallVectorImpl<char>& buf) {
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;
buf.clear();
switch (cs::GetSourceKind(source, &status)) {
case CS_SOURCE_USB: {
wpi::StringRef prefix{"usb:"};
std::string_view prefix{"usb:"};
buf.append(prefix.begin(), prefix.end());
auto path = cs::GetUsbCameraPath(source, &status);
buf.append(path.begin(), path.end());
break;
}
case CS_SOURCE_HTTP: {
wpi::StringRef prefix{"ip:"};
std::string_view prefix{"ip:"};
buf.append(prefix.begin(), prefix.end());
auto urls = cs::GetHttpCameraUrls(source, &status);
if (!urls.empty()) buf.append(urls[0].begin(), urls[0].end());
if (!urls.empty()) {
buf.append(urls[0].begin(), urls[0].end());
}
break;
}
case CS_SOURCE_CV:
@@ -83,27 +85,25 @@ static wpi::StringRef MakeSourceValue(CS_Source source,
return "unknown:";
}
return wpi::StringRef{buf.begin(), buf.size()};
return {buf.begin(), buf.size()};
}
static std::string MakeStreamValue(const wpi::Twine& address, int port) {
return ("mjpg:http://" + address + wpi::Twine(':') + wpi::Twine(port) +
"/?action=stream")
.str();
static std::string MakeStreamValue(std::string_view address, int port) {
return fmt::format("mjpg:http://{}:{}/?action=stream", address, port);
}
std::shared_ptr<nt::NetworkTable> CameraServer::Impl::GetSourceTable(
CS_Source source) {
std::shared_ptr<nt::NetworkTable> Instance::GetSourceTable(CS_Source source) {
std::scoped_lock lock(m_mutex);
return m_tables.lookup(source);
}
std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
std::vector<std::string> Instance::GetSinkStreamValues(CS_Sink sink) {
CS_Status status = 0;
// Ignore all but MjpegServer
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG)
return std::vector<std::string>{};
if (cs::GetSinkKind(sink, &status) != CS_SINK_MJPEG) {
return {};
}
// Get port
int port = cs::GetMjpegServerPort(sink, &status);
@@ -119,7 +119,9 @@ std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
values.emplace_back(MakeStreamValue(cs::GetHostname() + ".local", port));
for (const auto& addr : m_addresses) {
if (addr == "127.0.0.1") continue; // ignore localhost
if (addr == "127.0.0.1") {
continue; // ignore localhost
}
values.emplace_back(MakeStreamValue(addr, port));
}
}
@@ -127,17 +129,19 @@ std::vector<std::string> CameraServer::Impl::GetSinkStreamValues(CS_Sink sink) {
return values;
}
std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
CS_Source source) {
std::vector<std::string> Instance::GetSourceStreamValues(CS_Source source) {
CS_Status status = 0;
// Ignore all but HttpCamera
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP)
return std::vector<std::string>{};
if (cs::GetSourceKind(source, &status) != CS_SOURCE_HTTP) {
return {};
}
// Generate values
auto values = cs::GetHttpCameraUrls(source, &status);
for (auto& value : values) value = "mjpg:" + value;
for (auto& value : values) {
value = "mjpg:" + value;
}
#ifdef __FRC_ROBORIO__
// Look to see if we have a passthrough server for this source
@@ -159,7 +163,7 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
return values;
}
void CameraServer::Impl::UpdateStreamValues() {
void Instance::UpdateStreamValues() {
std::scoped_lock lock(m_mutex);
// Over all the sinks...
for (const auto& i : m_sinks) {
@@ -168,16 +172,24 @@ void CameraServer::Impl::UpdateStreamValues() {
// Get the source's subtable (if none exists, we're done)
CS_Source source = m_fixedSources.lookup(sink);
if (source == 0) source = cs::GetSinkSource(sink, &status);
if (source == 0) continue;
if (source == 0) {
source = cs::GetSinkSource(sink, &status);
}
if (source == 0) {
continue;
}
auto table = m_tables.lookup(source);
if (table) {
// Don't set stream values if this is a HttpCamera passthrough
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) continue;
if (cs::GetSourceKind(source, &status) == CS_SOURCE_HTTP) {
continue;
}
// Set table value
auto values = GetSinkStreamValues(sink);
if (!values.empty()) table->GetEntry("streams").SetStringArray(values);
if (!values.empty()) {
table->GetEntry("streams").SetStringArray(values);
}
}
}
@@ -190,7 +202,9 @@ void CameraServer::Impl::UpdateStreamValues() {
if (table) {
// Set table value
auto values = GetSourceStreamValues(source);
if (!values.empty()) table->GetEntry("streams").SetStringArray(values);
if (!values.empty()) {
table->GetEntry("streams").SetStringArray(values);
}
}
}
}
@@ -213,79 +227,72 @@ static std::string PixelFormatToString(int pixelFormat) {
}
static std::string VideoModeToString(const cs::VideoMode& mode) {
std::string rv;
wpi::raw_string_ostream oss{rv};
oss << mode.width << "x" << mode.height;
oss << " " << PixelFormatToString(mode.pixelFormat) << " ";
oss << mode.fps << " fps";
return oss.str();
return fmt::format("{}x{} {} {} fps", mode.width, mode.height,
PixelFormatToString(mode.pixelFormat), mode.fps);
}
static std::vector<std::string> GetSourceModeValues(int source) {
std::vector<std::string> rv;
CS_Status status = 0;
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status))
for (const auto& mode : cs::EnumerateSourceVideoModes(source, &status)) {
rv.emplace_back(VideoModeToString(mode));
}
return rv;
}
static void PutSourcePropertyValue(nt::NetworkTable* table,
const cs::VideoEvent& event, bool isNew) {
wpi::SmallString<64> name;
wpi::SmallString<64> infoName;
if (wpi::StringRef{event.name}.startswith("raw_")) {
name = "RawProperty/";
name += event.name;
infoName = "RawPropertyInfo/";
infoName += event.name;
std::string_view namePrefix;
std::string_view infoPrefix;
if (wpi::starts_with(event.name, "raw_")) {
namePrefix = "RawProperty";
infoPrefix = "RawPropertyInfo";
} else {
name = "Property/";
name += event.name;
infoName = "PropertyInfo/";
infoName += event.name;
namePrefix = "Property";
infoPrefix = "PropertyInfo";
}
wpi::SmallString<64> buf;
CS_Status status = 0;
nt::NetworkTableEntry entry = table->GetEntry(name);
nt::NetworkTableEntry entry =
table->GetEntry(fmt::format("{}/{}", namePrefix, event.name));
switch (event.propertyKind) {
case CS_PROP_BOOLEAN:
if (isNew)
if (isNew) {
entry.SetDefaultBoolean(event.value != 0);
else
} else {
entry.SetBoolean(event.value != 0);
}
break;
case CS_PROP_INTEGER:
case CS_PROP_ENUM:
if (isNew) {
entry.SetDefaultDouble(event.value);
table->GetEntry(infoName + "/min")
table->GetEntry(fmt::format("{}/{}/min", infoPrefix, event.name))
.SetDouble(cs::GetPropertyMin(event.propertyHandle, &status));
table->GetEntry(infoName + "/max")
table->GetEntry(fmt::format("{}/{}/max", infoPrefix, event.name))
.SetDouble(cs::GetPropertyMax(event.propertyHandle, &status));
table->GetEntry(infoName + "/step")
table->GetEntry(fmt::format("{}/{}/step", infoPrefix, event.name))
.SetDouble(cs::GetPropertyStep(event.propertyHandle, &status));
table->GetEntry(infoName + "/default")
table->GetEntry(fmt::format("{}/{}/default", infoPrefix, event.name))
.SetDouble(cs::GetPropertyDefault(event.propertyHandle, &status));
} else {
entry.SetDouble(event.value);
}
break;
case CS_PROP_STRING:
if (isNew)
if (isNew) {
entry.SetDefaultString(event.valueStr);
else
} else {
entry.SetString(event.valueStr);
}
break;
default:
break;
}
}
CameraServer::Impl::Impl()
: m_publishTable{nt::NetworkTableInstance::GetDefault().GetTable(
kPublishName)},
m_nextPort(kBasePort) {
Instance::Instance() {
// We publish sources to NetworkTables using the following structure:
// "/CameraPublisher/{Source.Name}/" - root
// - "source" (string): Descriptive, prefixed with type (e.g. "usb:0")
@@ -351,41 +358,48 @@ CameraServer::Impl::Impl()
}
case cs::VideoEvent::kSourceDisconnected: {
auto table = GetSourceTable(event.sourceHandle);
if (table) table->GetEntry("connected").SetBoolean(false);
if (table) {
table->GetEntry("connected").SetBoolean(false);
}
break;
}
case cs::VideoEvent::kSourceVideoModesUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table)
if (table) {
table->GetEntry("modes").SetStringArray(
GetSourceModeValues(event.sourceHandle));
}
break;
}
case cs::VideoEvent::kSourceVideoModeChanged: {
auto table = GetSourceTable(event.sourceHandle);
if (table)
if (table) {
table->GetEntry("mode").SetString(VideoModeToString(event.mode));
}
break;
}
case cs::VideoEvent::kSourcePropertyCreated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) PutSourcePropertyValue(table.get(), event, true);
if (table) {
PutSourcePropertyValue(table.get(), event, true);
}
break;
}
case cs::VideoEvent::kSourcePropertyValueUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) PutSourcePropertyValue(table.get(), event, false);
if (table) {
PutSourcePropertyValue(table.get(), event, false);
}
break;
}
case cs::VideoEvent::kSourcePropertyChoicesUpdated: {
auto table = GetSourceTable(event.sourceHandle);
if (table) {
wpi::SmallString<64> name{"PropertyInfo/"};
name += event.name;
name += "/choices";
auto choices =
cs::GetEnumPropertyChoices(event.propertyHandle, &status);
table->GetEntry(name).SetStringArray(choices);
table
->GetEntry(fmt::format("PropertyInfo/{}/choices", event.name))
.SetStringArray(choices);
}
break;
}
@@ -409,32 +423,36 @@ CameraServer::Impl::Impl()
// else tries to change it.
wpi::SmallString<64> buf;
m_tableListener = nt::NetworkTableInstance::GetDefault().AddEntryListener(
kPublishName + wpi::Twine('/'),
fmt::format("{}/", kPublishName),
[=](const nt::EntryNotification& event) {
wpi::StringRef relativeKey =
event.name.substr(wpi::StringRef(kPublishName).size() + 1);
auto relativeKey = wpi::drop_front(
event.name, std::string_view{kPublishName}.size() + 1);
// get source (sourceName/...)
auto subKeyIndex = relativeKey.find('/');
if (subKeyIndex == wpi::StringRef::npos) return;
wpi::StringRef sourceName = relativeKey.slice(0, subKeyIndex);
if (subKeyIndex == std::string_view::npos) {
return;
}
auto sourceName = wpi::slice(relativeKey, 0, subKeyIndex);
auto sourceIt = m_sources.find(sourceName);
if (sourceIt == m_sources.end()) return;
if (sourceIt == m_sources.end()) {
return;
}
// get subkey
relativeKey = relativeKey.substr(subKeyIndex + 1);
relativeKey.remove_prefix(subKeyIndex + 1);
// handle standard names
wpi::StringRef propName;
std::string_view propName;
nt::NetworkTableEntry entry{event.entry};
if (relativeKey == "mode") {
// reset to current mode
entry.SetString(VideoModeToString(sourceIt->second.GetVideoMode()));
return;
} else if (relativeKey.startswith("Property/")) {
propName = relativeKey.substr(9);
} else if (relativeKey.startswith("RawProperty/")) {
propName = relativeKey.substr(12);
} else if (wpi::starts_with(relativeKey, "Property/")) {
propName = wpi::substr(relativeKey, 9);
} else if (wpi::starts_with(relativeKey, "RawProperty/")) {
propName = wpi::substr(relativeKey, 12);
} else {
return; // ignore
}
@@ -461,26 +479,23 @@ CameraServer::Impl::Impl()
NT_NOTIFY_IMMEDIATE | NT_NOTIFY_UPDATE);
}
CameraServer::CameraServer() : m_impl(new Impl) {}
CameraServer::~CameraServer() {}
cs::UsbCamera CameraServer::StartAutomaticCapture() {
cs::UsbCamera camera = StartAutomaticCapture(m_impl->m_defaultUsbDevice++);
cs::UsbCamera camera =
StartAutomaticCapture(::GetInstance().m_defaultUsbDevice++);
auto csShared = GetCameraServerShared();
csShared->ReportUsbCamera(camera.GetHandle());
return camera;
}
cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) {
cs::UsbCamera camera{"USB Camera " + wpi::Twine(dev), dev};
cs::UsbCamera camera{fmt::format("USB Camera {}", dev), dev};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
csShared->ReportUsbCamera(camera.GetHandle());
return camera;
}
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
int dev) {
cs::UsbCamera camera{name, dev};
StartAutomaticCapture(camera);
@@ -489,8 +504,8 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
return camera;
}
cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
const wpi::Twine& path) {
cs::UsbCamera CameraServer::StartAutomaticCapture(std::string_view name,
std::string_view path) {
cs::UsbCamera camera{name, path};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
@@ -498,7 +513,7 @@ cs::UsbCamera CameraServer::StartAutomaticCapture(const wpi::Twine& name,
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& host) {
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view host) {
return AddAxisCamera("Axis Camera", host);
}
@@ -510,12 +525,12 @@ cs::AxisCamera CameraServer::AddAxisCamera(const std::string& host) {
return AddAxisCamera("Axis Camera", host);
}
cs::AxisCamera CameraServer::AddAxisCamera(wpi::ArrayRef<std::string> hosts) {
cs::AxisCamera CameraServer::AddAxisCamera(wpi::span<const std::string> hosts) {
return AddAxisCamera("Axis Camera", hosts);
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
const wpi::Twine& host) {
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
std::string_view host) {
cs::AxisCamera camera{name, host};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
@@ -523,7 +538,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
const char* host) {
cs::AxisCamera camera{name, host};
StartAutomaticCapture(camera);
@@ -532,7 +547,7 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
const std::string& host) {
cs::AxisCamera camera{name, host};
StartAutomaticCapture(camera);
@@ -541,8 +556,8 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
return camera;
}
cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
wpi::ArrayRef<std::string> hosts) {
cs::AxisCamera CameraServer::AddAxisCamera(std::string_view name,
wpi::span<const std::string> hosts) {
cs::AxisCamera camera{name, hosts};
StartAutomaticCapture(camera);
auto csShared = GetCameraServerShared();
@@ -550,11 +565,11 @@ cs::AxisCamera CameraServer::AddAxisCamera(const wpi::Twine& name,
return camera;
}
cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
cs::MjpegServer CameraServer::AddSwitchedCamera(std::string_view name) {
// create a dummy CvSource
cs::CvSource source{name, cs::VideoMode::PixelFormat::kMJPEG, 160, 120, 30};
cs::MjpegServer server = StartAutomaticCapture(source);
m_impl->m_fixedSources[server.GetHandle()] = source.GetHandle();
::GetInstance().m_fixedSources[server.GetHandle()] = source.GetHandle();
return server;
}
@@ -562,22 +577,23 @@ cs::MjpegServer CameraServer::AddSwitchedCamera(const wpi::Twine& name) {
cs::MjpegServer CameraServer::StartAutomaticCapture(
const cs::VideoSource& camera) {
AddCamera(camera);
auto server = AddServer(wpi::Twine("serve_") + camera.GetName());
auto server = AddServer(fmt::format("serve_{}", camera.GetName()));
server.SetSource(camera);
return server;
}
cs::CvSink CameraServer::GetVideo() {
auto& inst = ::GetInstance();
cs::VideoSource source;
{
auto csShared = GetCameraServerShared();
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
std::scoped_lock lock(inst.m_mutex);
if (inst.m_primarySourceName.empty()) {
csShared->SetCameraServerError("no camera available");
return cs::CvSink{};
}
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
if (it == m_impl->m_sources.end()) {
auto it = inst.m_sources.find(inst.m_primarySourceName);
if (it == inst.m_sources.end()) {
csShared->SetCameraServerError("no camera available");
return cs::CvSink{};
}
@@ -587,40 +603,40 @@ cs::CvSink CameraServer::GetVideo() {
}
cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
auto& inst = ::GetInstance();
wpi::SmallString<64> name{"opencv_"};
name += camera.GetName();
{
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sinks.find(name);
if (it != m_impl->m_sinks.end()) {
std::scoped_lock lock(inst.m_mutex);
auto it = inst.m_sinks.find(name);
if (it != inst.m_sinks.end()) {
auto kind = it->second.GetKind();
if (kind != cs::VideoSink::kCv) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("expected OpenCV sink, but got " +
wpi::Twine(kind));
csShared->SetCameraServerError("expected OpenCV sink, but got {}",
kind);
return cs::CvSink{};
}
return *static_cast<cs::CvSink*>(&it->second);
}
}
cs::CvSink newsink{name};
cs::CvSink newsink{name.str()};
newsink.SetSource(camera);
AddServer(newsink);
return newsink;
}
cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
wpi::SmallString<64> nameBuf;
wpi::StringRef nameStr = name.toStringRef(nameBuf);
cs::CvSink CameraServer::GetVideo(std::string_view name) {
auto& inst = ::GetInstance();
cs::VideoSource source;
{
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sources.find(nameStr);
if (it == m_impl->m_sources.end()) {
std::scoped_lock lock(inst.m_mutex);
auto it = inst.m_sources.find(name);
if (it == inst.m_sources.end()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("could not find camera " + nameStr);
csShared->SetCameraServerError("could not find camera {}", name);
return cs::CvSink{};
}
source = it->second;
@@ -628,89 +644,99 @@ cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
return GetVideo(source);
}
cs::CvSource CameraServer::PutVideo(const wpi::Twine& name, int width,
cs::CvSource CameraServer::PutVideo(std::string_view name, int width,
int height) {
cs::CvSource source{name, cs::VideoMode::kMJPEG, width, height, 30};
StartAutomaticCapture(source);
return source;
}
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
cs::MjpegServer CameraServer::AddServer(std::string_view name) {
auto& inst = ::GetInstance();
int port;
{
std::scoped_lock lock(m_impl->m_mutex);
port = m_impl->m_nextPort++;
std::scoped_lock lock(inst.m_mutex);
port = inst.m_nextPort++;
}
return AddServer(name, port);
}
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name, int port) {
cs::MjpegServer CameraServer::AddServer(std::string_view name, int port) {
cs::MjpegServer server{name, port};
AddServer(server);
return server;
}
void CameraServer::AddServer(const cs::VideoSink& server) {
std::scoped_lock lock(m_impl->m_mutex);
m_impl->m_sinks.try_emplace(server.GetName(), server);
auto& inst = ::GetInstance();
std::scoped_lock lock(inst.m_mutex);
inst.m_sinks.try_emplace(server.GetName(), server);
}
void CameraServer::RemoveServer(const wpi::Twine& name) {
std::scoped_lock lock(m_impl->m_mutex);
wpi::SmallString<64> nameBuf;
m_impl->m_sinks.erase(name.toStringRef(nameBuf));
void CameraServer::RemoveServer(std::string_view name) {
auto& inst = ::GetInstance();
std::scoped_lock lock(inst.m_mutex);
inst.m_sinks.erase(name);
}
cs::VideoSink CameraServer::GetServer() {
wpi::SmallString<64> name;
auto& inst = ::GetInstance();
std::string name;
{
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
std::scoped_lock lock(inst.m_mutex);
if (inst.m_primarySourceName.empty()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("no camera available");
return cs::VideoSink{};
}
name = "serve_";
name += m_impl->m_primarySourceName;
name = fmt::format("serve_{}", inst.m_primarySourceName);
}
return GetServer(name);
}
cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
wpi::SmallString<64> nameBuf;
wpi::StringRef nameStr = name.toStringRef(nameBuf);
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sinks.find(nameStr);
if (it == m_impl->m_sinks.end()) {
cs::VideoSink CameraServer::GetServer(std::string_view name) {
auto& inst = ::GetInstance();
std::scoped_lock lock(inst.m_mutex);
auto it = inst.m_sinks.find(name);
if (it == inst.m_sinks.end()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("could not find server " + nameStr);
csShared->SetCameraServerError("could not find server {}", name);
return cs::VideoSink{};
}
return it->second;
}
void CameraServer::AddCamera(const cs::VideoSource& camera) {
auto& inst = ::GetInstance();
std::string name = camera.GetName();
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) m_impl->m_primarySourceName = name;
m_impl->m_sources.try_emplace(name, camera);
std::scoped_lock lock(inst.m_mutex);
if (inst.m_primarySourceName.empty()) {
inst.m_primarySourceName = name;
}
inst.m_sources.try_emplace(name, camera);
}
void CameraServer::RemoveCamera(const wpi::Twine& name) {
std::scoped_lock lock(m_impl->m_mutex);
wpi::SmallString<64> nameBuf;
m_impl->m_sources.erase(name.toStringRef(nameBuf));
void CameraServer::RemoveCamera(std::string_view name) {
auto& inst = ::GetInstance();
std::scoped_lock lock(inst.m_mutex);
inst.m_sources.erase(name);
}
void CameraServer::SetSize(int size) {
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) return;
auto it = m_impl->m_sources.find(m_impl->m_primarySourceName);
if (it == m_impl->m_sources.end()) return;
if (size == kSize160x120)
auto& inst = ::GetInstance();
std::scoped_lock lock(inst.m_mutex);
if (inst.m_primarySourceName.empty()) {
return;
}
auto it = inst.m_sources.find(inst.m_primarySourceName);
if (it == inst.m_sources.end()) {
return;
}
if (size == kSize160x120) {
it->second.SetResolution(160, 120);
else if (size == kSize320x240)
} else if (size == kSize320x240) {
it->second.SetResolution(320, 240);
else if (size == kSize640x480)
} else if (size == kSize640x480) {
it->second.SetResolution(640, 480);
}
}

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "cameraserver/CameraServerShared.h"
@@ -15,9 +12,12 @@ class DefaultCameraServerShared : public frc::CameraServerShared {
void ReportUsbCamera(int id) override {}
void ReportAxisCamera(int id) override {}
void ReportVideoServer(int id) override {}
void SetCameraServerError(const wpi::Twine& error) override {}
void SetVisionRunnerError(const wpi::Twine& error) override {}
void ReportDriverStationError(const wpi::Twine& error) override {}
void SetCameraServerErrorV(fmt::string_view format,
fmt::format_args args) override {}
void SetVisionRunnerErrorV(fmt::string_view format,
fmt::format_args args) override {}
void ReportDriverStationErrorV(fmt::string_view format,
fmt::format_args args) override {}
std::pair<std::thread::id, bool> GetRobotMainThreadId() const override {
return std::make_pair(std::thread::id(), false);
}

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "vision/VisionRunner.h"
@@ -23,7 +20,7 @@ VisionRunnerBase::VisionRunnerBase(cs::VideoSource videoSource)
}
// Located here and not in header due to cv::Mat forward declaration.
VisionRunnerBase::~VisionRunnerBase() {}
VisionRunnerBase::~VisionRunnerBase() = default;
void VisionRunnerBase::RunOnce() {
auto csShared = frc::GetCameraServerShared();
@@ -36,7 +33,7 @@ void VisionRunnerBase::RunOnce() {
auto frameTime = m_cvSink.GrabFrame(*m_image);
if (frameTime == 0) {
auto error = m_cvSink.GetError();
csShared->ReportDriverStationError(error);
csShared->ReportDriverStationError(error.c_str());
} else {
DoProcess(*m_image);
}
@@ -56,4 +53,6 @@ void VisionRunnerBase::RunForever() {
}
}
void VisionRunnerBase::Stop() { m_enabled = false; }
void VisionRunnerBase::Stop() {
m_enabled = false;
}

View File

@@ -1,19 +1,16 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2014-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <stdint.h>
#include <memory>
#include <string>
#include <string_view>
#include <wpi/ArrayRef.h>
#include <wpi/Twine.h>
#include <wpi/deprecated.h>
#include <wpi/span.h>
#include "cscore.h"
#include "cscore_cv.h"
@@ -34,7 +31,9 @@ class CameraServer {
/**
* Get the CameraServer instance.
* @deprecated Use the static methods
*/
WPI_DEPRECATED("Use static methods")
static CameraServer* GetInstance();
/**
@@ -48,7 +47,7 @@ class CameraServer {
* with device 0, creating a camera named "USB Camera 0". Subsequent calls
* increment the device number (e.g. 1, 2, etc).
*/
cs::UsbCamera StartAutomaticCapture();
static cs::UsbCamera StartAutomaticCapture();
/**
* Start automatically capturing images to send to the dashboard.
@@ -58,7 +57,7 @@ class CameraServer {
*
* @param dev The device number of the camera interface
*/
cs::UsbCamera StartAutomaticCapture(int dev);
static cs::UsbCamera StartAutomaticCapture(int dev);
/**
* Start automatically capturing images to send to the dashboard.
@@ -66,7 +65,7 @@ class CameraServer {
* @param name The name to give the camera
* @param dev The device number of the camera interface
*/
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name, int dev);
static cs::UsbCamera StartAutomaticCapture(std::string_view name, int dev);
/**
* Start automatically capturing images to send to the dashboard.
@@ -74,8 +73,8 @@ class CameraServer {
* @param name The name to give the camera
* @param path The device path (e.g. "/dev/video0") of the camera
*/
cs::UsbCamera StartAutomaticCapture(const wpi::Twine& name,
const wpi::Twine& path);
static cs::UsbCamera StartAutomaticCapture(std::string_view name,
std::string_view path);
/**
* Start automatically capturing images to send to the dashboard from
@@ -83,7 +82,7 @@ class CameraServer {
*
* @param camera Camera
*/
cs::MjpegServer StartAutomaticCapture(const cs::VideoSource& camera);
static cs::MjpegServer StartAutomaticCapture(const cs::VideoSource& camera);
/**
* Adds an Axis IP camera.
@@ -92,7 +91,7 @@ class CameraServer {
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& host);
static cs::AxisCamera AddAxisCamera(std::string_view host);
/**
* Adds an Axis IP camera.
@@ -101,7 +100,7 @@ class CameraServer {
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const char* host);
static cs::AxisCamera AddAxisCamera(const char* host);
/**
* Adds an Axis IP camera.
@@ -110,7 +109,7 @@ class CameraServer {
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const std::string& host);
static cs::AxisCamera AddAxisCamera(const std::string& host);
/**
* Adds an Axis IP camera.
@@ -119,7 +118,7 @@ class CameraServer {
*
* @param hosts Array of Camera host IPs/DNS names
*/
cs::AxisCamera AddAxisCamera(wpi::ArrayRef<std::string> hosts);
static cs::AxisCamera AddAxisCamera(wpi::span<const std::string> hosts);
/**
* Adds an Axis IP camera.
@@ -129,7 +128,7 @@ class CameraServer {
* @param hosts Array of Camera host IPs/DNS names
*/
template <typename T>
cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
static cs::AxisCamera AddAxisCamera(std::initializer_list<T> hosts);
/**
* Adds an Axis IP camera.
@@ -137,7 +136,8 @@ class CameraServer {
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const wpi::Twine& host);
static cs::AxisCamera AddAxisCamera(std::string_view name,
std::string_view host);
/**
* Adds an Axis IP camera.
@@ -145,7 +145,7 @@ class CameraServer {
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const char* host);
static cs::AxisCamera AddAxisCamera(std::string_view name, const char* host);
/**
* Adds an Axis IP camera.
@@ -153,7 +153,8 @@ class CameraServer {
* @param name The name to give the camera
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name, const std::string& host);
static cs::AxisCamera AddAxisCamera(std::string_view name,
const std::string& host);
/**
* Adds an Axis IP camera.
@@ -161,8 +162,8 @@ class CameraServer {
* @param name The name to give the camera
* @param hosts Array of Camera host IPs/DNS names
*/
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
wpi::ArrayRef<std::string> hosts);
static cs::AxisCamera AddAxisCamera(std::string_view name,
wpi::span<const std::string> hosts);
/**
* Adds an Axis IP camera.
@@ -171,8 +172,8 @@ class CameraServer {
* @param hosts Array of Camera host IPs/DNS names
*/
template <typename T>
cs::AxisCamera AddAxisCamera(const wpi::Twine& name,
std::initializer_list<T> hosts);
static cs::AxisCamera AddAxisCamera(std::string_view name,
std::initializer_list<T> hosts);
/**
* Adds a virtual camera for switching between two streams. Unlike the
@@ -180,7 +181,7 @@ class CameraServer {
* VideoSource. Calling SetSource() on the returned object can be used
* to switch the actual source of the stream.
*/
cs::MjpegServer AddSwitchedCamera(const wpi::Twine& name);
static cs::MjpegServer AddSwitchedCamera(std::string_view name);
/**
* Get OpenCV access to the primary camera feed. This allows you to
@@ -189,7 +190,7 @@ class CameraServer {
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
*/
cs::CvSink GetVideo();
static cs::CvSink GetVideo();
/**
* Get OpenCV access to the specified camera. This allows you to get
@@ -197,7 +198,7 @@ class CameraServer {
*
* @param camera Camera (e.g. as returned by startAutomaticCapture).
*/
cs::CvSink GetVideo(const cs::VideoSource& camera);
static cs::CvSink GetVideo(const cs::VideoSource& camera);
/**
* Get OpenCV access to the specified camera. This allows you to get
@@ -205,7 +206,7 @@ class CameraServer {
*
* @param name Camera name
*/
cs::CvSink GetVideo(const wpi::Twine& name);
static cs::CvSink GetVideo(std::string_view name);
/**
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
@@ -215,35 +216,36 @@ class CameraServer {
* @param width Width of the image being sent
* @param height Height of the image being sent
*/
cs::CvSource PutVideo(const wpi::Twine& name, int width, int height);
static cs::CvSource PutVideo(std::string_view name, int width, int height);
/**
* Adds a MJPEG server at the next available port.
*
* @param name Server name
*/
cs::MjpegServer AddServer(const wpi::Twine& name);
static cs::MjpegServer AddServer(std::string_view name);
/**
* Adds a MJPEG server.
*
* @param name Server name
* @param port Port number
*/
cs::MjpegServer AddServer(const wpi::Twine& name, int port);
static cs::MjpegServer AddServer(std::string_view name, int port);
/**
* Adds an already created server.
*
* @param server Server
*/
void AddServer(const cs::VideoSink& server);
static void AddServer(const cs::VideoSink& server);
/**
* Removes a server by name.
*
* @param name Server name
*/
void RemoveServer(const wpi::Twine& name);
static void RemoveServer(std::string_view name);
/**
* Get server for the primary camera feed.
@@ -251,28 +253,28 @@ class CameraServer {
* This is only valid to call after a camera feed has been added with
* StartAutomaticCapture() or AddServer().
*/
cs::VideoSink GetServer();
static cs::VideoSink GetServer();
/**
* Gets a server by name.
*
* @param name Server name
*/
cs::VideoSink GetServer(const wpi::Twine& name);
static cs::VideoSink GetServer(std::string_view name);
/**
* Adds an already created camera.
*
* @param camera Camera
*/
void AddCamera(const cs::VideoSource& camera);
static void AddCamera(const cs::VideoSource& camera);
/**
* Removes a camera by name.
*
* @param name Camera name
*/
void RemoveCamera(const wpi::Twine& name);
static void RemoveCamera(std::string_view name);
/**
* Sets the size of the image to use. Use the public kSize constants to set
@@ -283,14 +285,10 @@ class CameraServer {
* StartAutomaticCapture() instead.
* @param size The size to use
*/
void SetSize(int size);
static void SetSize(int size);
private:
CameraServer();
~CameraServer();
struct Impl;
std::unique_ptr<Impl> m_impl;
CameraServer() = default;
};
} // namespace frc

View File

@@ -1,15 +1,14 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <string>
#include <vector>
#include "cameraserver/CameraServer.h"
namespace frc {
template <typename T>
@@ -20,10 +19,12 @@ inline cs::AxisCamera CameraServer::AddAxisCamera(
template <typename T>
inline cs::AxisCamera CameraServer::AddAxisCamera(
const wpi::Twine& name, std::initializer_list<T> hosts) {
std::string_view name, std::initializer_list<T> hosts) {
std::vector<std::string> vec;
vec.reserve(hosts.size());
for (const auto& host : hosts) vec.emplace_back(host);
for (const auto& host : hosts) {
vec.emplace_back(host);
}
return AddAxisCamera(name, vec);
}

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
@@ -11,7 +8,7 @@
#include <thread>
#include <utility>
#include <wpi/Twine.h>
#include <fmt/format.h>
namespace frc {
class CameraServerShared {
@@ -20,10 +17,31 @@ class CameraServerShared {
virtual void ReportUsbCamera(int id) = 0;
virtual void ReportAxisCamera(int id) = 0;
virtual void ReportVideoServer(int id) = 0;
virtual void SetCameraServerError(const wpi::Twine& error) = 0;
virtual void SetVisionRunnerError(const wpi::Twine& error) = 0;
virtual void ReportDriverStationError(const wpi::Twine& error) = 0;
virtual void SetCameraServerErrorV(fmt::string_view format,
fmt::format_args args) = 0;
virtual void SetVisionRunnerErrorV(fmt::string_view format,
fmt::format_args args) = 0;
virtual void ReportDriverStationErrorV(fmt::string_view format,
fmt::format_args args) = 0;
virtual std::pair<std::thread::id, bool> GetRobotMainThreadId() const = 0;
template <typename S, typename... Args>
inline void SetCameraServerError(const S& format, Args&&... args) {
SetCameraServerErrorV(format,
fmt::make_args_checked<Args...>(format, args...));
}
template <typename S, typename... Args>
inline void SetVisionRunnerError(const S& format, Args&&... args) {
SetVisionRunnerErrorV(format,
fmt::make_args_checked<Args...>(format, args...));
}
template <typename S, typename... Args>
inline void ReportDriverStationError(const S& format, Args&&... args) {
ReportDriverStationErrorV(format,
fmt::make_args_checked<Args...>(format, args...));
}
};
CameraServerShared* GetCameraServerShared();

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once

View File

@@ -1,9 +1,6 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
@@ -47,14 +44,14 @@ class VisionRunnerBase {
*
* <p>This method is exposed to allow teams to add additional functionality or
* have their own ways to run the pipeline. Most teams, however, should just
* use {@link #runForever} in its own thread using a std::thread.</p>
* use RunForever() in its own thread using a std::thread.</p>
*/
void RunOnce();
/**
* A convenience method that calls {@link #runOnce()} in an infinite loop.
* This must be run in a dedicated thread, and cannot be used in the main
* robot thread because it will freeze the robot program.
* A convenience method that calls runOnce() in an infinite loop. This must be
* run in a dedicated thread, and cannot be used in the main robot thread
* because it will freeze the robot program.
*
* <strong>Do not call this method directly from the main thread.</strong>
*/

View File

@@ -1,12 +1,11 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include "vision/VisionRunner.h"
namespace frc {
/**

View File

@@ -1,8 +1,7 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
int main() { return 0; }
int main() {
return 0;
}

View File

@@ -8,7 +8,7 @@ macro(wpilib_add_test name srcdir)
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
endif()
if (MSVC)
target_compile_options(${name}_test PRIVATE /wd4251 /wd4101)
target_compile_options(${name}_test PRIVATE /wd4101 /wd4251)
endif()
add_test(NAME ${name} COMMAND ${name}_test)
endmacro()

View File

@@ -2,6 +2,6 @@ macro(wpilib_target_warnings target)
if(NOT MSVC)
target_compile_options(${target} PRIVATE -Wall -pedantic -Wextra -Werror -Wno-unused-parameter -Wno-error=deprecated-declarations)
else()
target_compile_options(${target} PRIVATE /wd4244 /wd4267 /wd4146 /WX /wd4996)
target_compile_options(${target} PRIVATE /wd4146 /wd4244 /wd4251 /wd4267 /wd4996 /WX)
endif()
endmacro()

View File

@@ -0,0 +1,116 @@
# - Try to find LibSSH
# Once done this will define
#
# LIBSSH_FOUND - system has LibSSH
# LIBSSH_INCLUDE_DIRS - the LibSSH include directory
# LIBSSH_LIBRARIES - link these to use LibSSH
# LIBSSH_VERSION -
#
# Author Michal Vasko <mvasko@cesnet.cz>
# Copyright (c) 2020 CESNET, z.s.p.o.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
include(FindPackageHandleStandardArgs)
if(LIBSSH_LIBRARIES AND LIBSSH_INCLUDE_DIRS)
# in cache already
set(LIBSSH_FOUND TRUE)
else()
find_path(LIBSSH_INCLUDE_DIR
NAMES
libssh/libssh.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
${CMAKE_INCLUDE_PATH}
${CMAKE_INSTALL_PREFIX}/include
)
find_library(LIBSSH_LIBRARY
NAMES
ssh.so
libssh.so
libssh.dylib
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
${CMAKE_LIBRARY_PATH}
${CMAKE_INSTALL_PREFIX}/lib
)
if(LIBSSH_INCLUDE_DIR AND LIBSSH_LIBRARY)
# learn libssh version
if(EXISTS ${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h)
set(LIBSSH_HEADER_PATH ${LIBSSH_INCLUDE_DIR}/libssh/libssh_version.h)
else()
set(LIBSSH_HEADER_PATH ${LIBSSH_INCLUDE_DIR}/libssh/libssh.h)
endif()
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_MAJOR
REGEX "#define[ ]+LIBSSH_VERSION_MAJOR[ ]+[0-9]+")
if(NOT LIBSSH_VERSION_MAJOR)
message(STATUS "LIBSSH_VERSION_MAJOR not found, assuming libssh is too old and cannot be used!")
set(LIBSSH_INCLUDE_DIR "LIBSSH_INCLUDE_DIR-NOTFOUND")
set(LIBSSH_LIBRARY "LIBSSH_LIBRARY-NOTFOUND")
else()
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MAJOR ${LIBSSH_VERSION_MAJOR})
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_MINOR
REGEX "#define[ ]+LIBSSH_VERSION_MINOR[ ]+[0-9]+")
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_MINOR ${LIBSSH_VERSION_MINOR})
file(STRINGS ${LIBSSH_HEADER_PATH} LIBSSH_VERSION_PATCH
REGEX "#define[ ]+LIBSSH_VERSION_MICRO[ ]+[0-9]+")
string(REGEX MATCH "[0-9]+" LIBSSH_VERSION_PATCH ${LIBSSH_VERSION_PATCH})
set(LIBSSH_VERSION ${LIBSSH_VERSION_MAJOR}.${LIBSSH_VERSION_MINOR}.${LIBSSH_VERSION_PATCH})
if(LIBSSH_VERSION VERSION_LESS 0.8.0)
# libssh_threads also needs to be linked for these versions
string(REPLACE "libssh.so" "libssh_threads.so"
LIBSSH_THREADS_LIBRARY
${LIBSSH_LIBRARY}
)
string(REPLACE "libssh.dylib" "libssh_threads.dylib"
LIBSSH_THREADS_LIBRARY
${LIBSSH_THREADS_LIBRARY}
)
string(REPLACE "ssh.so" "ssh_threads.so"
LIBSSH_THREADS_LIBRARY
${LIBSSH_THREADS_LIBRARY}
)
endif()
endif()
endif()
set(LIBSSH_INCLUDE_DIRS ${LIBSSH_INCLUDE_DIR})
set(LIBSSH_LIBRARIES ${LIBSSH_LIBRARY} ${LIBSSH_THREADS_LIBRARY})
mark_as_advanced(LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES)
find_package_handle_standard_args(LibSSH FOUND_VAR LIBSSH_FOUND
REQUIRED_VARS LIBSSH_INCLUDE_DIRS LIBSSH_LIBRARIES
VERSION_VAR LIBSSH_VERSION)
endif()

View File

@@ -7,7 +7,7 @@ GET_FILENAME_COMPONENT(inputBase ${input} NAME)
STRING(REGEX REPLACE "[^a-zA-Z0-9]" "_" funcName "${inputBase}")
SET(funcName "GetResource_${funcName}")
FILE(WRITE "${output}" "#include <stddef.h>\n#include <wpi/StringRef.h>\nextern \"C\" {\nstatic const unsigned char contents[] = {")
FILE(WRITE "${output}" "#include <stddef.h>\n#include <string_view>\nextern \"C\" {\nstatic const unsigned char contents[] = {")
STRING(REGEX MATCHALL ".." outputData "${fileHex}")
STRING(REGEX REPLACE ";" ", 0x" outputData "${outputData}")
@@ -17,7 +17,7 @@ FILE(APPEND "${output}" "const unsigned char* ${prefix}${funcName}(size_t* len)
IF(NOT namespace STREQUAL "")
FILE(APPEND "${output}" "namespace ${namespace} {\n")
ENDIF()
FILE(APPEND "${output}" "wpi::StringRef ${funcName}() {\n return wpi::StringRef(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
FILE(APPEND "${output}" "std::string_view ${funcName}() {\n return std::string_view(reinterpret_cast<const char*>(contents), ${fileSize});\n}\n")
IF(NOT namespace STREQUAL "")
FILE(APPEND "${output}" "}\n")
ENDIF()

View File

@@ -1,4 +1,4 @@
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
set(GNU_MACHINE "arm-frc2021-linux-gnueabi" CACHE STRING "GNU compiler triple")
set(GNU_MACHINE "arm-frc2022-linux-gnueabi" CACHE STRING "GNU compiler triple")
set(SOFTFP yes)
include("${CMAKE_CURRENT_LIST_DIR}/arm.toolchain.cmake")

View File

@@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 2.8)
# load settings in case of "try compile"
set(TOOLCHAIN_CONFIG_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
set(TOOLCHAIN_CONFIG_FILE "${WPILIB_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain.config.cmake")
get_property(__IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE)
if(__IN_TRY_COMPILE)
include("${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake" OPTIONAL) # CMAKE_BINARY_DIR is different
include("${CMAKE_CURRENT_SOURCE_DIR}/../toolchain.config.cmake" OPTIONAL) # WPILIB_BINARY_DIR is different
macro(toolchain_save_config)
# nothing
endmacro()

View File

@@ -0,0 +1,119 @@
import org.gradle.language.base.internal.ProjectLayout
import edu.wpi.first.deployutils.deploy.target.RemoteTarget
import edu.wpi.first.deployutils.deploy.target.location.SshDeployLocation
import edu.wpi.first.deployutils.deploy.artifact.*
import org.gradle.internal.os.OperatingSystem
apply plugin: 'cpp'
apply plugin: 'visual-studio'
apply plugin: 'edu.wpi.first.NativeUtils'
apply plugin: ExtraTasks
apply plugin: 'edu.wpi.first.DeployUtils'
apply from: '../shared/config.gradle'
ext {
sharedCvConfigs = [crossConnIntegrationTests: []]
staticCvConfigs = [:]
useJava = false
useCpp = true
staticGtestConfigs = [crossConnIntegrationTests: []]
}
apply from: "${rootDir}/shared/opencv.gradle"
apply from: "${rootDir}/shared/googletest.gradle"
deploy {
targets {
roborio(RemoteTarget) {
directory = '/home/admin'
maxChannels = 4
locations {
ssh(SshDeployLocation) {
address = "172.22.11.2"
user = 'admin'
password = ''
ipv6 = false
}
}
artifacts {
all {
predeploy << { ctx ->
ctx.execute('/usr/local/frc/bin/frcKillRobot.sh -t')
}
postdeploy << { ctx ->
ctx.execute("sync")
ctx.execute("ldconfig")
}
}
crossConnIntegrationTests(NativeExecutableArtifact) {
libraryDirectory = '/usr/local/frc/third-party/lib'
postdeploy << { ctx ->
ctx.execute('chmod +x crossConnIntegrationTests')
}
}
}
}
}
}
model {
components {
crossConnIntegrationTests(NativeExecutableSpec) {
targetBuildTypes 'debug'
nativeUtils.useRequiredLibrary(it, 'googletest_static')
binaries.all { binary ->
if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
if (binary.buildType.name == 'debug') {
deploy.targets.roborio.artifacts.crossConnIntegrationTests.binary = binary
}
binary.sources {
athenaCpp(CppSourceSet) {
source {
srcDirs = ['src/main/native/cpp']
includes = ['**/*.cpp']
}
exportedHeaders {
srcDirs = ['src/main/native/include']
includes = ['**/*.h']
}
}
}
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: ':wpiutil', library: 'wpiutil', linkage: 'shared'
if (binary.targetPlatform.name == nativeUtils.wpi.platforms.roborio) {
nativeUtils.useRequiredLibrary(binary, 'ni_link_libraries', 'ni_runtime_libraries')
}
} else {
binary.sources {
simCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/dt'
includes = ['**/*.cpp']
}
}
}
}
}
}
}
}
tasks.register('deployTests') {
try {
dependsOn tasks.named('deployCrossConnIntegrationTestsLibrariesRoborio')
dependsOn tasks.named('deployCrossConnIntegrationTestsRoborio')
} catch (ignored) {
}
}

View File

@@ -0,0 +1,112 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <hal/AnalogInput.h>
#include <hal/AnalogOutput.h>
#include <wpi/SmallVector.h>
#include "CrossConnects.h"
#include "LifetimeWrappers.h"
#include "gtest/gtest.h"
using namespace hlt;
class AnalogCrossTest : public ::testing::TestWithParam<std::pair<int, int>> {};
TEST_P(AnalogCrossTest, AnalogCross) {
auto param = GetParam();
int32_t status = 0;
AnalogInputHandle input{param.first, &status};
ASSERT_EQ(0, status);
AnalogOutputHandle output{param.second, &status};
ASSERT_EQ(0, status);
for (double i = 0; i < 5; i += 0.1) {
HAL_SetAnalogOutput(output, i, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_NEAR(i, HAL_GetAnalogVoltage(input, &status), 0.01);
ASSERT_EQ(0, status);
}
for (double i = 5; i > 0; i -= 0.1) {
HAL_SetAnalogOutput(output, i, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_NEAR(i, HAL_GetAnalogVoltage(input, &status), 0.01);
ASSERT_EQ(0, status);
}
}
TEST(AnalogInputTest, AllocateAll) {
wpi::SmallVector<AnalogInputHandle, 21> analogHandles;
for (int i = 0; i < HAL_GetNumAnalogInputs(); i++) {
int32_t status = 0;
analogHandles.emplace_back(AnalogInputHandle(i, &status));
ASSERT_EQ(status, 0);
}
}
TEST(AnalogInputTest, MultipleAllocateFails) {
int32_t status = 0;
AnalogInputHandle handle(0, &status);
ASSERT_NE(handle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
AnalogInputHandle handle2(0, &status);
ASSERT_EQ(handle2, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
TEST(AnalogInputTest, OverAllocateFails) {
int32_t status = 0;
AnalogInputHandle handle(HAL_GetNumAnalogInputs(), &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(AnalogInputTest, UnderAllocateFails) {
int32_t status = 0;
AnalogInputHandle handle(-1, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(AnalogOutputTest, AllocateAll) {
wpi::SmallVector<AnalogOutputHandle, 21> analogHandles;
for (int i = 0; i < HAL_GetNumAnalogOutputs(); i++) {
int32_t status = 0;
analogHandles.emplace_back(AnalogOutputHandle(i, &status));
ASSERT_EQ(status, 0);
}
}
TEST(AnalogOutputTest, MultipleAllocateFails) {
int32_t status = 0;
AnalogOutputHandle handle(0, &status);
ASSERT_NE(handle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
AnalogOutputHandle handle2(0, &status);
ASSERT_EQ(handle2, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
TEST(AnalogOutputTest, OverAllocateFails) {
int32_t status = 0;
AnalogOutputHandle handle(HAL_GetNumAnalogOutputs(), &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(AnalogOutputTest, UnderAllocateFails) {
int32_t status = 0;
AnalogOutputHandle handle(-1, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
INSTANTIATE_TEST_SUITE_P(AnalogCrossConnectsTests, AnalogCrossTest,
::testing::ValuesIn(AnalogCrossConnects));

View File

@@ -0,0 +1,101 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <hal/DIO.h>
#include <wpi/SmallVector.h>
#include "CrossConnects.h"
#include "LifetimeWrappers.h"
#include "gtest/gtest.h"
using namespace hlt;
class DIOTest : public ::testing::TestWithParam<std::pair<int, int>> {};
TEST_P(DIOTest, DIOCross) {
auto param = GetParam();
int32_t status = 0;
DIOHandle first{param.first, false, &status};
ASSERT_EQ(0, status);
DIOHandle second{param.second, true, &status};
ASSERT_EQ(0, status);
HAL_SetDIO(first, false, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_FALSE(HAL_GetDIO(first, &status));
ASSERT_EQ(0, status);
ASSERT_FALSE(HAL_GetDIO(second, &status));
ASSERT_EQ(0, status);
HAL_SetDIO(first, true, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_TRUE(HAL_GetDIO(second, &status));
ASSERT_EQ(0, status);
HAL_SetDIODirection(first, true, &status);
ASSERT_EQ(0, status);
HAL_SetDIODirection(second, false, &status);
ASSERT_EQ(0, status);
HAL_SetDIO(second, false, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_FALSE(HAL_GetDIO(first, &status));
ASSERT_EQ(0, status);
HAL_SetDIO(second, true, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_TRUE(HAL_GetDIO(first, &status));
ASSERT_EQ(0, status);
}
TEST(DIOTest, AllocateAll) {
wpi::SmallVector<DIOHandle, 32> dioHandles;
for (int i = 0; i < HAL_GetNumDigitalChannels(); i++) {
int32_t status = 0;
dioHandles.emplace_back(i, true, &status);
ASSERT_EQ(status, 0);
}
}
TEST(DIOTest, MultipleAllocateFails) {
int32_t status = 0;
DIOHandle handle(0, true, &status);
ASSERT_NE(handle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
DIOHandle handle2(0, true, &status);
ASSERT_EQ(handle2, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
TEST(DIOTest, OverAllocateFails) {
int32_t status = 0;
DIOHandle handle(HAL_GetNumDigitalChannels(), true, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(DIOTest, UnderAllocateFails) {
int32_t status = 0;
DIOHandle handle(-1, true, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(DIOTest, CrossAllocationFails) {
int32_t status = 0;
PWMHandle pwmHandle(10, &status);
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
DIOHandle handle(10, true, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
INSTANTIATE_TEST_SUITE_P(DIOCrossConnectsTests, DIOTest,
::testing::ValuesIn(DIOCrossConnects));

View File

@@ -0,0 +1,51 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <hal/HAL.h>
#include "CrossConnects.h"
#include "LifetimeWrappers.h"
#include "gtest/gtest.h"
using namespace hlt;
class DutyCycleTest : public ::testing::TestWithParam<std::pair<int, int>> {};
TEST_P(DutyCycleTest, DutyCycle) {
auto param = GetParam();
int32_t status = 0;
PWMHandle pwmHandle(param.first, &status);
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
ASSERT_EQ(0, status);
// Ensure our PWM is disabled, and set up properly
HAL_SetPWMRaw(pwmHandle, 0, &status);
ASSERT_EQ(0, status);
HAL_SetPWMConfig(pwmHandle, 2.0, 1.0, 1.0, 0, 0, &status);
HAL_SetPWMConfig(pwmHandle, 5.05, 2.525, 2.525, 2.525, 0, &status);
ASSERT_EQ(0, status);
HAL_SetPWMPeriodScale(pwmHandle, 0, &status);
ASSERT_EQ(0, status);
DIOHandle dioHandle{param.second, true, &status};
ASSERT_EQ(0, status);
DutyCycleHandle dutyCycle{dioHandle, &status};
ASSERT_EQ(0, status);
HAL_SetPWMSpeed(pwmHandle, 0.5, &status);
ASSERT_EQ(0, status);
// Sleep enough time for the frequency to converge
usleep(3500000);
ASSERT_NEAR(1000 / 5.05,
(double)HAL_GetDutyCycleFrequency(dutyCycle, &status), 1);
// TODO measure output
}
INSTANTIATE_TEST_SUITE_P(DutyCycleCrossConnTests, DutyCycleTest,
::testing::ValuesIn(PWMCrossConnects));

View File

@@ -0,0 +1,10 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "gtest/gtest.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,357 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <atomic>
#include <thread>
#include <hal/DMA.h>
#include <hal/HAL.h>
#include <wpi/SmallVector.h>
#include <wpi/condition_variable.h>
#include <wpi/priority_mutex.h>
#include "CrossConnects.h"
#include "LifetimeWrappers.h"
#include "gtest/gtest.h"
using namespace hlt;
class PWMTest : public ::testing::TestWithParam<std::pair<int, int>> {};
void TestTimingDMA(int squelch, std::pair<int, int> param) {
// Initialize DMA
int32_t status = 0;
DMAHandle dmaHandle(&status);
ASSERT_NE(dmaHandle, HAL_kInvalidHandle);
ASSERT_EQ(0, status);
status = 0;
PWMHandle pwmHandle(param.first, &status);
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
ASSERT_EQ(0, status);
// Ensure our PWM is disabled, and set up properly
HAL_SetPWMRaw(pwmHandle, 0, &status);
HAL_SetPWMConfig(pwmHandle, 2.0, 1.0, 1.0, 0, 0, &status);
HAL_SetPWMPeriodScale(pwmHandle, squelch, &status);
unsigned int checkPeriod = 0;
switch (squelch) {
case (0):
checkPeriod = 5050;
break;
case (1):
checkPeriod = 10100;
break;
case (3):
checkPeriod = 20200;
break;
}
status = 0;
DIOHandle dioHandle(param.second, true, &status);
ASSERT_NE(dioHandle, HAL_kInvalidHandle);
HAL_AddDMADigitalSource(dmaHandle, dioHandle, &status);
ASSERT_EQ(0, status);
HAL_SetDMAExternalTrigger(dmaHandle, dioHandle,
HAL_AnalogTriggerType::HAL_Trigger_kInWindow, true,
true, &status);
ASSERT_EQ(0, status);
// Loop to test 5 speeds
for (unsigned int testWidth = 1000; testWidth < 2100; testWidth += 250) {
HAL_StartDMA(dmaHandle, 1024, &status);
ASSERT_EQ(0, status);
while (true) {
int32_t remaining = 0;
HAL_DMASample testSample;
HAL_ReadDMA(dmaHandle, &testSample, 0.01, &remaining, &status);
if (remaining == 0) {
break;
}
}
HAL_SetPWMSpeed(pwmHandle, (testWidth - 1000) / 1000.0, &status);
constexpr const int kSampleCount = 15;
HAL_DMASample dmaSamples[kSampleCount];
int readCount = 0;
while (readCount < kSampleCount) {
status = 0;
int32_t remaining = 0;
HAL_DMAReadStatus readStatus = HAL_ReadDMA(
dmaHandle, &dmaSamples[readCount], 1.0, &remaining, &status);
ASSERT_EQ(0, status);
ASSERT_EQ(HAL_DMAReadStatus::HAL_DMA_OK, readStatus);
readCount++;
}
HAL_SetPWMSpeed(pwmHandle, 0, &status);
HAL_StopDMA(dmaHandle, &status);
// Find first rising edge
int startIndex = 4;
while (startIndex < 6) {
status = 0;
auto value = HAL_GetDMASampleDigitalSource(&dmaSamples[startIndex],
dioHandle, &status);
ASSERT_EQ(0, status);
if (value)
break;
startIndex++;
}
ASSERT_LT(startIndex, 6);
// Check that samples alternate
bool previous = false;
int iterationCount = 0;
for (int i = startIndex; i < startIndex + 8; i++) {
auto value =
HAL_GetDMASampleDigitalSource(&dmaSamples[i], dioHandle, &status);
ASSERT_EQ(0, status);
ASSERT_NE(previous, value);
previous = !previous;
iterationCount++;
}
ASSERT_EQ(iterationCount, 8);
iterationCount = 0;
// Check width between samples
for (int i = startIndex; i < startIndex + 8; i += 2) {
auto width = HAL_GetDMASampleTime(&dmaSamples[i + 1], &status) -
HAL_GetDMASampleTime(&dmaSamples[i], &status);
ASSERT_NEAR(testWidth, width, 10);
iterationCount++;
}
ASSERT_EQ(iterationCount, 4);
iterationCount = 0;
// Check period between samples
for (int i = startIndex; i < startIndex + 6; i += 2) {
auto period = HAL_GetDMASampleTime(&dmaSamples[i + 2], &status) -
HAL_GetDMASampleTime(&dmaSamples[i], &status);
ASSERT_NEAR(checkPeriod, period, 10);
iterationCount++;
}
ASSERT_EQ(iterationCount, 3);
}
}
struct InterruptCheckData {
wpi::SmallVector<uint64_t, 8> risingStamps;
wpi::SmallVector<uint64_t, 8> fallingStamps;
wpi::priority_mutex mutex;
wpi::condition_variable cond;
HAL_InterruptHandle handle;
};
// TODO switch this to DMA
void TestTiming(int squelch, std::pair<int, int> param) {
// Initialize interrupt
int32_t status = 0;
InterruptHandle interruptHandle(&status);
// Ensure we have a valid interrupt handle
ASSERT_NE(interruptHandle, HAL_kInvalidHandle);
status = 0;
PWMHandle pwmHandle(param.first, &status);
ASSERT_NE(pwmHandle, HAL_kInvalidHandle);
// Ensure our PWM is disabled, and set up properly
HAL_SetPWMRaw(pwmHandle, 0, &status);
HAL_SetPWMConfig(pwmHandle, 2.0, 1.0, 1.0, 0, 0, &status);
HAL_SetPWMPeriodScale(pwmHandle, squelch, &status);
unsigned int checkPeriod = 0;
switch (squelch) {
case (0):
checkPeriod = 5050;
break;
case (1):
checkPeriod = 10100;
break;
case (3):
checkPeriod = 20200;
break;
}
status = 0;
DIOHandle dioHandle(param.second, true, &status);
ASSERT_NE(dioHandle, HAL_kInvalidHandle);
InterruptCheckData interruptData;
interruptData.handle = interruptHandle;
// Can use any type for the interrupt handle
HAL_RequestInterrupts(interruptHandle, dioHandle,
HAL_AnalogTriggerType::HAL_Trigger_kInWindow, &status);
HAL_SetInterruptUpSourceEdge(interruptHandle, true, true, &status);
// Loop to test 5 speeds
for (unsigned int i = 1000; i < 2100; i += 250) {
interruptData.risingStamps.clear();
interruptData.fallingStamps.clear();
std::atomic_bool runThread{true};
status = 0;
std::thread interruptThread([&]() {
while (runThread) {
int32_t threadStatus = 0;
auto mask =
HAL_WaitForInterrupt(interruptHandle, 5, true, &threadStatus);
if ((mask & 0x100) == 0x100 && interruptData.risingStamps.size() == 0 &&
interruptData.fallingStamps.size() == 0) {
// Falling edge at start of tracking. Skip
continue;
}
int32_t status = 0;
if ((mask & 0x1) == 0x1) {
auto ts = HAL_ReadInterruptRisingTimestamp(interruptHandle, &status);
// Rising Edge
interruptData.risingStamps.push_back(ts);
} else if ((mask & 0x100) == 0x100) {
auto ts = HAL_ReadInterruptFallingTimestamp(interruptHandle, &status);
// Falling Edge
interruptData.fallingStamps.push_back(ts);
}
if (interruptData.risingStamps.size() >= 4 &&
interruptData.fallingStamps.size() >= 4) {
interruptData.cond.notify_all();
runThread = false;
break;
}
}
});
// Ensure our interrupt actually got created correctly.
ASSERT_EQ(status, 0);
HAL_SetPWMSpeed(pwmHandle, (i - 1000) / 1000.0, &status);
ASSERT_EQ(status, 0);
{
std::unique_lock<wpi::priority_mutex> lock(interruptData.mutex);
// Wait for lock
// TODO: Add Timeout
auto timeout = interruptData.cond.wait_for(lock, std::chrono::seconds(2));
if (timeout == std::cv_status::timeout) {
runThread = false;
if (interruptThread.joinable()) {
interruptThread.join();
}
ASSERT_TRUE(false); // Exit test as failure on timeout
}
}
HAL_SetPWMRaw(pwmHandle, 0, &status);
// Ensure our interrupts have the proper counts
ASSERT_EQ(interruptData.risingStamps.size(),
interruptData.fallingStamps.size());
ASSERT_GT(interruptData.risingStamps.size(), 0u);
ASSERT_EQ(interruptData.risingStamps.size() % 2, 0u);
ASSERT_EQ(interruptData.fallingStamps.size() % 2, 0u);
for (size_t j = 0; j < interruptData.risingStamps.size(); j++) {
uint64_t width =
interruptData.fallingStamps[j] - interruptData.risingStamps[j];
ASSERT_NEAR(width, i, 10);
}
for (unsigned int j = 0; j < interruptData.risingStamps.size() - 1; j++) {
uint64_t period =
interruptData.risingStamps[j + 1] - interruptData.risingStamps[j];
ASSERT_NEAR(period, checkPeriod, 10);
}
runThread = false;
if (interruptThread.joinable()) {
interruptThread.join();
}
}
}
TEST_P(PWMTest, Timing4x) {
auto param = GetParam();
TestTiming(3, param);
}
TEST_P(PWMTest, Timing2x) {
auto param = GetParam();
TestTiming(1, param);
}
TEST_P(PWMTest, Timing1x) {
auto param = GetParam();
TestTiming(0, param);
}
TEST_P(PWMTest, TimingDMA4x) {
auto param = GetParam();
TestTimingDMA(3, param);
}
TEST_P(PWMTest, TimingDMA2x) {
auto param = GetParam();
TestTimingDMA(1, param);
}
TEST_P(PWMTest, TimingDMA1x) {
auto param = GetParam();
TestTimingDMA(0, param);
}
TEST(PWMTest, AllocateAll) {
wpi::SmallVector<PWMHandle, 21> pwmHandles;
for (int i = 0; i < HAL_GetNumPWMChannels(); i++) {
int32_t status = 0;
pwmHandles.emplace_back(PWMHandle(i, &status));
ASSERT_EQ(status, 0);
}
}
TEST(PWMTest, MultipleAllocateFails) {
int32_t status = 0;
PWMHandle handle(0, &status);
ASSERT_NE(handle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
PWMHandle handle2(0, &status);
ASSERT_EQ(handle2, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
TEST(PWMTest, OverAllocateFails) {
int32_t status = 0;
PWMHandle handle(HAL_GetNumPWMChannels(), &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(PWMTest, UnderAllocateFails) {
int32_t status = 0;
PWMHandle handle(-1, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(PWMTest, CrossAllocationFails) {
int32_t status = 0;
DIOHandle dioHandle(10, true, &status);
ASSERT_NE(dioHandle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
PWMHandle handle(10, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
INSTANTIATE_TEST_SUITE_P(PWMCrossConnectTests, PWMTest,
::testing::ValuesIn(PWMCrossConnects));

View File

@@ -0,0 +1,50 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <hal/AnalogInput.h>
#include <hal/Relay.h>
#include <wpi/SmallVector.h>
#include "CrossConnects.h"
#include "LifetimeWrappers.h"
#include "gtest/gtest.h"
using namespace hlt;
class RelayAnalogTest : public ::testing::TestWithParam<std::pair<int, int>> {};
TEST_P(RelayAnalogTest, RelayAnalogCross) {
auto param = GetParam();
int32_t status = 0;
RelayHandle relay{param.first, true, &status};
ASSERT_EQ(0, status);
AnalogInputHandle analog{param.second, &status};
ASSERT_EQ(0, status);
AnalogTriggerHandle trigger{analog, &status};
ASSERT_EQ(0, status);
HAL_SetAnalogTriggerLimitsVoltage(trigger, 1.5, 3.0, &status);
ASSERT_EQ(0, status);
HAL_SetRelay(relay, false, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_FALSE(HAL_GetAnalogTriggerTriggerState(trigger, &status));
ASSERT_EQ(0, status);
HAL_SetRelay(relay, true, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_TRUE(HAL_GetAnalogTriggerTriggerState(trigger, &status));
ASSERT_EQ(0, status);
HAL_SetRelay(relay, false, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_FALSE(HAL_GetAnalogTriggerTriggerState(trigger, &status));
ASSERT_EQ(0, status);
}
INSTANTIATE_TEST_SUITE_P(RelayAnalogCrossConnectsTests, RelayAnalogTest,
::testing::ValuesIn(RelayAnalogCrossConnects));

View File

@@ -0,0 +1,104 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <hal/Relay.h>
#include <wpi/SmallVector.h>
#include "CrossConnects.h"
#include "LifetimeWrappers.h"
#include "gtest/gtest.h"
using namespace hlt;
class RelayDigitalTest : public ::testing::TestWithParam<RelayCross> {};
TEST_P(RelayDigitalTest, RelayCross) {
auto param = GetParam();
int32_t status = 0;
RelayHandle fwd{param.Relay, true, &status};
ASSERT_EQ(0, status);
RelayHandle rev{param.Relay, false, &status};
ASSERT_EQ(0, status);
DIOHandle fwdInput{param.FwdDio, true, &status};
ASSERT_EQ(0, status);
DIOHandle revInput{param.RevDio, true, &status};
ASSERT_EQ(0, status);
HAL_SetRelay(fwd, false, &status);
ASSERT_EQ(0, status);
HAL_SetRelay(rev, false, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_FALSE(HAL_GetDIO(fwdInput, &status));
ASSERT_EQ(0, status);
ASSERT_FALSE(HAL_GetDIO(revInput, &status));
ASSERT_EQ(0, status);
HAL_SetRelay(fwd, false, &status);
ASSERT_EQ(0, status);
HAL_SetRelay(rev, true, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_FALSE(HAL_GetDIO(fwdInput, &status));
ASSERT_EQ(0, status);
ASSERT_TRUE(HAL_GetDIO(revInput, &status));
ASSERT_EQ(0, status);
HAL_SetRelay(fwd, true, &status);
ASSERT_EQ(0, status);
HAL_SetRelay(rev, false, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_TRUE(HAL_GetDIO(fwdInput, &status));
ASSERT_EQ(0, status);
ASSERT_FALSE(HAL_GetDIO(revInput, &status));
ASSERT_EQ(0, status);
HAL_SetRelay(fwd, true, &status);
ASSERT_EQ(0, status);
HAL_SetRelay(rev, true, &status);
ASSERT_EQ(0, status);
usleep(1000);
ASSERT_TRUE(HAL_GetDIO(fwdInput, &status));
ASSERT_EQ(0, status);
ASSERT_TRUE(HAL_GetDIO(revInput, &status));
ASSERT_EQ(0, status);
}
TEST(RelayDigitalTest, AllocateAll) {
wpi::SmallVector<RelayHandle, 32> relayHandles;
for (int i = 0; i < HAL_GetNumRelayChannels(); i++) {
int32_t status = 0;
relayHandles.emplace_back(i / 2, i % 2, &status);
ASSERT_EQ(status, 0);
}
}
TEST(RelayDigitalTest, MultipleAllocateFails) {
int32_t status = 0;
RelayHandle handle(0, true, &status);
ASSERT_NE(handle, HAL_kInvalidHandle);
ASSERT_EQ(status, 0);
RelayHandle handle2(0, true, &status);
ASSERT_EQ(handle2, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_IS_ALLOCATED);
}
TEST(RelayDigitalTest, OverAllocateFails) {
int32_t status = 0;
RelayHandle handle(HAL_GetNumRelayChannels(), true, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
TEST(RelayDigitalTest, UnderAllocateFails) {
int32_t status = 0;
RelayHandle handle(-1, true, &status);
ASSERT_EQ(handle, HAL_kInvalidHandle);
ASSERT_LAST_ERROR_STATUS(status, RESOURCE_OUT_OF_RANGE);
}
INSTANTIATE_TEST_SUITE_P(RelayDigitalCrossConnectsTests, RelayDigitalTest,
::testing::ValuesIn(RelayCrossConnects));

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.
#include <cstdlib>
#include <thread>
#include <fmt/core.h>
#include <hal/HAL.h>
#include "gtest/gtest.h"
#include "mockds/MockDS.h"
using namespace std::chrono_literals;
class TestEnvironment : public testing::Environment {
bool m_alreadySetUp = false;
MockDS m_mockDS;
public:
TestEnvironment() {
// Only set up once. This allows gtest_repeat to be used to automatically
// repeat tests.
if (m_alreadySetUp) {
return;
}
m_alreadySetUp = true;
if (!HAL_Initialize(500, 0)) {
fmt::print(stderr, "FATAL ERROR: HAL could not be initialized\n");
std::exit(-1);
}
m_mockDS.Start();
// This sets up the network communications library to enable the driver
// station. After starting network coms, it will loop until the driver
// station returns that the robot is enabled, to ensure that tests will be
// able to run on the hardware.
HAL_ObserveUserProgramStarting();
fmt::print("Started coms\n");
int enableCounter = 0;
auto checkEnabled = []() {
HAL_ControlWord controlWord;
std::memset(&controlWord, 0, sizeof(controlWord));
HAL_GetControlWord(&controlWord);
return controlWord.enabled && controlWord.dsAttached;
};
while (!checkEnabled()) {
if (enableCounter > 50) {
// Robot did not enable properly after 5 seconds.
// Force exit
fmt::print(stderr, " Failed to enable. Aborting\n");
std::terminate();
}
std::this_thread::sleep_for(100ms);
fmt::print("Waiting for enable: {}\n", enableCounter++);
}
std::this_thread::sleep_for(500ms);
}
~TestEnvironment() override { m_mockDS.Stop(); }
};
testing::Environment* const environment =
testing::AddGlobalTestEnvironment(new TestEnvironment);

View File

@@ -0,0 +1,86 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "MockDS.h"
#include <stdint.h>
#include <string_view>
#include <fmt/core.h>
#include <hal/cpp/fpga_clock.h>
#include <wpi/Logger.h>
#include <wpi/SmallVector.h>
#include <wpi/UDPClient.h>
static void LoggerFunc(unsigned int level, const char* file, unsigned int line,
const char* msg) {
if (level == 20) {
fmt::print(stderr, "DS: {}\n", msg);
return;
}
std::string_view levelmsg;
if (level >= 50) {
levelmsg = "CRITICAL";
} else if (level >= 40) {
levelmsg = "ERROR";
} else if (level >= 30) {
levelmsg = "WARNING";
} else {
return;
}
fmt::print(stderr, "DS: {}: {} ({}:{})\n", levelmsg, msg, file, line);
}
static void generateEnabledDsPacket(wpi::SmallVectorImpl<uint8_t>& data,
uint16_t sendCount) {
data.clear();
data.push_back(sendCount >> 8);
data.push_back(sendCount);
data.push_back(0x01); // general data tag
data.push_back(0x04); // teleop enabled
data.push_back(0x10); // normal data request
data.push_back(0x00); // red 1 station
}
void MockDS::Start() {
if (m_active) {
return;
}
m_active = true;
m_thread = std::thread([&]() {
wpi::Logger logger(LoggerFunc);
wpi::UDPClient client(logger);
client.start();
auto timeout_time = hal::fpga_clock::now();
int initCount = 0;
uint16_t sendCount = 0;
wpi::SmallVector<uint8_t, 8> data;
while (m_active) {
// Keep 20ms intervals, and increase time to next interval
auto current = hal::fpga_clock::now();
while (timeout_time <= current) {
timeout_time += std::chrono::milliseconds(20);
}
std::this_thread::sleep_until(timeout_time);
generateEnabledDsPacket(data, sendCount++);
// ~10 disabled packets are required to make the robot actually enable
// 1 is definitely not enough.
if (initCount < 10) {
initCount++;
data[3] = 0;
}
client.send(data, "127.0.0.1", 1110);
}
client.shutdown();
});
}
void MockDS::Stop() {
m_active = false;
if (m_thread.joinable()) {
m_thread.join();
}
}

View File

@@ -0,0 +1,23 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <atomic>
#include <thread>
class MockDS {
public:
MockDS() = default;
~MockDS() { Stop(); }
MockDS(const MockDS& other) = delete;
MockDS& operator=(const MockDS& other) = delete;
void Start();
void Stop();
private:
std::thread m_thread;
std::atomic_bool m_active{false};
};

View File

@@ -0,0 +1,5 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
int main() {}

View File

@@ -0,0 +1,62 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <array>
#include <utility>
namespace hlt {
constexpr static std::array<std::pair<int, int>, 22> DIOCrossConnects{
std::pair{20, 25},
std::pair{19, 24},
std::pair{17, 13},
std::pair{16, 12},
std::pair{15, 11},
std::pair{14, 10},
std::pair{26, 2},
std::pair{27, 1},
std::pair{28, 0},
std::pair{29, 3},
std::pair{30, 4},
// Opposite direction
std::pair{25, 20},
std::pair{24, 19},
std::pair{13, 17},
std::pair{12, 16},
std::pair{11, 15},
std::pair{10, 14},
std::pair{2, 26},
std::pair{1, 27},
std::pair{0, 28},
std::pair{3, 29},
std::pair{4, 30},
};
// PWM on left, DIO on right
constexpr static std::array<std::pair<int, int>, 2> PWMCrossConnects{
std::pair{0, 18},
std::pair{16, 25},
};
// FWD only, relay on left
constexpr static std::array<std::pair<int, int>, 2> RelayAnalogCrossConnects{
std::pair{2, 0}, std::pair{3, 1}};
struct RelayCross {
int Relay;
int FwdDio;
int RevDio;
};
constexpr static std::array<RelayCross, 1> RelayCrossConnects{
RelayCross{0, 23, 22}};
// input on left
constexpr static std::array<std::pair<int, int>, 2> AnalogCrossConnects{
std::pair{2, 0}, std::pair{4, 1}};
} // namespace hlt

View File

@@ -0,0 +1,200 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <hal/DMA.h>
#include <hal/DutyCycle.h>
#include <hal/HAL.h>
namespace hlt {
struct InterruptHandle {
public:
explicit InterruptHandle(int32_t* status) {
handle = HAL_InitializeInterrupts(status);
}
InterruptHandle(const InterruptHandle&) = delete;
InterruptHandle operator=(const InterruptHandle&) = delete;
InterruptHandle(InterruptHandle&&) = default;
InterruptHandle& operator=(InterruptHandle&&) = default;
~InterruptHandle() { HAL_CleanInterrupts(handle); }
operator HAL_InterruptHandle() const { return handle; }
private:
HAL_InterruptHandle handle = 0;
};
struct DMAHandle {
public:
explicit DMAHandle(int32_t* status) { handle = HAL_InitializeDMA(status); }
DMAHandle(const DMAHandle&) = delete;
DMAHandle operator=(const DMAHandle&) = delete;
DMAHandle(DMAHandle&&) = default;
DMAHandle& operator=(DMAHandle&&) = default;
~DMAHandle() { HAL_FreeDMA(handle); }
operator HAL_DMAHandle() const { return handle; }
private:
HAL_DMAHandle handle = 0;
};
struct AnalogInputHandle {
public:
AnalogInputHandle(int32_t port, int32_t* status) {
handle = HAL_InitializeAnalogInputPort(HAL_GetPort(port), nullptr, status);
}
AnalogInputHandle(const AnalogInputHandle&) = delete;
AnalogInputHandle operator=(const AnalogInputHandle&) = delete;
AnalogInputHandle(AnalogInputHandle&&) = default;
AnalogInputHandle& operator=(AnalogInputHandle&&) = default;
~AnalogInputHandle() { HAL_FreeAnalogInputPort(handle); }
operator HAL_AnalogInputHandle() const { return handle; }
private:
HAL_AnalogInputHandle handle = 0;
};
struct AnalogOutputHandle {
public:
AnalogOutputHandle(int32_t port, int32_t* status) {
handle = HAL_InitializeAnalogOutputPort(HAL_GetPort(port), nullptr, status);
}
AnalogOutputHandle(const AnalogOutputHandle&) = delete;
AnalogOutputHandle operator=(const AnalogOutputHandle&) = delete;
AnalogOutputHandle(AnalogOutputHandle&&) = default;
AnalogOutputHandle& operator=(AnalogOutputHandle&&) = default;
~AnalogOutputHandle() { HAL_FreeAnalogOutputPort(handle); }
operator HAL_AnalogOutputHandle() const { return handle; }
private:
HAL_AnalogOutputHandle handle = 0;
};
struct AnalogTriggerHandle {
public:
explicit AnalogTriggerHandle(HAL_AnalogInputHandle port, int32_t* status) {
handle = HAL_InitializeAnalogTrigger(port, status);
}
AnalogTriggerHandle(const AnalogTriggerHandle&) = delete;
AnalogTriggerHandle operator=(const AnalogTriggerHandle&) = delete;
AnalogTriggerHandle(AnalogTriggerHandle&&) = default;
AnalogTriggerHandle& operator=(AnalogTriggerHandle&&) = default;
~AnalogTriggerHandle() {
int32_t status = 0;
HAL_CleanAnalogTrigger(handle, &status);
}
operator HAL_AnalogTriggerHandle() const { return handle; }
private:
HAL_AnalogTriggerHandle handle = 0;
};
struct DutyCycleHandle {
public:
DutyCycleHandle(HAL_DigitalHandle port, int32_t* status) {
handle = HAL_InitializeDutyCycle(
port, HAL_AnalogTriggerType::HAL_Trigger_kInWindow, status);
}
DutyCycleHandle(const DutyCycleHandle&) = delete;
DutyCycleHandle operator=(const DutyCycleHandle&) = delete;
DutyCycleHandle(DutyCycleHandle&&) = default;
DutyCycleHandle& operator=(DutyCycleHandle&&) = default;
~DutyCycleHandle() { HAL_FreeDutyCycle(handle); }
operator HAL_DutyCycleHandle() const { return handle; }
private:
HAL_DutyCycleHandle handle = 0;
};
struct DIOHandle {
public:
DIOHandle() {}
DIOHandle(const DIOHandle&) = delete;
DIOHandle operator=(const DIOHandle&) = delete;
DIOHandle(DIOHandle&&) = default;
DIOHandle& operator=(DIOHandle&&) = default;
DIOHandle(int32_t port, HAL_Bool input, int32_t* status) {
handle = HAL_InitializeDIOPort(HAL_GetPort(port), input, nullptr, status);
}
~DIOHandle() { HAL_FreeDIOPort(handle); }
operator HAL_DigitalHandle() const { return handle; }
private:
HAL_DigitalHandle handle = 0;
};
struct PWMHandle {
public:
PWMHandle() {}
PWMHandle(const PWMHandle&) = delete;
PWMHandle operator=(const PWMHandle&) = delete;
PWMHandle(PWMHandle&&) = default;
PWMHandle& operator=(PWMHandle&&) = default;
PWMHandle(int32_t port, int32_t* status) {
handle = HAL_InitializePWMPort(HAL_GetPort(port), nullptr, status);
}
~PWMHandle() {
int32_t status = 0;
HAL_FreePWMPort(handle, &status);
}
operator HAL_DigitalHandle() const { return handle; }
private:
HAL_DigitalHandle handle = 0;
};
struct RelayHandle {
public:
RelayHandle(int32_t port, HAL_Bool fwd, int32_t* status) {
handle = HAL_InitializeRelayPort(HAL_GetPort(port), fwd, nullptr, status);
}
RelayHandle(const RelayHandle&) = delete;
RelayHandle operator=(const RelayHandle&) = delete;
RelayHandle(RelayHandle&&) = default;
RelayHandle& operator=(RelayHandle&&) = default;
~RelayHandle() { HAL_FreeRelayPort(handle); }
operator HAL_RelayHandle() const { return handle; }
private:
HAL_RelayHandle handle = 0;
};
#define ASSERT_LAST_ERROR_STATUS(status, x) \
do { \
ASSERT_EQ(status, HAL_USE_LAST_ERROR); \
const char* lastErrorMessageInMacro = HAL_GetLastError(&status); \
ASSERT_EQ(status, x); \
} while (0)
} // namespace hlt

View File

@@ -31,6 +31,7 @@ repoRootNameOverride {
}
includeOtherLibs {
^fmt/
^opencv2/
^support/
^tcpsockets/

View File

@@ -46,8 +46,8 @@ else()
set (cscore_config_dir share/cscore)
endif()
configure_file(cscore-config.cmake.in ${CMAKE_BINARY_DIR}/cscore-config.cmake )
install(FILES ${CMAKE_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
configure_file(cscore-config.cmake.in ${WPILIB_BINARY_DIR}/cscore-config.cmake )
install(FILES ${WPILIB_BINARY_DIR}/cscore-config.cmake DESTINATION ${cscore_config_dir})
install(EXPORT cscore DESTINATION ${cscore_config_dir})
SUBDIR_LIST(cscore_examples "${CMAKE_CURRENT_SOURCE_DIR}/examples")
@@ -79,7 +79,7 @@ if (WITH_JAVA)
find_package(Java REQUIRED)
find_package(JNI REQUIRED)
include(UseJava)
set(CMAKE_JAVA_COMPILE_FLAGS "-Xlint:unchecked")
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding" "UTF8" "-Xlint:unchecked")
#find java files, copy them locally
@@ -87,11 +87,11 @@ if (WITH_JAVA)
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
endif()
find_file(OPENCV_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin NO_DEFAULT_PATH)
find_file(OPENCV_JAR_FILE NAMES opencv-${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.jar PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/share/java NO_DEFAULT_PATH)
find_file(OPENCV_JNI_FILE NAMES libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dylib
opencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.dll
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib NO_DEFAULT_PATH)
PATHS ${OPENCV_JAVA_INSTALL_DIR} ${OpenCV_INSTALL_PATH}/bin ${OpenCV_INSTALL_PATH}/bin/Release ${OpenCV_INSTALL_PATH}/bin/Debug ${OpenCV_INSTALL_PATH}/lib ${OpenCV_INSTALL_PATH}/lib/jni NO_DEFAULT_PATH)
file(GLOB
cscore_jni_src src/main/native/cpp/jni/CameraServerJNI.cpp)

View File

@@ -60,12 +60,12 @@ model {
ext {
sharedCvConfigs = [cscore : [],
cscoreBase: [],
cscoreDev : [],
cscoreTest: [],
cscoreJNIShared: []]
cscoreBase: [],
cscoreDev : [],
cscoreTest: [],
cscoreJNIShared: []]
staticCvConfigs = [cscoreJNI: [],
cscoreJNICvStatic: []]
cscoreJNICvStatic: []]
useJava = true
useCpp = true
cvStaticBuild = true
@@ -127,43 +127,57 @@ def examplesMap = [:];
File examplesTree = file("$projectDir/examples")
examplesTree.list(new FilenameFilter() {
@Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
}).each {
sharedCvConfigs.put(it, [])
examplesMap.put(it, [])
}
@Override
public boolean accept(File current, String name) {
return new File(current, name).isDirectory();
}
}).each {
sharedCvConfigs.put(it, [])
examplesMap.put(it, [])
}
apply from: "${rootDir}/shared/opencv.gradle"
Action<List<String>> symbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
} as Action<List<String>>;
nativeUtils.exportsConfigs {
cscore {
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '_CT??_R0?AVout_of_range', '_CTA3?AVout_of_range',
'_TI3?AVout_of_range', '_CT??_R0?AVbad_cast']
x86ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
x64ExcludeSymbols = [
'_CT??_R0?AV_System_error',
'_CT??_R0?AVexception',
'_CT??_R0?AVfailure',
'_CT??_R0?AVruntime_error',
'_CT??_R0?AVsystem_error',
'_CTA5?AVfailure',
'_TI5?AVfailure',
'_CT??_R0?AVout_of_range',
'_CTA3?AVout_of_range',
'_TI3?AVout_of_range',
'_CT??_R0?AVbad_cast'
]
}
cscoreJNI {
x86SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
x64SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
x86SymbolFilter = symbolFilter
x64SymbolFilter = symbolFilter
}
cscoreJNICvStatic {
x86SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
x64SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
x86SymbolFilter = symbolFilter
x64SymbolFilter = symbolFilter
}
}

View File

@@ -1,84 +1,78 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <wpi/SmallString.h>
#include <wpi/raw_ostream.h>
#include <cstdio>
#include <fmt/format.h>
#include "cscore.h"
int main() {
CS_Status status = 0;
wpi::SmallString<64> buf;
for (const auto& caminfo : cs::EnumerateUsbCameras(&status)) {
wpi::outs() << caminfo.dev << ": " << caminfo.path << " (" << caminfo.name
<< ")\n";
fmt::print("{}: {} ({})\n", caminfo.dev, caminfo.path, caminfo.name);
if (!caminfo.otherPaths.empty()) {
wpi::outs() << "Other device paths:\n";
for (auto&& path : caminfo.otherPaths)
wpi::outs() << " " << path << '\n';
std::puts("Other device paths:");
for (auto&& path : caminfo.otherPaths) {
fmt::print(" {}\n", path);
}
}
cs::UsbCamera camera{"usbcam", caminfo.dev};
wpi::outs() << "Properties:\n";
std::puts("Properties:");
for (const auto& prop : camera.EnumerateProperties()) {
wpi::outs() << " " << prop.GetName();
fmt::print(" {}", prop.GetName());
switch (prop.GetKind()) {
case cs::VideoProperty::kBoolean:
wpi::outs() << " (bool): "
<< "value=" << prop.Get()
<< " default=" << prop.GetDefault();
fmt::print(" (bool): value={} default={}", prop.Get(),
prop.GetDefault());
break;
case cs::VideoProperty::kInteger:
wpi::outs() << " (int): "
<< "value=" << prop.Get() << " min=" << prop.GetMin()
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
<< " default=" << prop.GetDefault();
fmt::print(" (int): value={} min={} max={} step={} default={}",
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
prop.GetDefault());
break;
case cs::VideoProperty::kString:
wpi::outs() << " (string): " << prop.GetString(buf);
fmt::print(" (string): {}", prop.GetString());
break;
case cs::VideoProperty::kEnum: {
wpi::outs() << " (enum): "
<< "value=" << prop.Get();
fmt::print(" (enum): value={}", prop.Get());
auto choices = prop.GetChoices();
for (size_t i = 0; i < choices.size(); ++i) {
if (choices[i].empty()) continue;
wpi::outs() << "\n " << i << ": " << choices[i];
if (!choices[i].empty()) {
fmt::print("\n {}: {}", i, choices[i]);
}
}
break;
}
default:
break;
}
wpi::outs() << '\n';
std::fputc('\n', stdout);
}
wpi::outs() << "Video Modes:\n";
std::puts("Video Modes:");
for (const auto& mode : camera.EnumerateVideoModes()) {
wpi::outs() << " PixelFormat:";
const char* pixelFormat;
switch (mode.pixelFormat) {
case cs::VideoMode::kMJPEG:
wpi::outs() << "MJPEG";
pixelFormat = "MJPEG";
break;
case cs::VideoMode::kYUYV:
wpi::outs() << "YUYV";
pixelFormat = "YUYV";
break;
case cs::VideoMode::kRGB565:
wpi::outs() << "RGB565";
pixelFormat = "RGB565";
break;
default:
wpi::outs() << "Unknown";
pixelFormat = "Unknown";
break;
}
wpi::outs() << " Width:" << mode.width;
wpi::outs() << " Height:" << mode.height;
wpi::outs() << " FPS:" << mode.fps << '\n';
fmt::print(" PixelFormat:{} Width:{} Height:{} FPS:{}\n", pixelFormat,
mode.width, mode.height, mode.fps);
}
}
}

View File

@@ -1,13 +1,10 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <iostream>
#include <fmt/core.h>
#include <opencv2/core/core.hpp>
#include "cscore.h"
@@ -27,11 +24,11 @@ int main() {
for (;;) {
uint64_t time = cvsink.GrabFrame(test);
if (time == 0) {
std::cout << "error: " << cvsink.GetError() << std::endl;
fmt::print("error: {}\n", cvsink.GetError());
continue;
}
std::cout << "got frame at time " << time << " size " << test.size()
<< std::endl;
fmt::print("got frame at time {} size ({}, {})\n", time, test.size().width,
test.size().height);
cv::flip(test, flip, 0);
cvsource.PutFrame(flip);
}

View File

@@ -1,28 +1,29 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <chrono>
#include <cstdio>
#include <thread>
#include <wpi/SmallString.h>
#include <wpi/raw_ostream.h>
#include <fmt/format.h>
#include <wpi/StringExtras.h>
#include "cscore.h"
int main(int argc, char** argv) {
if (argc < 2) {
wpi::errs() << "Usage: settings camera [prop val] ... -- [prop val]...\n";
wpi::errs() << " Example: settings 1 brightness 30 raw_contrast 10\n";
std::fputs("Usage: settings camera [prop val] ... -- [prop val]...\n",
stderr);
std::fputs(" Example: settings 1 brightness 30 raw_contrast 10\n", stderr);
return 1;
}
int id;
if (wpi::StringRef{argv[1]}.getAsInteger(10, id)) {
wpi::errs() << "Expected number for camera\n";
if (auto v = wpi::parse_integer<int>(argv[1], 10)) {
id = v.value();
} else {
std::fputs("Expected number for camera\n", stderr);
return 2;
}
@@ -30,75 +31,75 @@ int main(int argc, char** argv) {
// Set prior to connect
int arg = 2;
wpi::StringRef propName;
for (; arg < argc && wpi::StringRef{argv[arg]} != "--"; ++arg) {
std::string_view propName;
for (; arg < argc && std::string_view{argv[arg]} != "--"; ++arg) {
if (propName.empty()) {
propName = argv[arg];
} else {
wpi::StringRef propVal{argv[arg]};
int intVal;
if (propVal.getAsInteger(10, intVal))
std::string_view propVal{argv[arg]};
if (auto v = wpi::parse_integer<int>(propVal, 10)) {
camera.GetProperty(propName).Set(v.value());
} else {
camera.GetProperty(propName).SetString(propVal);
else
camera.GetProperty(propName).Set(intVal);
propName = wpi::StringRef{};
}
propName = {};
}
}
if (arg < argc && wpi::StringRef{argv[arg]} == "--") ++arg;
if (arg < argc && std::string_view{argv[arg]} == "--") {
++arg;
}
// Wait to connect
while (!camera.IsConnected())
while (!camera.IsConnected()) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
// Set rest
propName = wpi::StringRef{};
propName = {};
for (; arg < argc; ++arg) {
if (propName.empty()) {
propName = argv[arg];
} else {
wpi::StringRef propVal{argv[arg]};
int intVal;
if (propVal.getAsInteger(10, intVal))
std::string_view propVal{argv[arg]};
if (auto v = wpi::parse_integer<int>(propVal, 10)) {
camera.GetProperty(propName).Set(v.value());
} else {
camera.GetProperty(propName).SetString(propVal);
else
camera.GetProperty(propName).Set(intVal);
propName = wpi::StringRef{};
}
propName = {};
}
}
// Print settings
wpi::SmallString<64> buf;
wpi::outs() << "Properties:\n";
std::puts("Properties:");
for (const auto& prop : camera.EnumerateProperties()) {
wpi::outs() << " " << prop.GetName();
fmt::print(" {}", prop.GetName());
switch (prop.GetKind()) {
case cs::VideoProperty::kBoolean:
wpi::outs() << " (bool): "
<< "value=" << prop.Get()
<< " default=" << prop.GetDefault();
fmt::print(" (bool): value={} default={}", prop.Get(),
prop.GetDefault());
break;
case cs::VideoProperty::kInteger:
wpi::outs() << " (int): "
<< "value=" << prop.Get() << " min=" << prop.GetMin()
<< " max=" << prop.GetMax() << " step=" << prop.GetStep()
<< " default=" << prop.GetDefault();
fmt::print(" (int): value={} min={} max={} step={} default={}",
prop.Get(), prop.GetMin(), prop.GetMax(), prop.GetStep(),
prop.GetDefault());
break;
case cs::VideoProperty::kString:
wpi::outs() << " (string): " << prop.GetString(buf);
fmt::print(" (string): {}", prop.GetString());
break;
case cs::VideoProperty::kEnum: {
wpi::outs() << " (enum): "
<< "value=" << prop.Get();
fmt::print(" (enum): value={}", prop.Get());
auto choices = prop.GetChoices();
for (size_t i = 0; i < choices.size(); ++i) {
if (choices[i].empty()) continue;
wpi::outs() << "\n " << i << ": " << choices[i];
if (!choices[i].empty()) {
fmt::print("\n {}: {}", i, choices[i]);
}
}
break;
}
default:
break;
}
wpi::outs() << '\n';
std::fputc('\n', stdout);
}
}

View File

@@ -1,13 +1,8 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include <cstdio>
#include <iostream>
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <fmt/core.h>
#include <opencv2/core/core.hpp>
#include "cscore.h"
@@ -29,11 +24,11 @@ int main() {
for (;;) {
uint64_t time = cvsink.GrabFrame(test);
if (time == 0) {
std::cout << "error: " << cvsink.GetError() << std::endl;
fmt::print("error: {}\n", cvsink.GetError());
continue;
}
std::cout << "got frame at time " << time << " size " << test.size()
<< std::endl;
fmt::print("got frame at time {} size ({}, {})\n", time, test.size().width,
test.size().height);
cv::flip(test, flip, 0);
cvsource.PutFrame(flip);
}

View File

@@ -1,21 +1,19 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <cstdio>
#include <wpi/raw_ostream.h>
#include <fmt/format.h>
#include "cscore.h"
int main() {
wpi::outs() << "hostname: " << cs::GetHostname() << '\n';
wpi::outs() << "IPv4 network addresses:\n";
for (const auto& addr : cs::GetNetworkInterfaces())
wpi::outs() << " " << addr << '\n';
fmt::print("hostname: {}\n", cs::GetHostname());
std::puts("IPv4 network addresses:");
for (const auto& addr : cs::GetNetworkInterfaces()) {
fmt::print(" {}\n", addr);
}
cs::UsbCamera camera{"usbcam", 0};
camera.SetVideoMode(cs::VideoMode::kMJPEG, 320, 240, 30);
cs::MjpegServer mjpegServer{"httpserver", 8081};
@@ -24,9 +22,8 @@ int main() {
CS_Status status = 0;
cs::AddListener(
[&](const cs::RawEvent& event) {
wpi::outs() << "FPS=" << camera.GetActualFPS()
<< " MBPS=" << (camera.GetActualDataRate() / 1000000.0)
<< '\n';
fmt::print("FPS={} MBPS={}\n", camera.GetActualFPS(),
(camera.GetActualDataRate() / 1000000.0));
},
cs::RawEvent::kTelemetryUpdated, false, &status);
cs::SetTelemetryPeriod(1.0);

View File

@@ -1,20 +1,18 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2020 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <atomic>
#include <thread>
#include <vector>
#include <fmt/format.h>
#define IMGUI_DEFINE_MATH_OPERATORS
#include <imgui.h>
#include <imgui_internal.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include <wpi/raw_ostream.h>
#include <wpi/spinlock.h>
#include <wpigui.h>
@@ -41,7 +39,7 @@ int main() {
// get frame from camera
uint64_t time = cvsink.GrabFrame(frame);
if (time == 0) {
wpi::outs() << "error: " << cvsink.GetError() << '\n';
fmt::print("error: {}\n", cvsink.GetError());
continue;
}
@@ -53,7 +51,9 @@ int main() {
} else {
{
std::scoped_lock lock(sharedFreeListMutex);
for (auto mat : sharedFreeList) sourceFreeList.emplace_back(mat);
for (auto mat : sharedFreeList) {
sourceFreeList.emplace_back(mat);
}
sharedFreeList.clear();
}
if (!sourceFreeList.empty()) {
@@ -71,7 +71,9 @@ int main() {
auto prev = latestFrame.exchange(out);
// put prev on free list
if (prev) sourceFreeList.emplace_back(prev);
if (prev) {
sourceFreeList.emplace_back(prev);
}
}
});

View File

@@ -1,19 +1,14 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
import java.nio.ByteBuffer;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import edu.wpi.cscore.VideoMode.PixelFormat;
import edu.wpi.cscore.raw.RawFrame;
import java.nio.ByteBuffer;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
public class RawCVMatSink extends ImageSink {
RawFrame frame = new RawFrame();
@@ -27,26 +22,25 @@ public class RawCVMatSink extends ImageSink {
private int getCVFormat(PixelFormat pixelFormat) {
int type = 0;
switch (pixelFormat) {
case kYUYV:
case kRGB565:
type = CvType.CV_8UC2;
break;
case kBGR:
type = CvType.CV_8UC3;
break;
case kGray:
case kMJPEG:
default:
type = CvType.CV_8UC1;
break;
case kYUYV:
case kRGB565:
type = CvType.CV_8UC2;
break;
case kBGR:
type = CvType.CV_8UC3;
break;
case kGray:
case kMJPEG:
default:
type = CvType.CV_8UC1;
break;
}
return type;
}
/**
* Create a sink for accepting OpenCV images.
* WaitForFrame() must be called on the created sink to get each new
* image.
* Create a sink for accepting OpenCV images. WaitForFrame() must be called on the created sink to
* get each new image.
*
* @param name Source name (arbitrary unique identifier)
*/
@@ -55,24 +49,21 @@ public class RawCVMatSink extends ImageSink {
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after 0.225 seconds.
* The provided image will have three 3-bit channels stored in BGR order.
* Wait for the next frame and get the image. Times out (returning 0) after 0.225 seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message)
* @return Frame time, or 0 on error (call GetError() to obtain the error message)
*/
public long grabFrame(Mat image) {
return grabFrame(image, 0.225);
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after timeout seconds.
* The provided image will have three 3-bit channels stored in BGR order.
* Wait for the next frame and get the image. Times out (returning 0) after timeout seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message); the frame time is in 1 us increments.
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
* is in 1 us increments.
*/
public long grabFrame(Mat image, double timeout) {
frame.setWidth(0);
@@ -83,12 +74,20 @@ public class RawCVMatSink extends ImageSink {
return rv;
}
if (frame.getDataByteBuffer() != origByteBuffer || width != frame.getWidth() || height != frame.getHeight() || pixelFormat != frame.getPixelFormat()) {
if (frame.getDataByteBuffer() != origByteBuffer
|| width != frame.getWidth()
|| height != frame.getHeight()
|| pixelFormat != frame.getPixelFormat()) {
origByteBuffer = frame.getDataByteBuffer();
height = frame.getHeight();
width = frame.getWidth();
pixelFormat = frame.getPixelFormat();
tmpMat = new Mat(frame.getHeight(), frame.getWidth(), getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)), origByteBuffer);
tmpMat =
new Mat(
frame.getHeight(),
frame.getWidth(),
getCVFormat(VideoMode.getPixelFormatFromInt(pixelFormat)),
origByteBuffer);
}
tmpMat.copyTo(image);
return rv;

View File

@@ -1,15 +1,11 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
import org.opencv.core.Mat;
import edu.wpi.cscore.VideoMode.PixelFormat;
import org.opencv.core.Mat;
public class RawCVMatSource extends ImageSource {
/**
@@ -19,11 +15,9 @@ public class RawCVMatSource extends ImageSource {
* @param mode Video mode being generated
*/
public RawCVMatSource(String name, VideoMode mode) {
super(CameraServerJNI.createRawSource(name,
mode.pixelFormat.getValue(),
mode.width,
mode.height,
mode.fps));
super(
CameraServerJNI.createRawSource(
name, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps));
}
/**
@@ -35,16 +29,17 @@ public class RawCVMatSource extends ImageSource {
* @param height height
* @param fps fps
*/
public RawCVMatSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
public RawCVMatSource(
String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerJNI.createRawSource(name, pixelFormat.getValue(), width, height, fps));
}
/**
* Put an OpenCV image and notify sinks.
*
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
* are supported. If the format, depth or channel order is different, use
* Mat.convertTo() and/or cvtColor() to convert it first.
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images are supported. If the
* format, depth or channel order is different, use Mat.convertTo() and/or cvtColor() to convert
* it first.
*
* @param image OpenCV image
*/
@@ -54,6 +49,12 @@ public class RawCVMatSource extends ImageSource {
throw new VideoException("Unsupported Image Type");
}
int imgType = channels == 1 ? PixelFormat.kGray.getValue() : PixelFormat.kBGR.getValue();
CameraServerJNI.putRawSourceFrame(m_handle, image.dataAddr(), image.width(), image.height(), imgType, (int)image.total() * channels);
CameraServerJNI.putRawSourceFrame(
m_handle,
image.dataAddr(),
image.width(),
image.height(),
imgType,
(int) image.total() * channels);
}
}

View File

@@ -1,24 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
import edu.wpi.first.wpiutil.RuntimeDetector;
public final class DevMain {
/**
* Main method.
*/
public static void main(String[] args) {
System.out.println("Hello World!");
System.out.println(RuntimeDetector.getPlatformPath());
System.out.println(CameraServerJNI.getHostname());
}
private DevMain() {
}
}

View File

@@ -0,0 +1,18 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.cscore;
import edu.wpi.first.util.RuntimeDetector;
public final class DevMain {
/** Main method. */
public static void main(String[] args) {
System.out.println("Hello World!");
System.out.println(RuntimeDetector.getPlatformPath());
System.out.println(CameraServerJNI.getHostname());
}
private DevMain() {}
}

View File

@@ -1,12 +1,11 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include <iostream>
#include <fmt/core.h>
#include "cscore.h"
int main() { std::cout << cs::GetHostname() << std::endl; }
int main() {
fmt::print("{}\n", cs::GetHostname());
}

View File

@@ -1,59 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
import org.opencv.core.Mat;
/**
* A source that represents a video camera.
* These sources require the WPILib OpenCV builds.
* For an alternate OpenCV, see the documentation how to build your own
* with RawSource.
*/
public class CvSource extends ImageSource {
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
public CvSource(String name, VideoMode mode) {
super(CameraServerCvJNI.createCvSource(name,
mode.pixelFormat.getValue(),
mode.width,
mode.height,
mode.fps));
}
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
}
/**
* Put an OpenCV image and notify sinks.
*
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images
* are supported. If the format, depth or channel order is different, use
* Mat.convertTo() and/or cvtColor() to convert it first.
*
* @param image OpenCV image
*/
public void putFrame(Mat image) {
CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
}
}

View File

@@ -1,41 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
public abstract class ImageSink extends VideoSink {
protected ImageSink(int handle) {
super(handle);
}
/**
* Set sink description.
*
* @param description Description
*/
public void setDescription(String description) {
CameraServerJNI.setSinkDescription(m_handle, description);
}
/**
* Get error string. Call this if WaitForFrame() returns 0 to determine
* what the error is.
*/
public String getError() {
return CameraServerJNI.getSinkError(m_handle);
}
/**
* Enable or disable getting new frames.
* Disabling will cause processFrame (for callback-based CvSinks) to not
* be called and WaitForFrame() to not return. This can be used to save
* processor resources when frames are not needed.
*/
public void setEnabled(boolean enabled) {
CameraServerJNI.setSinkEnabled(m_handle, enabled);
}
}

View File

@@ -1,70 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
/**
* USB camera information.
*/
public class UsbCameraInfo {
/**
* Create a new set of UsbCameraInfo.
*
* @param dev Device number (e.g. N in '/dev/videoN' on Linux)
* @param path Path to device if available (e.g. '/dev/video0' on Linux)
* @param name Vendor/model name of the camera as provided by the USB driver
* @param otherPaths Other path aliases to device
* @param vendorId USB vendor id
* @param productId USB product id
*/
@SuppressWarnings("PMD.ArrayIsStoredDirectly")
public UsbCameraInfo(int dev, String path, String name, String[] otherPaths, int vendorId,
int productId) {
this.dev = dev;
this.path = path;
this.name = name;
this.otherPaths = otherPaths;
this.vendorId = vendorId;
this.productId = productId;
}
/**
* Device number (e.g. N in '/dev/videoN' on Linux).
*/
@SuppressWarnings("MemberName")
public int dev;
/**
* Path to device if available (e.g. '/dev/video0' on Linux).
*/
@SuppressWarnings("MemberName")
public String path;
/**
* Vendor/model name of the camera as provided by the USB driver.
*/
@SuppressWarnings("MemberName")
public String name;
/**
* Other path aliases to device (e.g. '/dev/v4l/by-id/...' etc on Linux).
*/
@SuppressWarnings("MemberName")
public String[] otherPaths;
/**
* USB vendor id.
*/
@SuppressWarnings("MemberName")
public int vendorId;
/**
* USB product id.
*/
@SuppressWarnings("MemberName")
public int productId;
}

View File

@@ -1,24 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
/**
* An exception raised by the camera server.
*/
public class VideoException extends RuntimeException {
private static final long serialVersionUID = -9155939328084105145L;
public VideoException(String msg) {
super(msg);
}
@Override
public String toString() {
return "VideoException [" + super.toString() + "]";
}
}

View File

@@ -1,43 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
import java.util.function.Consumer;
/**
* An event listener. This calls back to a desigated callback function when
* an event matching the specified mask is generated by the library.
*/
public class VideoListener implements AutoCloseable {
/**
* Create an event listener.
*
* @param listener Listener function
* @param eventMask Bitmask of VideoEvent.Type values
* @param immediateNotify Whether callback should be immediately called with
* a representative set of events for the current library state.
*/
public VideoListener(Consumer<VideoEvent> listener, int eventMask,
boolean immediateNotify) {
m_handle = CameraServerJNI.addListener(listener, eventMask, immediateNotify);
}
@Override
public synchronized void close() {
if (m_handle != 0) {
CameraServerJNI.removeListener(m_handle);
}
m_handle = 0;
}
public boolean isValid() {
return m_handle != 0;
}
private int m_handle;
}

View File

@@ -1,68 +0,0 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore.raw;
import edu.wpi.cscore.CameraServerJNI;
import edu.wpi.cscore.ImageSink;
/**
* A sink for user code to accept video frames as raw bytes.
*
* <p>This is a complex API, most cases should use CvSink.
*/
public class RawSink extends ImageSink {
/**
* Create a sink for accepting raw images.
*
* <p>grabFrame() must be called on the created sink to get each new
* image.
*
* @param name Source name (arbitrary unique identifier)
*/
public RawSink(String name) {
super(CameraServerJNI.createRawSink(name));
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after 0.225 seconds.
* The provided image will have three 8-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call getError() to obtain the error
* message); the frame time is in the same time base as wpi::Now(),
* and is in 1 us increments.
*/
protected long grabFrame(RawFrame frame) {
return grabFrame(frame, 0.225);
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after timeout seconds.
* The provided image will have three 8-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call getError() to obtain the error
* message); the frame time is in the same time base as wpi::Now(),
* and is in 1 us increments.
*/
protected long grabFrame(RawFrame frame, double timeout) {
return CameraServerJNI.grabSinkFrameTimeout(m_handle, frame, timeout);
}
/**
* Wait for the next frame and get the image. May block forever.
* The provided image will have three 8-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call getError() to obtain the error
* message); the frame time is in the same time base as wpi::Now(),
* and is in 1 us increments.
*/
protected long grabFrameNoTimeout(RawFrame frame) {
return CameraServerJNI.grabSinkFrame(m_handle, frame);
}
}

View File

@@ -1,15 +1,10 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
package edu.wpi.first.cscore;
/**
* A source that represents an Axis IP camera.
*/
/** A source that represents an Axis IP camera. */
public class AxisCamera extends HttpCamera {
private static String hostToUrl(String host) {
return "http://" + host + "/mjpg/video.mjpg";

View File

@@ -1,19 +1,14 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
package edu.wpi.first.cscore;
import edu.wpi.first.util.RuntimeLoader;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.opencv.core.Core;
import edu.wpi.first.wpiutil.RuntimeLoader;
public class CameraServerCvJNI {
static boolean libraryLoaded = false;
@@ -36,7 +31,8 @@ public class CameraServerCvJNI {
if (Helper.getExtractOnStaticLoad()) {
try {
CameraServerJNI.forceLoad();
loader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader =
new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibraryHashed();
} catch (IOException ex) {
ex.printStackTrace();
@@ -48,25 +44,31 @@ public class CameraServerCvJNI {
/**
* Force load the library.
*
* @throws IOException if library load failed
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
CameraServerJNI.forceLoad();
loader = new RuntimeLoader<>(Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader =
new RuntimeLoader<>(
Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibrary();
libraryLoaded = true;
}
public static native int createCvSource(String name, int pixelFormat, int width, int height, int fps);
public static native int createCvSource(
String name, int pixelFormat, int width, int height, int fps);
public static native void putSourceFrame(int source, long imageNativeObj);
public static native int createCvSink(String name);
//public static native int createCvSinkCallback(String name,
// public static native int createCvSinkCallback(String name,
// void (*processFrame)(long time));
public static native long grabSinkFrame(int sink, long imageNativeObj);
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
}

View File

@@ -1,20 +1,16 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
package edu.wpi.first.cscore;
import edu.wpi.first.cscore.raw.RawFrame;
import edu.wpi.first.util.RuntimeLoader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import edu.wpi.cscore.raw.RawFrame;
import edu.wpi.first.wpiutil.RuntimeLoader;
public class CameraServerJNI {
static boolean libraryLoaded = false;
@@ -35,7 +31,9 @@ public class CameraServerJNI {
static {
if (Helper.getExtractOnStaticLoad()) {
try {
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader =
new RuntimeLoader<>(
"cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
} catch (IOException ex) {
ex.printStackTrace();
@@ -47,12 +45,16 @@ public class CameraServerJNI {
/**
* Force load the library.
*
* @throws IOException if library load failed
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader =
new RuntimeLoader<>(
"cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
libraryLoaded = true;
}
@@ -61,89 +63,159 @@ public class CameraServerJNI {
// Property Functions
//
public static native int getPropertyKind(int property);
public static native String getPropertyName(int property);
public static native int getProperty(int property);
public static native void setProperty(int property, int value);
public static native int getPropertyMin(int property);
public static native int getPropertyMax(int property);
public static native int getPropertyStep(int property);
public static native int getPropertyDefault(int property);
public static native String getStringProperty(int property);
public static native void setStringProperty(int property, String value);
public static native String[] getEnumPropertyChoices(int property);
//
// Source Creation Functions
//
public static native int createUsbCameraDev(String name, int dev);
public static native int createUsbCameraPath(String name, String path);
public static native int createHttpCamera(String name, String url, int kind);
public static native int createHttpCameraMulti(String name, String[] urls, int kind);
public static native int createRawSource(String name, int pixelFormat, int width, int height, int fps);
public static native int createRawSource(
String name, int pixelFormat, int width, int height, int fps);
//
// Source Functions
//
public static native int getSourceKind(int source);
public static native String getSourceName(int source);
public static native String getSourceDescription(int source);
public static native long getSourceLastFrameTime(int source);
public static native void setSourceConnectionStrategy(int source, int strategy);
public static native boolean isSourceConnected(int source);
public static native boolean isSourceEnabled(int source);
public static native int getSourceProperty(int source, String name);
public static native int[] enumerateSourceProperties(int source);
public static native VideoMode getSourceVideoMode(int source);
public static native boolean setSourceVideoMode(int source, int pixelFormat, int width, int height, int fps);
public static native boolean setSourceVideoMode(
int source, int pixelFormat, int width, int height, int fps);
public static native boolean setSourcePixelFormat(int source, int pixelFormat);
public static native boolean setSourceResolution(int source, int width, int height);
public static native boolean setSourceFPS(int source, int fps);
public static native boolean setSourceConfigJson(int source, String config);
public static native String getSourceConfigJson(int source);
public static native VideoMode[] enumerateSourceVideoModes(int source);
public static native int[] enumerateSourceSinks(int source);
public static native int copySource(int source);
public static native void releaseSource(int source);
//
// Camera Source Common Property Fuctions
//
public static native void setCameraBrightness(int source, int brightness);
public static native int getCameraBrightness(int source);
public static native void setCameraWhiteBalanceAuto(int source);
public static native void setCameraWhiteBalanceHoldCurrent(int source);
public static native void setCameraWhiteBalanceManual(int source, int value);
public static native void setCameraExposureAuto(int source);
public static native void setCameraExposureHoldCurrent(int source);
public static native void setCameraExposureManual(int source, int value);
//
// UsbCamera Source Functions
//
public static native void setUsbCameraPath(int source, String path);
public static native String getUsbCameraPath(int source);
public static native UsbCameraInfo getUsbCameraInfo(int source);
//
// HttpCamera Source Functions
//
public static native int getHttpCameraKind(int source);
public static native void setHttpCameraUrls(int source, String[] urls);
public static native String[] getHttpCameraUrls(int source);
//
// Image Source Functions
//
public static native void putRawSourceFrameBB(int source, ByteBuffer data, int width, int height, int pixelFormat, int totalData);
public static native void putRawSourceFrame(int source, long data, int width, int height, int pixelFormat, int totalData);
public static native void putRawSourceFrameBB(
int source, ByteBuffer data, int width, int height, int pixelFormat, int totalData);
public static native void putRawSourceFrame(
int source, long data, int width, int height, int pixelFormat, int totalData);
public static void putRawSourceFrame(int source, RawFrame raw) {
putRawSourceFrame(source, raw.getDataPtr(), raw.getWidth(), raw.getHeight(), raw.getPixelFormat(), raw.getTotalData());
putRawSourceFrame(
source,
raw.getDataPtr(),
raw.getWidth(),
raw.getHeight(),
raw.getPixelFormat(),
raw.getTotalData());
}
public static native void notifySourceError(int source, String msg);
public static native void setSourceConnected(int source, boolean connected);
public static native void setSourceDescription(int source, String description);
public static native int createSourceProperty(int source, String name, int kind, int minimum, int maximum, int step, int defaultValue, int value);
public static native void setSourceEnumPropertyChoices(int source, int property, String[] choices);
public static native int createSourceProperty(
int source,
String name,
int kind,
int minimum,
int maximum,
int step,
int defaultValue,
int value);
public static native void setSourceEnumPropertyChoices(
int source, int property, String[] choices);
//
// Sink Creation Functions
@@ -156,22 +228,34 @@ public class CameraServerJNI {
// Sink Functions
//
public static native int getSinkKind(int sink);
public static native String getSinkName(int sink);
public static native String getSinkDescription(int sink);
public static native int getSinkProperty(int sink, String name);
public static native int[] enumerateSinkProperties(int sink);
public static native boolean setSinkConfigJson(int sink, String config);
public static native String getSinkConfigJson(int sink);
public static native void setSinkSource(int sink, int source);
public static native int getSinkSourceProperty(int sink, String name);
public static native int getSinkSource(int sink);
public static native int copySink(int sink);
public static native void releaseSink(int sink);
//
// MjpegServer Sink Functions
//
public static native String getMjpegServerListenAddress(int sink);
public static native int getMjpegServerPort(int sink);
//
@@ -179,26 +263,73 @@ public class CameraServerJNI {
//
public static native void setSinkDescription(int sink, String description);
private static native long grabRawSinkFrameImpl(int sink, RawFrame rawFrame, long rawFramePtr, ByteBuffer byteBuffer, int width, int height, int pixelFormat);
private static native long grabRawSinkFrameTimeoutImpl(int sink, RawFrame rawFrame, long rawFramePtr, ByteBuffer byteBuffer, int width, int height, int pixelFormat, double timeout);
private static native long grabRawSinkFrameImpl(
int sink,
RawFrame rawFrame,
long rawFramePtr,
ByteBuffer byteBuffer,
int width,
int height,
int pixelFormat);
private static native long grabRawSinkFrameTimeoutImpl(
int sink,
RawFrame rawFrame,
long rawFramePtr,
ByteBuffer byteBuffer,
int width,
int height,
int pixelFormat,
double timeout);
public static long grabSinkFrame(int sink, RawFrame rawFrame) {
return grabRawSinkFrameImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat());
return grabRawSinkFrameImpl(
sink,
rawFrame,
rawFrame.getFramePtr(),
rawFrame.getDataByteBuffer(),
rawFrame.getWidth(),
rawFrame.getHeight(),
rawFrame.getPixelFormat());
}
public static long grabSinkFrameTimeout(int sink, RawFrame rawFrame, double timeout) {
return grabRawSinkFrameTimeoutImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat(), timeout);
return grabRawSinkFrameTimeoutImpl(
sink,
rawFrame,
rawFrame.getFramePtr(),
rawFrame.getDataByteBuffer(),
rawFrame.getWidth(),
rawFrame.getHeight(),
rawFrame.getPixelFormat(),
timeout);
}
public static native String getSinkError(int sink);
public static native void setSinkEnabled(int sink, boolean enabled);
//
// Listener Functions
//
public static native int addListener(Consumer<VideoEvent> listener,
int eventMask, boolean immediateNotify);
public static native int addListener(
Consumer<VideoEvent> listener, int eventMask, boolean immediateNotify);
public static native void removeListener(int handle);
public static native int createListenerPoller();
public static native void destroyListenerPoller(int poller);
public static native int addPolledListener(int poller, int eventMask, boolean immediateNotify);
public static native VideoEvent[] pollListener(int poller) throws InterruptedException;
public static native VideoEvent[] pollListenerTimeout(int poller, double timeout)
throws InterruptedException;
public static native void cancelPollListener(int poller);
//
// Telemetry Functions
//
@@ -206,7 +337,6 @@ public class CameraServerJNI {
kSourceBytesReceived(1),
kSourceFramesReceived(2);
@SuppressWarnings("MemberName")
private final int value;
TelemetryKind(int value) {
@@ -217,13 +347,19 @@ public class CameraServerJNI {
return value;
}
}
public static native void setTelemetryPeriod(double seconds);
public static native double getTelemetryElapsedTime();
public static native long getTelemetryValue(int handle, int kind);
public static long getTelemetryValue(int handle, TelemetryKind kind) {
return getTelemetryValue(handle, kind.getValue());
}
public static native double getTelemetryAverageValue(int handle, int kind);
public static double getTelemetryAverageValue(int handle, TelemetryKind kind) {
return getTelemetryAverageValue(handle, kind.getValue());
}
@@ -235,6 +371,7 @@ public class CameraServerJNI {
public interface LoggerFunction {
void apply(int level, String file, int line, String msg);
}
public static native void setLogger(LoggerFunction func, int minLevel);
//

View File

@@ -1,25 +1,19 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.cscore;
package edu.wpi.first.cscore;
import org.opencv.core.Mat;
/**
* A sink for user code to accept video frames as OpenCV images.
* These sinks require the WPILib OpenCV builds.
* For an alternate OpenCV, see the documentation how to build your own
* with RawSink.
* A sink for user code to accept video frames as OpenCV images. These sinks require the WPILib
* OpenCV builds. For an alternate OpenCV, see the documentation how to build your own with RawSink.
*/
public class CvSink extends ImageSink {
/**
* Create a sink for accepting OpenCV images.
* WaitForFrame() must be called on the created sink to get each new
* image.
* Create a sink for accepting OpenCV images. WaitForFrame() must be called on the created sink to
* get each new image.
*
* @param name Source name (arbitrary unique identifier)
*/
@@ -35,41 +29,42 @@ public class CvSink extends ImageSink {
/// time=0 if an error occurred. processFrame should call GetImage()
/// or GetError() as needed, but should not call (except in very
/// unusual circumstances) WaitForImage().
//public CvSink(wpi::StringRef name,
// public CvSink(wpi::StringRef name,
// std::function<void(uint64_t time)> processFrame) {
// super(CameraServerJNI.createCvSinkCallback(name, processFrame));
//}
// }
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after 0.225 seconds.
* The provided image will have three 3-bit channels stored in BGR order.
* Wait for the next frame and get the image. Times out (returning 0) after 0.225 seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message)
* @param image Where to store the image.
* @return Frame time, or 0 on error (call GetError() to obtain the error message)
*/
public long grabFrame(Mat image) {
return grabFrame(image, 0.225);
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after timeout seconds.
* The provided image will have three 3-bit channels stored in BGR order.
* Wait for the next frame and get the image. Times out (returning 0) after timeout seconds. The
* provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message); the frame time is in 1 us increments.
* @param image Where to store the image.
* @param timeout Retrieval timeout in seconds.
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
* is in 1 us increments.
*/
public long grabFrame(Mat image, double timeout) {
return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
}
/**
* Wait for the next frame and get the image. May block forever.
* The provided image will have three 3-bit channels stored in BGR order.
* Wait for the next frame and get the image. May block forever. The provided image will have
* three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message); the frame time is in 1 us increments.
* @param image Where to store the image.
* @return Frame time, or 0 on error (call GetError() to obtain the error message); the frame time
* is in 1 us increments.
*/
public long grabFrameNoTimeout(Mat image) {
return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);

View File

@@ -0,0 +1,51 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package edu.wpi.first.cscore;
import org.opencv.core.Mat;
/**
* A source that represents a video camera. These sources require the WPILib OpenCV builds. For an
* alternate OpenCV, see the documentation how to build your own with RawSource.
*/
public class CvSource extends ImageSource {
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
public CvSource(String name, VideoMode mode) {
super(
CameraServerCvJNI.createCvSource(
name, mode.pixelFormat.getValue(), mode.width, mode.height, mode.fps));
}
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
}
/**
* Put an OpenCV image and notify sinks.
*
* <p>Only 8-bit single-channel or 3-channel (with BGR channel order) images are supported. If the
* format, depth or channel order is different, use Mat.convertTo() and/or cvtColor() to convert
* it first.
*
* @param image OpenCV image
*/
public void putFrame(Mat image) {
CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
}
}

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