Compare commits

...

512 Commits

Author SHA1 Message Date
Tyler Veness
35eb90c135 Fix "'dimensionless' ambiguous symbol" error (#2382)
A typedef for units::dimensionless::dimensionless is defined, which
conflicted with the namespace when we added "using namespace
dimensionless". This patch reverts the "using namespace" directive.
"using" directives were added to pull three of the four relevant
typedefs but avoid the "dimensionless" type conflict.

This issue was first introduced in #2301.
2020-02-21 00:41:50 -08:00
Dustin Spicuzza
761f79385a Add SimulationInit and SimulationPeriodic functions (#2377)
Fixes #2375
2020-02-18 23:05:16 -08:00
Thad House
554bda3332 HAL: Expose NetComm SendConsoleLine (#2337)
This can be use to synchronize writes between threads, assuming writes all go through this and not stdout.
2020-02-18 20:44:40 -08:00
Thad House
2a968df779 Add method for releasing a waiting interrupt (#2347)
Useful for a new high level interrupt implementation.
2020-02-18 20:41:42 -08:00
sciencewhiz
30ccd13b69 Add methods for getting color of an LED (#2366)
Also fix rounding in Color.
2020-02-18 20:40:03 -08:00
Thad House
60c09ea51f Fix notifier race happening with very fast notifiers (#2370)
What would happen is the Stop() call would happen between the notifier loop being triggered and calling UpdateAlarm(). This would cause the Update to overwrite the stop.
2020-02-18 20:38:05 -08:00
Oblarg
65eab93527 Fix DifferentialDriveVoltageConstraint for tight turns w/ zero velocity (#2341) 2020-02-15 12:36:16 -08:00
sciencewhiz
a226ad8509 Set a default option for Sendable Chooser in examples (#2361) 2020-02-15 09:54:12 -08:00
Peter Johnson
31f4fd70ce Sim GUI: Fix crash when field/robot image load is canceled (#2362) 2020-02-15 09:53:21 -08:00
Dustin Spicuzza
7275ab9837 Add headerpad_max_install_names to Mac builds (#2333)
This allows dylib paths to be rewritten to a larger size by downstream tools.
2020-02-10 21:52:58 -08:00
Dustin Spicuzza
5b3facc63b TrapezoidProfile: Make units public (#2342) 2020-02-10 21:44:21 -08:00
CircuitCraft42
0f313fb9ab cmake: Improved portability of OpenCV Java binding search (#2348)
The CMake option OPENCV_JAVA_INSTALL_DIR can be set to the location
to search for the jar file. Note that the file name cannot be
changed, as, after checking several Linux package repositories,
that seems to be constant across all of them.

Fixes #2346.
2020-02-10 17:30:54 -08:00
Oblarg
05b7593e66 C++ circular_buffer: support types not implicitly convertible from int (#2350)
Also fixes two cases of returning a reference to a constant.
2020-02-08 13:35:21 -08:00
sciencewhiz
1b85066d26 Fix C++ ParallelRaceGroup multiple calls behavior (#2339)
The Java version was correct, but the C++ version would only run once.
2020-02-08 10:26:06 -08:00
sciencewhiz
e93b64f58d Add note that only a single instance of ADXRS450 is supported (#2349) 2020-02-08 10:24:18 -08:00
Oblarg
f0a18f31e7 Timer: add hasElapsed, advanceIfElapsed (#2322)
The current hasPeriodPassed() function is confusing.  In preparation for deprecating it,
add new advanceIfElapsed() function with same functionality and hasElapsed() function
which only checks that the time period has elapsed and does not advance the timer.

Also fix a couple of incorrect usages of hasPeriodPassed().
2020-02-08 10:23:29 -08:00
Vasista Vovveti
29c82527a5 Fix typo in ADXL sim double creation (#2332)
Sets m_simY to the virtual Y acceleration.
2020-02-04 20:15:25 -08:00
Peter Johnson
c165dc5e50 Simulation GUI: Add 2D field view (#2261)
The field image and robot image can be loaded or just a wireframe used.
The robot can be moved and rotated with a mouse click + drag.
The robot position is settable in robot code via the Field2d class.
2020-02-01 21:30:23 -08:00
sciencewhiz
42da07396c Add missing references to f in PIDSubsystem javadoc (#2318) 2020-01-31 19:18:17 -08:00
Jonathan Noyola
20e6c04059 Fix cmake install of hal generated files (#2320) 2020-01-31 19:18:00 -08:00
Declan Freeman-Gleason
ff5d3e5b36 RamseteController: Add setEnabled method (#2313) 2020-01-27 21:53:00 -08:00
sciencewhiz
6cc68ab503 Update MavenArtifacts.md (#2289) 2020-01-27 19:45:53 -08:00
Thad House
068465146b Fix null check order in SendableRegistry (#2314) 2020-01-27 19:43:31 -08:00
Thad House
3bcf8057d4 Add more detail to RuntimeLoader failure message (#2309)
Now specifies the C++ runtime is needed, along with more detail to make it easier to troubleshoot and not lose exception information.
2020-01-27 14:10:46 -08:00
David Vo
8039a6c525 Add missing include to ShuffleboardEventImportance (#2310) 2020-01-26 21:03:15 -08:00
Prateek Machiraju
558c020cca Fix duplicated state when using quintic splines (#2307)
Generating a trajectory using quintic splines caused a duplicated state at all knot points.
2020-01-24 23:10:28 -08:00
Prateek Machiraju
7797da78f5 Add missing methods to Timed and TimedSkeleton templates (#2306) 2020-01-24 20:01:23 -08:00
Oblarg
0ab81d768f Add feed-forward and slew rate limiting to advanced drive examples (#2301) 2020-01-23 18:07:38 -08:00
Oblarg
1cee5ccb93 Feed RobotDrive watchdog in RamseteCommand example (#2298) 2020-01-23 17:41:45 -08:00
Dan Katzuv
3ce01b5ac2 Fix DriveSubsystem.getHeading Java documentation (#2282) 2020-01-23 16:46:53 -08:00
sciencewhiz
e6aa8f3ff4 Update toolchain link in readme (#2304) 2020-01-23 16:43:06 -08:00
Peter Johnson
9d7b087972 Simulation GUI: Add support for custom names (#2292)
This allows users to right click on just about any name in the GUI (e.g. "PWM[0]") and rename it (e.g. "Left Motor [0]"). The index portion is not editable. The name is saved into imgui.ini so it's persistent.
2020-01-20 22:47:36 -08:00
Peter Johnson
bb184ed481 Simulation GUI: Refactor ini saving (#2291) 2020-01-20 21:49:03 -08:00
Peter Johnson
b9b31069cc Fix C++ POVButton (#2294)
Also add unit test.
2020-01-20 21:35:19 -08:00
Peter Johnson
d0cf4e8882 Change sim Filesystem.getDeployDirectory() to src/main/deploy (#2293) 2020-01-19 16:34:45 -08:00
sciencewhiz
02fb850761 Add new speed controllers to shuffleboard docs (#2288)
Also fix java links in C++ docs and a few typos.
2020-01-19 14:26:44 -08:00
sciencewhiz
ac8177e10d Fix GearsBot log methods not being called periodically (#2280)
Add logging for C++ Wrist and Claw
2020-01-17 20:18:15 -08:00
Tyler Veness
2eb5c54476 TrapezoidProfile: Fix aliasing of m_initial to result in calculate() (#2284)
Fixes #2283.
2020-01-17 20:17:21 -08:00
Peter Johnson
0e206e69cf Remove Set Camera Server Shared message (#2285) 2020-01-17 20:16:24 -08:00
Peter Johnson
b1357cace7 Fix LiveWindow SetEnabled C++ std::bad_function_call (#2281)
It was missing a null check.
2020-01-16 00:34:51 -08:00
Thad House
37202b6f28 Add missing SensorUtil::kAnalogOutputs (#2276) 2020-01-15 21:34:28 -08:00
Thad House
2ac0d52960 Remove AnalogTrigger::SetDutyCycle (#2275) 2020-01-15 21:33:58 -08:00
Thad House
dbe1e6f466 Fix missing SetDutyCycleSimDevice on Rio (#2274) 2020-01-15 21:33:35 -08:00
Chris Russell
a61fcbd68d Make Button class concrete (#2244) 2020-01-15 18:59:51 -08:00
Thad House
fe597eeba1 Fix SPI DIO count for sim (#2272)
Only 26 DIO were detectable, not 31.
2020-01-15 18:58:14 -08:00
Jonathan Leitschuh
e213a47efd Official Gradle Wrapper Validation GitHub Action (#2273)
See: https://github.com/gradle/wrapper-validation-action
2020-01-15 14:21:50 -08:00
Peter Johnson
dcb96cb50c TrajectoryGenerator: Allow replacement of error reporting function (C++) (#2267)
C++ version of #2234.
2020-01-13 20:36:16 -08:00
Austin Shalit
60d48fec57 Fix Java static colors having zero values (#2269)
Also add test for this.
2020-01-13 12:21:44 -08:00
Austin Shalit
ee8475d21f Run wpiformat (#2270) 2020-01-13 12:19:08 -08:00
Peter Johnson
f47e318131 C++ units: Interoperate with Windows headers min/max (#2268) 2020-01-12 22:52:36 -08:00
Thad House
cb66bcca3c Add callback handlers for LiveWindow (#2053)
Fixes #2223
2020-01-12 22:37:24 -08:00
Simon Abrelat
73302f6162 Fix color name typos (#2265) 2020-01-12 22:15:19 -08:00
Oblarg
cba21a768f Fix C++ JoystickButton and POVButton (#2259)
C++ JoystickButton and POVButton were both nonfunctional due to slicing when trigger passes itself by value to the button scheduler it creates.

Fix is to remove the virtual Get() method entirely and use only the m_isActive functor; since the subclass now passes the button condition back as a functor to the base class, in which it's stored as a member, it will now still work after being sliced.
2020-01-12 14:57:28 -08:00
Peter Johnson
822e75ec45 Simulator GUI: Handle save file having window size=0 (#2260)
This should never happen, but if it does, it's not recoverable without
either deleting imgui.ini or editing it manually.
2020-01-12 01:37:53 -08:00
Peter Johnson
108ddfa1b4 Fix Pi Camera auto exposure property name (#2258) 2020-01-11 15:04:29 -08:00
Prateek Machiraju
d4c8ee5915 Add Axis enum in XboxController (#2253) 2020-01-10 23:43:19 -08:00
Peter Johnson
ab9647ff5b CommandScheduler: Don't store NetworkTableEntry 2020-01-10 23:42:18 -08:00
Peter Johnson
6666d3be42 SendableBuilder: Allow multiple updateTable functions
This fixes cases like CommandScheduler not working when added to both
LiveWindow and SmartDashboard.
2020-01-10 23:42:18 -08:00
Peter Johnson
795086b4cf Fix Demangle when used standalone (#2256) 2020-01-10 23:41:40 -08:00
Peter Johnson
56765cf49a C++ CommandBase: Don't add to LiveWindow (#2255) 2020-01-10 20:37:49 -08:00
Peter Johnson
bf7012fa2d Fix new CommandScheduler.cancelAll() (#2251)
When called outside the run loop, it would result in a CME in Java.
2020-01-10 16:10:16 -08:00
Peter Johnson
10e8fdb724 Make C++ IterativeRobotBase and RobotBase constructor and destructor public (#2242) 2020-01-08 23:17:12 -08:00
Peter Johnson
790dc552ca Add quirks support for Pi camera (#2241)
- Valid video modes (native modes plus some low-res modes)
- Exposure setting
2020-01-07 20:21:28 -08:00
Peter Johnson
0ec8ed6c05 Make C++ controller using declarations public (#2240) 2020-01-06 23:30:47 -08:00
Tyler Veness
832693617f Add missing definition for PIDController::SetPID() (#2239)
Fixes #2238.
2020-01-06 21:17:16 -08:00
sciencewhiz
772ef8f961 Update Maven location to artifactory (#2235) 2020-01-06 20:13:42 -08:00
Peter Johnson
95b6cd2dd9 TrajectoryGenerator: Allow replacement of error reporting function (#2234)
This is needed to avoid use of DriverStation if used from desktop applications
such as PathWeaver.
2020-01-05 16:01:31 -08:00
sciencewhiz
ce1ac17dfb Remove experimental from new command example descriptions (#2226) 2020-01-04 19:57:31 -08:00
Thad House
b2f7a6b651 Add clarification to LED about length and # of drivers (#2231) 2020-01-04 19:57:10 -08:00
Peter Johnson
bedbef7999 Revert "Remove -no-module-directories flag from javadoc build (#2201)" (#2229)
This reverts commit f9a11cce5e.
2020-01-04 19:52:43 -08:00
Thad House
bc159a92a7 Default sim voltage to 12v, make user rails active (#2224) 2020-01-04 15:07:47 -08:00
Austin Shalit
f50d710a5e Make color ctor public (#2222) 2020-01-04 08:28:18 -08:00
Peter Johnson
bc8f68bec7 Add sim HAL_WaitForCachedControlData (#2221) 2020-01-03 22:38:45 -08:00
Peter Johnson
32c62449be Add ArrayRef overloads to new command classes (#2216)
Also default requirements to {} in all cases for consistency.
2020-01-01 20:09:17 -08:00
Tyler Veness
6190fcb237 Run wpiformat (#2218) 2020-01-01 20:04:56 -08:00
Declan Freeman-Gleason
012d93b2bd Use an explicit stack instead of recursion when parameterizing splines (#2197)
This PR changes the spline parameterizer to use an explicit stack instead of recursion. This is motivated by the fact that splines with adjacent waypoints with approximately opposite headings will never parameterize. In this case the parameterizer subdivides these malformed splines fine for a while, and then gets stuck parameterizing infinitely on some interval. In the recursive approach, this would lead to a stack overflow. We could implement a recursion depth counter (this is what my team did on our similar trajectory code last season), but it's hard to choose a good number for max depth because the initial amount of stack used varies based on how the user calls Parameterize.

A good solution for this is converting the recursion to an "explicit stack," which basically simulates recursion, but allows us to have a much larger maximum stack size. Because we avoid the stack overflow, we can instead throws a more informative MalformedSplineException. If the user is using the TrajectoryGenerator instead of the SplineParameterizer directly then the TrajectoryGenerator will go ahead and catch the exception, return a harmless empty trajectory, and report and error to the driver station.
2020-01-01 18:23:08 -08:00
Matt
222669dc2c Fix trapezoidal profile PID controller setpoint bug (#2210)
Co-Authored-By: Austin Shalit <austinshalit@gmail.com>
2020-01-01 15:23:25 -08:00
Peter Johnson
abe25b795b TrajectoryUtil.toPathweaverJson: Create parent directories (#2214) 2020-01-01 13:35:04 -08:00
sciencewhiz
354185189c Update ProjectYear to 2020 (#2212) 2020-01-01 11:14:31 -08:00
sciencewhiz
f14fe434a1 Add (Old) qualifier to old subsystem (#2211) 2019-12-31 23:00:35 -06:00
Prateek Machiraju
e874ba9313 Add Color classes for use with AddressableLED (#2127)
Both floating point and 8-bit integer classes are included, as well as a wide selection of color constants.

Co-authored-by: Austin Shalit <austinshalit@gmail.com>
2019-12-30 00:01:20 -06:00
Peter Johnson
96348e835a Fix C++ SendableRegistry::AddChild() (#2207)
Add a Sendable* overload so pointers to sendable objects work appropriately.
Otherwise an AddLW(this) in a child (which is a Sendable*) could be a
different pointer than a void* to the same object.

For example:
  AnalogInput constructor calls AddLW(this)
  AnalogPotentiometer constructor calls AddChild(analog input pointer)

Also add handling for the child object moving (if it's Sendable).
2019-12-29 23:37:14 -06:00
Oblarg
d91796f8d2 fix clang-format version number (#2206) 2019-12-29 21:31:26 -06:00
Peter Johnson
9abce8eb06 Fix subsystem LiveWindow usage (#2202) 2019-12-29 21:28:38 -06:00
Peter Johnson
8b4508ad53 Use default path for networktables.ini in simulation (#2205) 2019-12-29 18:55:02 -06:00
Oblarg
5b7dd186d2 Add templates for new commands for vscode plugin (#2016) 2019-12-29 15:02:49 -06:00
Peter Johnson
6ea13ea8f3 ntcore: Add support for local-only operation (#2204)
StartLocal() causes future calls to StartServer() or StartClient() to have
no effect. StopLocal() re-enables these calls.
2019-12-29 14:56:41 -06:00
Oblarg
44bcf7fb4d Java examples: use non-static imports for constants (#2191) 2019-12-29 14:55:49 -06:00
Oblarg
c7a1dfc0bc Add SlewRateLimiter class (#2192)
This is extremely useful for implementing various "ramping" functions
(such as voltage ramps, setpoint ramps, etc). Usage is straightforward;
it behaves like all of our other filter classes. C++ version is unit-safe.
2019-12-29 13:36:28 -06:00
Peter Johnson
a12bb447e4 Fail cmake build if python3 generate_numbers.py fails (#2203) 2019-12-29 13:12:00 -06:00
Declan Freeman-Gleason
c4bd54ef44 Add JNI binding to suppress driver station error/warning messages (#2200)
This is to allow suppressing an ugly stack trace/error message in a unit test in #2197. It doesn't support the full HALSIM_SetSendError callback stuff (i.e. you can only suppress, not intercept, stack traces with this).
2019-12-27 21:11:26 -06:00
Austin Shalit
f9a11cce5e Remove -no-module-directories flag from javadoc build (#2201) 2019-12-27 10:19:49 -06:00
Peter Johnson
6008671c30 Report WPILib version as part of usage reporting (#2199) 2019-12-26 22:34:10 -06:00
Peter Johnson
7b952d599d Add usage reporting for many new things (#2184)
- new CommandScheduler
- kinematics and odometry classes
- new PIDController
- ProfiledPIDController
- TrapezoidProfile (reported in Constraints class)

Also update instances.txt to match latest NI version.

One side effect is that a couple of classes are no longer constexpr.
2019-12-25 00:42:14 -06:00
Peter Johnson
93cdf68694 Add Constants.cpp for MecanumControllerCommand example (#2196) 2019-12-24 16:19:02 -06:00
Peter Johnson
0c6f24562f Fix bug in ULEB128 decoding (#2195) 2019-12-24 14:12:42 -06:00
Thad House
bdc1cab013 Add support for configuring SPI Auto Stall Config (#2193) 2019-12-24 12:52:58 -06:00
Prateek Machiraju
3259cffc63 Add transform methods to Trajectory (#2187) 2019-12-23 13:16:30 -06:00
Oblarg
67b59f2b31 Minor improvements/fixes to new command framework (#2186) 2019-12-23 01:09:25 -06:00
sciencewhiz
1ce24a7a2f Add 2020 speed controllers (#2188)
Add CTRE TalonFX (PWMTalonFX)
Add Playing with Fusion Venom (PWMVenom)
2019-12-22 13:51:43 -06:00
Prateek Machiraju
635882a9f7 Add getter for initial pose in Trajectory (#2180) 2019-12-21 06:57:39 -08:00
Thad House
71a22861eb Use ManagedStatic for CameraServer (#2174) 2019-12-20 14:20:38 -08:00
Thad House
9cb69c5b46 Add a way to pass in a preconstructed value to ManagedStatic (#2175)
A lot of our cases don't need the lazy construction, but do need manual destruction.
2019-12-20 14:06:22 -08:00
Thad House
5e08bb28f8 Add docs and lifecycle tasks for faster dev builds (#2182) 2019-12-20 13:48:26 -08:00
Oblarg
ea4d1a39e1 Update characterization values to match real robot (#2183)
This is in preparation for an end-to-end trajectory tutorial example.

Co-Authored-By: Dalton Smith <gamefollower26@gmail.com>
2019-12-20 13:46:13 -08:00
Prateek Machiraju
31b588d961 Fix ArmFeedforward Javadocs (#2176) 2019-12-15 14:34:18 -08:00
Thad House
0b80d566ad Use ChipObject HMB function for LED (#2173)
It's fixed in v9 and up.
2019-12-14 21:15:32 -08:00
Peter Johnson
f8294e689b Sim GUI: Add a bit of spacing to the analog inputs (#2170)
This helps make it clear they are separate controls.
2019-12-14 10:49:01 -08:00
Peter Johnson
b78f115fcf Work around VS2019 16.4.0 bugs (#2171)
Work around frontend bug in scoped_lock and code generation bug in reverse_iterator in gtest.

See https://github.com/google/googletest/pull/2635
2019-12-14 10:48:19 -08:00
sciencewhiz
b468c51251 Change AddressableLED example to use consistent PWM port (#2168) 2019-12-11 15:39:36 -08:00
Prateek Machiraju
023c088290 Add toString() to relevant kinematics classes (#2160) 2019-12-09 21:35:43 -08:00
Thad House
8a11d13a39 Fix C++ DutyCycleEncoder int constructor (#2166) 2019-12-09 21:35:00 -08:00
Claudius Tewari
daa81c64a7 Minor javadoc fix in SwerveDriveKinematicsConstraint (#2167) 2019-12-09 21:34:32 -08:00
Peter Johnson
e20d96ea4e Use __has_include for WPILib.h (#2164)
Now that commands and cameraserver libraries are no longer direct dependencies,
it's necessary to check for their presence.
2019-12-07 21:39:58 -08:00
Thad House
a76d006a07 Update native-utils to 2020.7.2 (#2161)
Fixes a bug where source directories were being added to the header search path
2019-12-07 17:18:50 -08:00
Thad House
24c031d692 Increase SPI auto byte count to allow 32 bytes to be sent (#2163)
The FPGA now supports 32 bytes.
2019-12-07 17:18:25 -08:00
Thad House
6b4eecf5fe Add hidden functions to get the SPI system and SPI DMA (#2162)
With the addition of stall configuration, its not very clear how it works, and seems like it would be different
per use. So adding ways to manually get them, so the functionality can be figured out how to be used.
2019-12-07 17:16:14 -08:00
Oblarg
ccdd0fbdb2 Add TrapezoidProfile external PID examples (#2131) 2019-12-07 13:37:54 -08:00
Tyler Veness
5c6b8a0f45 Replace std::is_pod_v with std::is_standard_layout_v (#2159)
The former is deprecated in C++20.
2019-12-07 13:34:52 -08:00
Thad House
67d2fed685 Add DutyCycleEncoder channel constructor (#2158)
Avoids extra boilerplate at user level.
2019-12-06 20:58:04 -08:00
Thad House
d8f11eb149 Hardcode channels for LSB weight (#2153)
Avoids a mutex and a lookup.
2019-12-06 20:56:40 -08:00
Thad House
b2ae75acd8 Add way to disable "no extensions found" message (#2134)
We want it enabled by default, but there have been requests for a way to disable it.
2019-12-06 20:55:36 -08:00
Austin Shalit
4f951789fe Build testbench tests online inorder to improve speed (#2144)
* Attempt to build testbench tests online inorder to improve speed

* Fix contianer reference

* Start to remove jenkins shell script

* Change job names

* Remove sshpass

* Remove teststand code

* Copy test results back

* Fix build by using athena container

* Fail if any command fails

* Remove jenkins test script

* Remove name argument

* Fix param count

* Add build display name

* Fix scp to copy into dir

* Update display names

* Update stage name

* Fix test results scp

* Create local test report dir

* Remove commented out old code

* Remove force pseudo-terminal allocation

* Remove extra variables

* Update readme

* Remove old test runs

* Update license header
2019-12-06 17:46:29 -05:00
Austin Shalit
005c4c5beb Try catch around task dependencies to fix loading in editor (#2156) 2019-12-06 11:46:21 -08:00
Tyler Veness
34f6b3f4c0 Fix C++ RamseteCommand param doxygen (#2157) 2019-12-05 23:54:32 -08:00
Oblarg
f7a93713fa Fix up templated TrapezoidProfile classes (#2151)
* Fix two-phase name lookup bug

* Fix param in ProfiledPIDCommand constructor overload

* Fix ProfiledPIDCommand/Controller
2019-12-04 20:40:37 -08:00
Tyler Veness
8c2ff94d70 Rename MathUtils to MathUtil for consistency with other util classes (#2155) 2019-12-04 20:39:12 -08:00
Thad House
d003ec2dc9 Update to 2020v9 image (#2154)
- Fix VISA include and FPGA header
- Fix missing VISA lib from executables
2019-12-04 20:38:43 -08:00
Peter Johnson
8e7cc3fe78 Add user-friendly SimDeviceSim wrappers (#2150)
This makes unit testing with SimDevice devices much easier.
2019-12-02 23:27:33 -08:00
Matt
6c8f6cf479 Fix bug in cubic and quintic hermetic spline generation (#2139)
Add documentation for spline derivatives and explicitly zero matrices.
2019-12-01 21:29:52 -08:00
Peter Johnson
e37ecd33ae Sim GUI: Add support for LED displays (#2138)
LED displays connect the LEDs in various ways (column major vs row major,
different starting locations, serpentine connection order), so add
configuration parameters for these options.
2019-12-01 21:28:02 -08:00
Prateek Machiraju
57c5523d67 Fix documentation in RamseteCommand (#2149) 2019-12-01 21:27:02 -08:00
Matt
7b9c6ebc2f Fix wpiutilJNIShared linkage typo in wpilibj (#2143) 2019-12-01 13:25:46 -08:00
Oblarg
9a515c80f8 Template C++ LinearFilter to work with unit types (#2142) 2019-11-30 23:12:02 -08:00
Prateek Machiraju
5b73c17f25 Remove encoder velocities methods in DifferentialDriveOdometry (#2147)
It doesn't make sense to continue to provide a less accurate method of performing odometry
when a more accurate method using distances exists.

This also removes the need to pass DifferentialDriveKinematics to the constructor.
2019-11-30 23:10:29 -08:00
Banks T
b8c1024261 Fix PS3Eye VID and PID (#2146) 2019-11-30 12:35:47 -08:00
Prateek Machiraju
2622c6c291 Add default values for b and zeta in RamseteController (#2145)
Values b=2.0 and zeta=0.7 have been well-tested to produce desirable results.
2019-11-29 21:16:01 -08:00
Austin Shalit
f66ae59992 Add HSV helpers to AddressableLED (#2135)
Also change the setLED() method to setRGB() for consistency and clarity.

Add rainbow example to demonstrate HSV usage.
2019-11-29 15:16:57 -08:00
Oblarg
5e97c81d80 Add MedianFilter class for moving-window median (#2136)
This kind of filter is extremely useful for signals that are susceptible to sudden
outliers - ultrasonics, 1-D LIDAR, and results from vision processing are all
good use-cases.

This also modifies the existing ultrasonic examples accordingly.
2019-11-29 15:13:40 -08:00
Tyler Veness
f79b7a058a Remove unnecessary constructor arg for LinearFilter's circular buffers (#2140)
They are initialized in LinearFilter's constructor, so the default is
never used.
2019-11-28 23:27:20 -08:00
Austin Shalit
e49494830f Replace Jenkins with Azure agent (#1914) 2019-11-25 22:00:35 -08:00
sciencewhiz
b67d049ac2 Check status of PDP CAN reads (#2126)
Fixes #2124
2019-11-25 21:47:35 -08:00
Peter Johnson
70102a60b7 SendableRegistry.foreachLiveWindow: Prevent concurrent modification (#2129)
Copy the internal map values into an array before iterating.

In C++, change to recursive mutex as well.
2019-11-25 21:47:06 -08:00
Oblarg
6dcd2b0e2c Improve various subsystem APIs (#2130)
Improves the APIs for various prebuilt subsystems (PIDSubsystem, TrapezoidProfileSubsystem, ProfiledPIDSubsystem). Addresses #2128, and also changes the rather cumbersome getSetpoint API to a more intuitive setSetpoint one. Updates examples to match.
2019-11-25 21:46:47 -08:00
Thad House
ce3973435e HAL_CAN_ReceiveMessage: return MessageNotFound if no callbacks registered (#2133) 2019-11-25 21:45:44 -08:00
Thad House
3fcfc8ea72 Fix double disable segfaulting interrupts (#2132)
Also fixes DigitalOutput not closing correctly.
2019-11-25 21:43:58 -08:00
sciencewhiz
6ceafe3cd0 Fix class reference for logger (#2123) 2019-11-23 07:47:02 -08:00
Peter Johnson
b058dcf64e Catch exceptions generated by OpenCV in cscore JNI (#2118) 2019-11-22 08:12:17 -08:00
Tyler Veness
0b9307fdf3 Remove unused parts of .styleguide files (#2119) 2019-11-22 06:34:58 -08:00
Peter Johnson
39be812b2e Fix C++ ArmFeedforward (#2120) 2019-11-22 06:31:32 -08:00
Oblarg
21e957ee42 Add DifferentialDrive voltage constraint (#2075) 2019-11-21 21:43:02 -08:00
Oblarg
e0bc97f66b Add ProfiledPIDSubsystem example (#2076) 2019-11-21 20:55:16 -08:00
Modelmat
3df44c874d Remove Rotation2d.h wpi/math include (#2117) 2019-11-21 19:54:29 -08:00
CTT
a58dbec8aa Add holonomic follower examples (#2052) 2019-11-21 19:52:56 -08:00
Tyler Veness
9a8067465c Fix incomplete .styleguide (#2113)
Also clean up other .styleguides.

Fixes #2111.
2019-11-20 22:44:18 -08:00
Tyler Veness
ffa4b907c0 Fix C++ floating point literal formatting (#2114)
Found formatting errors with this regex
"([^a-z0-9\.]\.[0-9]|[^a-z0-9\.][0-9]\.[^a-z0-9\.])" and ignored false
positives.

Fixes #2112.
2019-11-20 21:48:15 -08:00
Oblarg
3d1ca856b2 Fix missing typename and return type (#2115) 2019-11-20 21:46:33 -08:00
Austin Shalit
5f85457a97 Add usage reporting for AddressableLED (#2108) 2019-11-20 20:13:39 -08:00
Austin Shalit
4ebae17123 Enforce leading/trailing zeros in Java numeric constants (#2105)
Enforce that integer literals must not have leading zeros and that floating point literals must have leading or trailing zeros in Java.
2019-11-20 20:13:15 -08:00
Oblarg
fa85fbfc1c Template C++ TrapezoidProfile and ProfiledPIDController on units (#2109) 2019-11-20 20:11:46 -08:00
Thad House
f62e23f1af Add Doxygen for new HAL interfaces (#2110) 2019-11-20 16:21:07 -08:00
Thad House
5443fdabc1 Directly construct PWM port from HAL, avoid wpilib PWM object (#2106) 2019-11-20 14:48:14 -08:00
Austin Shalit
c0e36df9d8 Standardize on PWMVictorSPX in examples (#2104) 2019-11-19 21:48:22 -08:00
Oblarg
8c4d9f5415 Add TrapezoidProfileSubsystem (#2077)
Adds a subsystem that continually runs a TrapezoidProfile, for composition with offboard PID controllers.
2019-11-19 12:38:42 -08:00
Prateek Machiraju
45201d15fc Add encoder distance overload to DifferentialDriveOdometry (#2096)
Also force encoders to be reset to zero on pose reset.
2019-11-19 09:56:34 -08:00
Tyler Veness
845aba33fe Make feedforward classes constexpr (#2103)
ArmFeedforward::Calculate() can't be made constexpr because std::cos()
and thus units::math::cos() is not constexpr.

Fixes #2101.
2019-11-19 06:47:59 -08:00
Thad House
500c43fb84 Add examples for DMA, DutyCycle, DutyCycleEncoder and AddressableLED (#2100) 2019-11-18 22:12:17 -08:00
Prateek Machiraju
5891628112 Use DifferentialDriveWheelSpeeds in RamseteCommand ctor (#2091) 2019-11-18 22:11:05 -08:00
Thad House
b37b68daaf Add JRE deployment to MyRobot Deploy (#2099) 2019-11-18 19:52:56 -08:00
Oblarg
0e83c65d27 Fix small logic error in ParallelDeadlineGroup (#2095) 2019-11-18 15:33:45 -08:00
Thad House
6f6c6da9f5 Updates to addressable LED (#2098)
Only PWM Headers are supported, so enforce that.

Also fixes some init checks and init order checks.
2019-11-18 15:25:04 -08:00
Thad House
1894219ef6 Fix devmain package in commands (#2097) 2019-11-18 15:24:04 -08:00
Peter Johnson
77a9949bbf Add AddressableLED simulation GUI support 2019-11-18 00:51:59 -08:00
Peter Johnson
a4c9e4ec28 Add AddressableLED simulation support 2019-11-18 00:51:59 -08:00
Thad House
8ed2059074 Add AddressableLED (#2092) 2019-11-17 16:39:38 -08:00
Thad House
59507b12dc Bump to 2020 v7 image (#2086) 2019-11-15 21:51:31 -08:00
Peter Johnson
5d39bf8065 Make halsimgui::DrawLEDs() values parameter const (#2088) 2019-11-15 20:29:51 -08:00
Prateek Machiraju
841ef91c0f Use gyro angle instead of robot angle for odometry (#2081)
The odometry classes previously took in the robot angle as an argument, meaning that users had to take care of offsetting the gyro themselves to accurately report the robot angle. This change will make it so that users will not have to worry about resetting gyros and adding offsets themselves, as this will be handled by the odometry classes.
2019-11-15 17:34:10 -08:00
Tyler Veness
1b66ead49d Use standard constant for pi instead of 3.14 (#2084) 2019-11-15 17:33:18 -08:00
Thad House
db2c3dddd7 Use DMA Global Number for DMA Index (#2085) 2019-11-15 17:32:29 -08:00
Thad House
82b2170feb Add DMA support to HAL and WPILibC (#2080) 2019-11-14 22:52:34 -08:00
Thad House
8280b7e3af Add DutyCycleEncoder and AnalogEncoder (#2040) 2019-11-14 22:51:33 -08:00
Thad House
5510960068 Use kNumSystems for DutyCycle count in Ports (#2083) 2019-11-14 12:15:47 -08:00
Thad House
df10652183 Remove release configs of deploy in MyRobot (#2082)
Bug in lower level library causes having both be broken. So for now just removed release.

Issue created in low level library to fix
2019-11-14 12:15:36 -08:00
Thad House
bf5388393e Add deploy options to myRobot (#2079)
Will only deploy to USB by default, and will not deploy the JRE, but will deploy a Java app.
2019-11-13 22:45:19 -08:00
Thad House
b7bc1ea745 Update to 2020v6 image (#2078) 2019-11-13 21:35:52 -08:00
Thad House
708009cd20 Update to gradle 6.0 (#2074) 2019-11-12 17:14:04 -08:00
Thad House
3cce61b89f Add SmartDashboard::GetEntry function in C++ (#2064)
Existed in Java already.
2019-11-12 17:11:32 -08:00
CTT
565e1f3e79 Fix spelling in MecanumDriveOdometry docs (#2072) 2019-11-11 23:25:09 -08:00
Peter Johnson
1853f7b6b7 Add timing window to simulation GUI
This shows the FPGA time and notifier timing, and has buttons to
start/pause/step the simulation.

The GUI also pauses DS new data notifications when paused.  This could be
done globally instead by blocking NotifyNewData at the HAL level?
2019-11-11 22:03:29 -08:00
Peter Johnson
c5a0497124 Add simulation pause/resume/step support
Calling HALSIM_PauseTiming pauses the FPGA clock and notifiers.
Calling HALSIM_ResumeTiming resumes the FPGA clock and notifiers.
Calling HALSIM_StepTiming steps the FPGA clock and runs applicable notifiers.

This will effectively pause TimedRobot and any other notifier-based events,
but of course will not pause user threads that do not use the notifier (e.g.
image processing).
2019-11-11 22:03:29 -08:00
Peter Johnson
f5446c7409 Add Notifier HALSIM access 2019-11-11 22:03:29 -08:00
Peter Johnson
3e049e02f0 Add name to HAL Notifier 2019-11-11 22:03:29 -08:00
David Vo
2da64d15f6 Make usage reporting enums type match (#2069)
This changes the C++ HALUsageReporting enums to have an
explicit type which matches the HAL_Report parameter
types.  In practice this shouldn't change much except
for tooling that might be parsing this header.
2019-11-11 21:38:49 -08:00
David Vo
f04d95e50f Make FRCUsageReporting.h C-compatible (#2070)
Now that HAL_Report has been moved into FRCUsageReporting.h,
this should also be C-compatible.

This also removes the C++ ifdef guard in HAL.h.
2019-11-11 21:38:24 -08:00
sciencewhiz
d748c67a54 Generate docs for command libraries and fix doclint enable (#2071) 2019-11-11 21:38:04 -08:00
Prateek Machiraju
55a7f2b4ad Add template for old command-based style (#2031) 2019-11-10 23:20:33 -08:00
CTT
486fa9c696 Add XboxController examples for arcade and tank drive (#2058) 2019-11-10 22:53:17 -08:00
Oblarg
e3dd1c5d77 Fix small bug in SplineHelper (#2061)
Also add comments for clamped cubic solution.
2019-11-10 22:52:24 -08:00
Oblarg
7dc7c71b58 Add feedforward components (#2045)
Add helper classes for computing feedforwards with parameters supplied by the characterization tool.
2019-11-09 20:16:42 -08:00
Oblarg
5f33d6af12 Fix ProfiledPIDSubsystem parameter name (#2017)
Change from goal to setpoint (these are two different things).
2019-11-09 09:16:50 -08:00
sciencewhiz
94843adb8f Standardize documentation of Speed Controllers bounds (#2043)
Some were in constructor docs, some in init function docs, and some
inline in code. Move them all to class docs.
2019-11-09 09:14:53 -08:00
Thad House
9bcff37b93 Add HAL specific version of wpi_setError (#2055)
Cleans up error writing, and allows fewer headers to be included in many of the wpilibc cpp files.

This removes all usages of the hal/HAL.h header.
2019-11-08 22:53:20 -08:00
Thad House
326aecc9a0 Add error message for CAN Write Overrun (#2062) 2019-11-08 22:51:11 -08:00
Oblarg
00228678d4 Add requirements param to more Command APIs (#2059)
Assorted improvements to the ergonomics of declaring requirements in the new
command framework. C++ requirements list parameters have been defaulted
to an empty list, some missing C++ requirements list parameters have been
added, and both C++ and Java have been given requirements list params in
various InstantCommand wrapper methods (#2049), whose value is
forwarded to the command.
2019-11-08 18:30:30 -08:00
Thad House
ff39a96cee Make DigitalOutput a DigitalSource (#2054)
It's perfectly safe to use as a DigitalSource, and can enable some cool tricks.
2019-11-07 20:03:43 -08:00
Thad House
5ccad2e8a4 Fix frc2::Timer returning incorrect timestamp values (#2057) 2019-11-07 20:02:27 -08:00
Thad House
629e95776a Add VendorDeps JSON files for command libraries (#2048)
Add commandversion flag to the examples and templates json files.
2019-11-07 17:38:07 -08:00
Thad House
6858a57f72 Make notifier command tests a lot more lenient (#2056)
They don't need to be testing timing, just that the command starts and stops.
2019-11-07 17:26:29 -08:00
Thad House
0ebe32823a Fix MyRobotStatic accidentally linking to shared command libs (#2046) 2019-11-06 14:06:04 -08:00
Thad House
384d00f9e6 Fix various duty cycle bugs (#2047) 2019-11-06 14:05:25 -08:00
Thad House
1f6850adf2 Add CAN Manufacturer for Studica (#2050) 2019-11-06 14:04:27 -08:00
Peter Johnson
7508aada93 Add ability to end startCompetition() main loop (#2032)
This is useful for both cleanly exiting from simulation and for unit testing
at a framework level.

This change required removing move constructor/assignment from IterativeRobot.
2019-11-05 21:33:09 -08:00
Peter Johnson
f5b4be16db Old C++ Command: Make GetName et al public (#2042)
These used to be effectively public due to SendableBase, and are public
in the Java version.
2019-11-05 20:53:40 -08:00
Peter Johnson
e6f5c93ab1 Clean up new C++ commands (#2027)
- Remove use of std::set. The only place std::set was actually used was in ParallelRaceGroup,
but this was of minimal utility as ParallelRaceGroup checked for duplicate subsystem
requirements, so it would be very unusual to end up with duplicate commands
in any case; replaced it with a vector.
- Remove use of std::unordered_map except for SelectCommand. Replaced with vector.
- Use pImpl idiom for CommandScheduler
- Minimize include files (remove unnecessary ones)
- Reformat include file order for consistency
2019-11-05 20:52:49 -08:00
Thad House
39f46ceab6 Don't allow rising and falling values to be read from AnalogTrigger (#2039)
They can't be caught from user code
2019-11-05 20:42:01 -08:00
Thad House
d93aa2b6b2 Add missing lock in FRCDriverStation (#2034)
Switch newDataCounter to atomic
2019-11-05 20:41:16 -08:00
Austin Shalit
114ddaf81f Fix duplicate encoders in examples (#2033) 2019-11-03 09:08:05 -08:00
Peter Johnson
f22d0961e3 Sim GUI: Add duty cycle support 2019-11-02 21:43:57 -07:00
Peter Johnson
3262c2badb Sim GUI: Use new multi-channel PDP getter function 2019-11-02 21:43:57 -07:00
Peter Johnson
96d40192ae Revert accidental change to MyRobot.cpp (#2029) 2019-11-02 21:06:22 -07:00
carbotaniuman
ed30d5d40e Add JSON support for Trajectories (#2025) 2019-11-02 11:35:03 -07:00
Peter Johnson
2b6811eddb Fix null pointer dereference in C++ CommandScheduler (#2023)
Java has a null check that was missing in C++ when adding default commands.
2019-11-01 23:42:01 -07:00
Thad House
1d695a1660 Add FPGA Duty Cycle support (#1987) 2019-11-01 23:41:30 -07:00
Thad House
509819d83f Split the two command implementations into separate libraries (#2012)
This will allow us at the user code side to determine to include old commands, new commands or both.
2019-11-01 21:58:54 -07:00
Thad House
2ad15cae19 Add multi PDP getter and sim PCM/PDP multi arg functions (#2014) 2019-11-01 21:55:35 -07:00
Thad House
931b8ceefd Add new usage reporting types from 2020v5 (#2026) 2019-11-01 21:54:17 -07:00
Tyler Veness
0b3821eba3 Change files with CRLF line endings to LF (#2022) 2019-11-01 20:26:05 -07:00
Thad House
6f159d1426 Add way to atomically check for new data, and wait otherwise (#2015) 2019-11-01 17:09:28 -07:00
Austin Shalit
a769f1f227 Fix bug in RamseteCommand (using degrees instead of radians) (#2020) 2019-11-01 13:21:02 -07:00
Oblarg
c5186d8159 Clean up PIDCommand (#2010)
PIDCommand uses a function based (callback) model, so functions designed for use in derived classes are of limited utility.
2019-11-01 13:11:55 -07:00
Oblarg
9ebd23d61e Add setVoltage method to SpeedController (#1997)
Add a voltage-compensated setVoltage method to SpeedController, which is sorely needed to help teams use feedforward-based controls effectively. Also uses correct units on the cpp side.

Also update relevant examples.
2019-11-01 09:32:40 -07:00
Prateek Machiraju
f6e311ef86 Fix SplineHelper bug (#2018)
Add unit test to check interior waypoints
2019-11-01 09:28:11 -07:00
Oblarg
f33bd9f050 Fix NPE in RamseteCommand (#2019) 2019-11-01 09:26:48 -07:00
Thad House
1c1e0c9a6a Add HAL_SetAllSolenoids to sim (#2004) 2019-10-30 21:29:35 -07:00
Thad House
ea9bb651a3 Remove accidental OpenCV link from wpilibc shared library (#2013) 2019-10-30 21:28:45 -07:00
Oblarg
cc07425182 Change command decorators to return implementation (#2007)
Changes Command decorators to return actual implementation classes rather than Commands. Previously, decorated commands were not Sendable, which was a problem. Also, there's no real reason not to expose the implementation details here, as we're extremely unlikely to change the implementations in the future.
2019-10-30 21:28:08 -07:00
Thad House
16b34cce20 Remove IterativeRobot templates (#2011)
With the class being deprecated, new projects shouldn't be created with it
2019-10-30 21:26:30 -07:00
Thad House
669127e49c Update intellisense to work with Beta 2020 code (#2008)
Needed to fix case when both rio and raspbian compilers installed, along with C++17 intellisense.
2019-10-29 21:36:13 -07:00
Thad House
9dc30797e4 Fix usage reporting indices (#2009)
According to NI, 0 is unspecified, and all the indices need to be
index + 1, so the first index becomes 1.
2019-10-29 21:34:10 -07:00
Thad House
f6b844ea30 Move HAL Interrupt struct to anonymous namespace (#2003) 2019-10-28 22:32:28 -07:00
Thad House
a72f809911 Add extern C to DigitalGlitchFilterJNI (#2002) 2019-10-28 22:30:04 -07:00
Thad House
916596cb01 Fix invalid examples json, add validator (#2001) 2019-10-28 20:10:05 -07:00
Peter Johnson
5509a8e968 Use constexpr for all example constants
Also make DifferentialDriveKinematics constructor constexpr.
2019-10-28 09:19:41 -07:00
Peter Johnson
0be6b64756 Use constexpr for DifferentialDriveKinematics 2019-10-28 09:19:41 -07:00
Thad House
936627bd94 wpilibc: Remove direct CameraServer dependency (#1989)
This makes linking easier, particularly for third party vendors and other language wrappers.
2019-10-27 08:37:30 -07:00
Prateek Machiraju
8e333c0aad Use FPGA Time instead of wall clock time for odometry (#1996) 2019-10-27 07:57:35 -07:00
sciencewhiz
d4430b765e Gearsbot example: Use standard argument order (#1995)
The convention is to put the subsystem last.
2019-10-27 06:28:29 -07:00
Oblarg
75438ab2ce Add RamseteCommand (#1951) 2019-10-26 21:33:41 -07:00
Thad House
989df1b461 Bump Native Utils and OpenCV dependencies (#1993)
OpenCV doesn't change anything other then the hash file. NativeUtils is needed to get the newest compiler.
2019-10-26 16:21:29 -07:00
Oblarg
dbc33b61e1 Fix Timer usage in TrapezoidProfileCommand (#1992) 2019-10-26 12:50:30 -07:00
Oblarg
79f8c5644a Add TrapezoidProfileCommand (#1962) 2019-10-26 09:58:13 -07:00
Prateek Machiraju
9440edf2b5 Refactor TrajectoryGenerator (#1972) 2019-10-26 09:39:47 -07:00
Oblarg
73a30182c3 Add frc2::Timer (#1968)
This is a unit-safe version of frc::Timer.
Undo previous (#1815) deprecation of parts of frc::Timer.
2019-10-26 08:21:40 -07:00
Banks T
36ea865edc Add toString for geometry and trajectory classes (#1991) 2019-10-26 08:18:56 -07:00
Oblarg
cbe05e7e8a Update ProfiledPIDController API (#1967) 2019-10-24 20:37:55 -07:00
Tyler Veness
d04eb35465 Deprecate old PID classes (#1964)
PIDBase was only used by the old PIDController, which is deprecated.
PIDInterface is only used by PIDBase, and that's deprecated by this
commit.
2019-10-24 20:32:31 -07:00
Thad House
02264db69c Add JNI dependencies to myRobotCpp (#1980)
That way it's a bit easier to test the Java builds.
2019-10-24 20:31:07 -07:00
Banks T
2a76c996eb Use VID/PID detection for PS3Eye (#1977) 2019-10-24 20:28:21 -07:00
Thad House
a3820bbdfa Remove HAL_BaseInitialize (#1981) 2019-10-24 20:26:11 -07:00
Thad House
a83fb47933 Update to 2020v5 image (#1983)
* Update to 2020v5 image
2019-10-24 12:14:22 -07:00
CTT
4b0ed910ee Make SwerveDriveKinematics.toChassisSpeeds() public (#1976) 2019-10-24 09:13:04 -07:00
Thad House
103c1b121c Remove DS caching from the HAL level (#1971)
With updates to netcomm, this is no longer required.
2019-10-23 20:25:07 -07:00
Peter Johnson
6635ea75ee Fix NPE in SendableRegistry.foreachLiveWindow() (#1974) 2019-10-22 21:12:07 -07:00
sciencewhiz
cfe23c5cd0 Fix grammar error in comment for configureButtonBindings (#1969) 2019-10-22 19:59:15 -07:00
Thad House
4bde2654e2 Fix mac azure build (#1973)
Build was broken due to an azure image change.
2019-10-22 19:58:48 -07:00
Prateek Machiraju
4f034e6c14 generateTrajectory: default reversed param to false (#1953) 2019-10-21 16:21:46 -07:00
Peter Johnson
acf960f729 Sim GUI: Add option to disable outputs on DS disable 2019-10-21 16:16:17 -07:00
Peter Johnson
2d3dac99f0 Sim GUI: Handle low resolutions and scale default window positions
Low resolutions result in a maximized window and forced user scaling down
(by default, can still be changed by the user).
2019-10-21 16:16:17 -07:00
Peter Johnson
07c86e0cd5 Sim GUI: Support High DPI monitors
Add user setting for scaling on top of DPI scaling.
Add user setting for visual style (light/dark/normal).
Save window position, size, maximized state, scale, and style to ini file.
2019-10-21 16:16:17 -07:00
Peter Johnson
46ad95512e SimDeviceData: Add missing null check 2019-10-21 16:16:17 -07:00
Peter Johnson
5bce489b98 Add ProggyDotted font to imgui (both cmake and gradle) 2019-10-21 16:16:17 -07:00
Peter Johnson
55af553acc Simulation GUI: Map gamepad the same way as DS 2019-10-21 16:16:17 -07:00
Peter Johnson
c59f9cea5f CameraServer: Add VID/PID support for Linux USB devices (#1960) 2019-10-20 14:12:00 -07:00
carbotaniuman
3fc89c84d6 Make splinePointsFromSplines public (#1963) 2019-10-20 14:11:17 -07:00
Peter Johnson
2c50937975 Fix implicitly deleted move constructors (#1954)
These were incorrect and exhibited as warnings on more recent versions of
clang (notably on Mac).

- Use pointers instead of references internally in GenericHID and *Drive
- Leave PIDBase, PIDController, and Resource non-moveable
- Remove the atomic from m_disabled in NidecBrushless
- Make Timer and Trigger copyable as well as moveable
- Implement custom move constructor/assignment for SendableChooserBase

Also comment out some unused variables that caused clang warnings.
2019-10-19 11:36:44 -07:00
Peter Johnson
f3ad927f45 Update Java SmartDashboard and LiveWindow to match C++ 2019-10-19 11:36:24 -07:00
Peter Johnson
05c25deb7b Fix move handling of C++ Sendable in SmartDashboard and LiveWindow 2019-10-19 11:36:24 -07:00
Peter Johnson
d726591ce4 Fix Gazebo sim plugin build (#1959) 2019-10-19 11:35:56 -07:00
Peter Johnson
2ff694fa49 Unbreak gradle build when other compilers installed (#1958)
There was dependency breakage in halsim_gui, which is only available on desktop.
2019-10-19 09:50:49 -07:00
Oblarg
53816155ba Improve command decorator names (#1945) 2019-10-19 08:13:33 -07:00
Peter Johnson
a38f183a98 Fix GenResources.cmake so it's usable in a submodule (#1956)
This is only important for projects that reference this repo as a submodule.
2019-10-18 17:24:47 -07:00
Peter Johnson
b3398dca39 Set gradlebase correctly for all examples (#1950) 2019-10-18 11:39:31 -07:00
Banks T
2c311013d4 Add Aarch64Bionic platform detection (#1922) 2019-10-18 08:03:48 -07:00
Prateek Machiraju
c10f2003c5 Add generateTrajectory overload (#1944)
Add an overload for the generateTrajectory method that accepts a DifferentialDriveKinematics instance instead of a list of constraints. This instance is used to automatically create a DifferentialDriveKinematicsConstraint behind the scenes, saving the user some verbosity.
2019-10-18 08:02:42 -07:00
Prateek Machiraju
63cfa64fb3 Add getters for pose in odometry classes (#1943) 2019-10-18 07:58:22 -07:00
Oblarg
2402c2bad7 Fix C++ command group recursive constructor bug (#1941)
Passing command groups as lvalue-references to other command groups should be illegal, as their copy constructors have been deleted. However, copy constructors are const-qualified. This led to a very obscure bug where passing a command group by lvalue to another command group would result in a valid template expansion 'looking like' a copy constructor, and being preferred to the deleted copy constructor. This would result in constructor recursion (the expanded constructor would, in an attempt to call the copy constructor, call itself), and an eventual segfault when the stack inevitably overflowed.

This fixes the problem by explicitly deleting the problematic constructor signature - attempting to do this now (correctly) generates a compilation error.
2019-10-18 07:57:43 -07:00
Oblarg
f4eedf597f Fix ConcurrentModificationException in CommandScheduler (#1938) 2019-10-18 07:56:12 -07:00
Matt
bb0b207d2f Fix array out of bounds exception caused by parallel race group (#1935)
The current index would be set to -1 by the execute method of ParallelRaceGroup,
and then an index out of bounds exception would be thrown by the end() method of
SequentialCommandGroup. This change bound checks the current command index as well
as only calls end at the end of parallel race group rather than during execute.
2019-10-18 07:55:14 -07:00
sciencewhiz
7bd69e591c Fix typo in temperature (#1940) 2019-10-14 16:16:30 -07:00
Thad House
ec9738245d Bump to 2020 v4 image (#1931) 2019-10-10 10:11:59 -07:00
Thad House
46303a8221 Add messaging to extension loading in the HAL (#1926) 2019-10-09 22:25:02 -07:00
sciencewhiz
d169d6be9e Set extract_static for Doxygen config so that static members show up (#1930)
Update Doxygen to 1.8.16
2019-10-09 22:24:45 -07:00
Thad House
4e183eb104 Bump to 2020 v3 image (#1929) 2019-10-09 22:24:17 -07:00
Peter Johnson
84c185803d LiveWindow: catch errors in callback/builder functions (#1921)
This prevents LiveWindow bugs from crashing the entire robot program.
Instead, an error is printed and the object is removed from LiveWindow.
2019-10-09 22:22:30 -07:00
Thad House
0e3b0f3da7 Remove deprecated free() calls (#1925)
Replaced with the standard close()
2019-10-08 21:30:33 -07:00
Thad House
7f839b87ce Remove timeouts from azure builds (#1924)
Windows builds are occasionally crossing 1 hour and failing
2019-10-07 20:47:01 -07:00
Thad House
45b766a5dc Fix main thread ID being potentially incorrect for simulation (#1923) 2019-10-07 20:45:33 -07:00
Banks T
56d782b16c Add secondary camera name for PS3Eye (#1920) 2019-10-06 22:18:49 -07:00
Peter Johnson
2b4894038e Add simulation GUI plugin
This uses Dear Imgui to provide a cross-platform integrated GUI for robot
simulation. The GUI provides fully integrated DS and joystick support so it's
not necessary to run the official DS.
2019-10-06 17:28:39 -07:00
Peter Johnson
f97d16073a Add imgui build to cmake 2019-10-06 17:28:39 -07:00
Peter Johnson
55a844a3e1 HAL sim: Add encoder channel B access 2019-10-06 17:28:39 -07:00
Peter Johnson
10deba8546 Remove sendables from SendableRegistry when close() is called (#1917)
This only affected Java (C++ RAII doesn't have the same problem).

Needed to add close/AutoCloseable to several classes to add this behavior.
2019-10-05 23:42:53 -07:00
Peter Johnson
a9f0e46680 Implement sim devices for ADXL345, ADXL362, ADXRS450, Ultrasonic
This makes the halsim_adx_gyro_accelerometer simulation plugin and
the accelerometer part of lowfi_simulation obsolete.
2019-10-05 22:39:00 -07:00
Peter Johnson
aa90645865 Add ability to associate other devices with a SimDevice
Implemented only for AnalogInput, DIO, and Encoder.
2019-10-05 22:39:00 -07:00
Peter Johnson
81c2c8a7de Add simulation generic device/value support
This allows high-level library classes to implement enhanced simulation
support even if no low-level corresponding simulation library exists, and
avoids the need for bit-banging complex interfaces like SPI or CAN.
2019-10-05 22:39:00 -07:00
Peter Johnson
e8d6f8a2c1 Move mockdata/HAL_Value.h to hal/Value.h
Also prefix the MakeBoolean et al functions with HAL_ to avoid namespace
pollution.
2019-10-05 22:39:00 -07:00
Peter Johnson
1b266717a8 Add simulation module support to cmake build (#1906) 2019-10-04 19:08:57 -07:00
Thad House
fb8f3bd06b Add testbench yaml file (#1915) 2019-10-04 15:09:35 -07:00
Thad House
846d8def00 Update to 2020 v2 image (#1913)
* Update to 2020 v2 image
2019-10-02 13:14:30 -07:00
Thad House
d6ac6e512b Fix PortForwarder package declaration (#1912) 2019-09-30 15:13:09 -07:00
Banks T
2271570860 Fix PS3Eye exposure setting (#1911) 2019-09-30 15:09:39 -07:00
Peter Johnson
885744d7e1 Add myRobot C++ version to cmake build (#1907) 2019-09-29 20:36:28 -07:00
sciencewhiz
366091fa87 Document that ConditionalCommand requires all subsystems (#1909)
Fixes #1683
Fixes typo
2019-09-29 20:35:41 -07:00
sciencewhiz
c58b072c89 Fix Drive usage reporting order (#1908)
Fixes #1893
2019-09-29 20:35:04 -07:00
sciencewhiz
762c88adb8 Update compiler versions in readme (#1905) 2019-09-29 16:56:11 -07:00
Tyler Veness
af8ce568d1 Add Ramsete unicycle controller (#1790) 2019-09-29 16:48:12 -07:00
Tyler Veness
b2c2934d05 Fix javadoc warnings about invalid usage of ">" (#1904)
The trajectory gen docs use "->". ">" has been replaced with "&gt;".
2019-09-29 16:38:48 -07:00
Tyler Veness
cce26ec78e Replace CRLF line endings with LF (#1902) 2019-09-28 19:55:50 -07:00
Thad House
cb54602d49 Add support for writing RTR CAN Frames to the CAN API (#1900) 2019-09-28 16:49:34 -07:00
Thad House
9f740e5905 Use OS for serial port instead of NI VISA (#1875) 2019-09-28 16:49:11 -07:00
Peter Johnson
b23baf611a Add ability to run robot main loop in a separate thread (#1895)
Default behavior is still to run the robot main loop in the main thread.

The ability to run the robot main loop in a separate thread and add a hook
for running a different function in the main thread is needed for simulation
GUI support on some platforms.
2019-09-28 15:43:24 -07:00
Prateek Machiraju
457f94ba26 Add trajectory generation using hermite splines (#1843) 2019-09-28 15:40:56 -07:00
Thad House
fd612052f3 Update native utils to use new frchome directory (#1884) 2019-09-28 15:40:02 -07:00
Thad House
8858ec55c7 Remove periodic can read call (#1868)
It is not necessary anymore, and is a complicated and confusing API to keep around.
2019-09-28 15:38:58 -07:00
CodingWithFusion
41efb8015d Update CANAPITypes.h (#1860)
Add Playing With Fusion to CAN manufacturer list.
2019-09-28 15:33:18 -07:00
Thad House
c93be1b2d5 Remove LabVIEW HAL support (#1901) 2019-09-28 15:31:43 -07:00
Thad House
680f8919ed Remove eigen, units and libuv from doxygen generation (#1898) 2019-09-28 08:28:31 -07:00
Thad House
c5812524f8 Bump GradleJNI plugin version (#1899)
Fixes an issue where the symbol check task doesn't always run.
2019-09-28 08:28:02 -07:00
Peter Johnson
971303da8c Add PortForwarder class (#1890)
This class provides an easy way to forward local ports to another host/port.
This is primarily useful to provide a way to access Ethernet-connected devices
from a computer tethered to the RoboRIO USB port.

The most natural spot to put the shared implementation of this class was into
wpiutil, so a wpiutilJNI library has been added.
2019-09-26 22:53:21 -07:00
hjelstromboli
50db77bf25 Fix wpiutil cmake eigen install source directory (#1891) 2019-09-16 12:54:13 -05:00
Oblarg
85d42c1993 C++ PIDCommand: Add GetMeasurement() and UseOutput() (#1892)
These are in the Java version but were missed in C++.
2019-09-16 12:53:03 -05:00
Prateek Machiraju
2dfbb855d7 wpilibj: Fix SwerveDriveKinematics ctor parameter name (#1889) 2019-09-15 14:53:21 -05:00
Peter Johnson
471f375a38 Simplify Sendable interface (#1864)
This removes the name and subsystem from individual objects, and instead
puts this data into a new singleton class, SendableRegistry.  Much of
LiveWindow has been refactored into SendableRegistry.

In C++, a new CRTP helper class, SendableHelper, has been added to provide
move and destruction functionality.

Shims for GetName, SetName, GetSubsystem, and SetSubsystem have been added
to Command and Subsystem (both old and new), and also to SendableHelper to
prevent code breakage.

This deprecates SendableBase in preparation for future removal.
2019-09-14 15:22:54 -05:00
Tyler Veness
1d8c4d016f Replace ::value and ::type with _v and _t suffixes (#1885) 2019-09-13 22:14:37 -05:00
Rishab Rao
a5650b9439 Add Units Utility class for Java (#1829)
Units conversion class to convert between commonly used units.

Co-Authored-By: Austin Shalit <austinshalit@gmail.com>
2019-09-12 13:38:25 -05:00
Tyler Veness
904479ad43 Deprecate GearTooth class for removal (#1878)
It only works with a specific sensor that isn't available anymore, the
class is a trivial wrapper around a Counter, and no one uses this class
according to FMS usage reporting.
2019-09-08 13:21:36 -05:00
Prateek Machiraju
86b666bba9 Add equality comparator to geometry classes (#1882) 2019-09-08 13:20:26 -05:00
Tyler Veness
62f07c182c Make one-arg Rotation2d constructor implicit (#1883)
Since a value in radians is always a rotation, it makes sense to provide
an implicit constructor for this for convenience with Pose2d's
constructor.
2019-09-08 13:15:07 -05:00
Prateek Machiraju
f405582f86 Add kinematics suite (#1787)
Co-authored-by: Tyler Veness <calcmogul@gmail.com>
Co-authored-by: Matt <matthew.morley.ca@gmail.com>
2019-09-07 23:11:49 -05:00
Tyler Veness
561cbbd144 Deprecate Filter class for removal (#1876) 2019-09-07 23:02:44 -05:00
Tyler Veness
84e2973aaa Remove unused include from Filesystem.h (#1877) 2019-09-07 23:01:57 -05:00
Thad House
f49859ebfd Remove NI VISA headers, as they are now included in NI Libraries (#1879) 2019-09-07 23:01:27 -05:00
Thad House
bc59db5e6f Rename DEBUG macro to DEBUG0 (#1871)
This avoids conflicts with the platform DEBUG macro on some platforms.
2019-09-06 20:45:52 -05:00
Thad House
dd928b4cbf Remove JNI logging (#1872) 2019-09-06 20:42:40 -05:00
Peter Johnson
3e0f7d0995 Use units for new NotifierCommand (#1869) 2019-09-04 22:54:49 -05:00
Thad House
5ffe15d5ff Remove ability to build all combined artifacts (#1867) 2019-09-04 13:06:46 -07:00
Thad House
516cbef2c4 Remove RoboRIO ifdef from simulation headers (#1859) 2019-09-03 19:55:17 -07:00
Tyler Veness
9b6ffc201c Replace SetOutputRange() with SetIntegratorRange()
If users are attempting to use the output range to limit the controller
action, they should use ProfiledPIDController instead. If they actually
intended to clamp the output, they should use std::clamp().
2019-09-03 19:46:59 -07:00
Tyler Veness
ff8b8f0a8a Remove percent tolerance from PID controller
It breaks the unit system badly; the tolerance member variable has
different units depending on percent vs absolute. Absolute tolerance is
a lot more natural than percent tolerance anyway.
2019-09-03 19:46:59 -07:00
Peter Johnson
0ca8d667d2 Clean up AutoCloseable and other Java warnings (#1866) 2019-09-03 19:44:24 -07:00
Tyler Veness
7112add67f Watchdog: use units::second_t instead of double (#1863)
Fixes #1827.
2019-09-03 15:58:31 -07:00
Peter Johnson
761bc3ef85 Change C++ WaitCommand to use units (#1865)
Also remove unique_ptr usage.
2019-09-02 23:39:51 -07:00
Tyler Veness
1fb3011235 Add MathUtils.clamp() for Java (#1861)
Also use std::clamp() and MathUtils.clamp() in as many places as
possible in place of custom clamp functions or if statements.
2019-08-28 23:24:30 -07:00
Peter Johnson
eb3e0c9c95 Fix cmake Eigen include directory (#1862)
This currently only breaks when cmake is configured with WITH_TESTS but
ultimately this would have affected wpilibc builds too.
2019-08-28 23:24:08 -07:00
Tyler Veness
2250b7fbe3 Rename GearsBotNew example to GearsBot 2019-08-28 22:08:59 -07:00
Tyler Veness
c9f9feff1f Replace deprecated API usage in C++ examples
Since there is a new version of GearsBot using the new command-based
API, the old GearsBot is just removed.

PR #1842 is being included to verify this PR is correct.
2019-08-28 22:08:59 -07:00
Dalton Smith
d6b9c7e148 CONTRIBUTING.md: Point to frc-docs instead of screensteps (#1858) 2019-08-28 22:08:17 -07:00
Thad House
d10a1a7977 Fix eigen build in vcpkg (#1856) 2019-08-27 14:38:23 -07:00
Tyler Veness
2bdb443255 Add frc2 includes to list of "other lib" regexes (#1855) 2019-08-26 23:11:07 -07:00
Sam Carlberg
4b2b21d247 Replace outdated Java collections (#508) 2019-08-26 22:47:18 -07:00
Thad House
8993ce5bf1 Move Eigen headers out of main include folder (#1854)
This allows using Eigen as a separate cmake package, e.g. for vcpkg.
2019-08-26 21:22:41 -07:00
LilTiger
0f532a1174 Add PWMSparkMax (#1751) 2019-08-26 20:29:20 -07:00
Thad House
f7ad363d86 Add jni cross compile options for aarch64 (#1853) 2019-08-26 11:56:35 -07:00
Thad House
9afea33403 Add support for aarch64 jetson bionic builds (#1844) 2019-08-26 09:49:58 -07:00
Peter Johnson
d787b5d609 Add more items to .gitignore (#1850)
- compile_commands.json
- .clang
- .clangd/
2019-08-25 23:30:04 -07:00
Peter Johnson
5dd0d1b7db Use units in SPI 2019-08-25 22:52:48 -07:00
Peter Johnson
07ac711b31 Fix units deprecated warning in IterativeRobot 2019-08-25 22:52:48 -07:00
Peter Johnson
decfd858b8 Correctly report -1 for POV on disconnected joystick (#1852) 2019-08-25 22:51:54 -07:00
Oblarg
076ed7770c Add new C++ Command framework (#1785)
This is the C++ version of #1682.

The old command framework is still available, but will be deprecated.

Due to name conflicts, the new framework is in the frc2 namespace.
Eventually (after the old command framework is removed in a future year)
it will be moved into the main frc namespace.
2019-08-25 20:55:59 -07:00
Peter Johnson
a0be07c370 Refactor HAL handle move construction/assignment (#1845)
A templated hal::Handle class is used to wrap handles to make them move-only.
This eliminates a lot of boilerplate move constructor/assignment code
in the main WPILib classes.  HAL_SPIPort and HAL_I2CPort are also wrapped.

The wrapper class does not implement destruction.  This would require the
wrapper class to be handle-specific (rather than generic) and would result
in more code added than it removed, plus would add header dependencies on
more HAL headers.  In addition, some HAL handle release functions are more
complex (e.g. have return values) and can't be easily mapped to a destructor.
2019-08-25 18:42:00 -07:00
Oblarg
558c383088 Add new Java Command framework (#1682)
The old command framework is still available, but will be deprecated.

Due to name conflicts, the new framework is in the wpilibj2 package.
Eventually (after the old command framework is removed in a future year)
it will be moved into the main wpilibj package.
2019-08-25 14:47:07 -07:00
Peter Johnson
1379735aff Delete RobotState and SensorUtil constructors (#1847) 2019-08-24 22:28:39 -07:00
Tyler Veness
e3d86fee46 Move circular buffer class from wpilib to wpiutil (#1840) 2019-08-24 21:35:19 -07:00
Peter Johnson
4cd8a56672 TimedRobot.cpp: Fix deprecation warning (#1846)
For both TimedRobot and IterativeRobotBase, use delegating constructors
to reduce code duplication.
2019-08-24 21:13:29 -07:00
Thad House
b2861f8948 Use 2020 artifacts and artifactory server (#1838)
Uses 2020 artifacts and artifactory server, and new versioning and repository plugins.
2019-08-22 21:48:43 -07:00
Thad House
98cc32703c Update to use artifactory to publish artifacts (#1833)
* Update to use artifactory to publish artifacts
2019-08-21 07:28:24 -07:00
Tyler Veness
fa06403000 Move drive integration tests into wpilibj/src/test (#1836)
Also move drive and controller tests into subfolders.
2019-08-20 21:05:38 -07:00
Thad House
e716c36b89 Fix Nat.java generation to be incremental (#1831)
Also generate the imports.
2019-08-20 21:03:44 -07:00
Thad House
9fd2b5e3fa Fix MSVC builds on cmake windows in vcpkg (#1835) 2019-08-19 20:28:48 -07:00
Redrield
7e95010a29 Add compile-time EJML matrix wrapper to wpiutil (#1804)
This adds a wrapper over EJML's SimpleMatrix that uses generated classes representing numbers to encode the dimensions of each matrix at compile time, and to check operations between matrices for validity at compile time, rather than failing with an exception at runtime. This is required for the Java implementation of state-space control.

Additions to the wpiutil gradle script, and a python script at the wpiutil root are used to generate numeric types from a template at build time for both gradle and cmake. Users will be able to access types through functions on the Nat class.
2019-08-18 15:00:40 -07:00
Tyler Veness
3ebc5a6d3a Add ProfiledPIDController 2019-08-16 23:47:02 -07:00
Tyler Veness
fc98a79dbb Clean up PIDController interface in preparation for ProfiledPIDController 2019-08-16 23:47:02 -07:00
Tyler Veness
fdc098267e Fix compilation error in elevator trapezoid profile example (#1826)
Merging #1815 broke it, then #1814 was merged before fixing the failure.
2019-08-16 23:04:12 -07:00
Oblarg
a3dd84e854 Make XBoxController Button enum public (#1823)
This allows using the raw button number in places where that is useful.
2019-08-16 22:21:49 -07:00
Tyler Veness
a216b9e9ee Add TrapezoidProfile example (#1814) 2019-08-16 22:03:44 -07:00
Prateek Machiraju
8f386f6bb3 wpilibc: Add unit-safety to C++ geometry classes (#1811) 2019-08-16 22:00:32 -07:00
Prateek Machiraju
c07ac23532 wpilibc: Add overloads for units (#1815)
Add unit-taking overloads to the following classes:
- IterativeRobotBase
- LinearFilter
- Notifier
- TimedRobot
- Timer (HasPeriodPassed only)
- frc2::PIDController

The corresponding non-units-taking functions have been deprecated.

The return value of TimedRobot::GetPeriod() was updated.
This is a breaking change, users should use to<double> to get the value in seconds.

Other return values, e.g. Timer::Get(), have NOT been updated due to much wider use.
2019-08-16 21:56:48 -07:00
Peter Johnson
f1d71da8a9 Move GetStackTrace and Demangle to wpiutil, add Windows support (#1819)
For Windows, import the StackWalker source (https://github.com/JochenKalmbach/StackWalker)
plus PR 35 in that repo, with a few simplifications to StackWalker.h.
2019-08-12 23:45:45 -07:00
Tyler Veness
ef037457e5 Make LinearFilter copyable and moveable (#1789) 2019-08-09 22:29:23 -07:00
Thad House
76930250c0 Remove objective-cpp support (#1816)
Was only there for mac usb cam support, but we likely won't get to it this summer anyway,
and its causing a breakage in the backing libraries with cross builds
2019-08-09 16:28:53 -07:00
Tyler Veness
1c246418f8 Move TrapezoidProfileTest to trajectory folder (#1812)
The newer controls stuff is using subfolders, so it makes sense for
consistency and reduced clutter.
2019-08-09 16:27:41 -07:00
Matt
95a54a0f29 Add java arcade drive example (#1810) 2019-08-09 16:19:33 -07:00
Thad House
a4530243e1 HAL sim: Fix incorrectly setting dio port to initialized on cleanup (#1813) 2019-08-09 16:14:46 -07:00
Austin Shalit
09d00a6227 Update Java examples to use new PIDController (#1809)
This also allows us to re-enable Werror.
2019-08-04 20:35:33 -07:00
Abiel Fernandez
ba9b517427 Add missing Java examples (#841) 2019-08-04 20:34:02 -07:00
Thad House
6411bd79c6 InterruptableSensorBase: Fix callback function deletion (#1807)
Save the callback function into a unique_ptr member instead.
2019-08-04 20:25:25 -07:00
Austin Shalit
810e58ea85 I2C: Add tip about writeBulk() to transaction() (#1806) 2019-08-04 01:16:38 -07:00
Peter Johnson
607d6c148a Fix wpilibj integration tests jar name (#1808) 2019-08-04 00:06:07 -07:00
Oblarg
c9873e81b2 Remove PIDControllerRunner and mutex from new PIDController (#1795)
Teams that wish to use it asynchronously may still do so - they simply need to handle the thread safety themselves (it is not that difficult, and can be done more cleanly in the calling code anyway).
2019-08-04 00:01:11 -07:00
Tyler Veness
98d0706de8 Fix cscore build with OpenCV 4 (#1803)
The main change in OpenCV 4 was removing its C APIs from OpenCV 1. If
the user has OpenCV 4, they have no way of obtaining the correct
arguments for cscore functions that require the C API. Therefore, we can
fix the build by just not compiling in functions reliant on the C API if
OpenCV 4 is being used.

OpenCV 3 builds should continue to work with this change.
2019-08-03 16:10:39 -07:00
Oblarg
fbe67c90c8 Make Sendable setters synchronous (#1799)
Instead of being called asynchronously by NetworkTables, they are now called by updateValues() synchronously with the main loop, just like the getters.
2019-08-03 15:08:06 -07:00
Oblarg
c67a488a09 Format SendableBuilderImpl javadocs (#1802) 2019-08-03 15:00:43 -07:00
Tyler Veness
8e93ce8929 Fix PIDControllerRunner member destruction order (#1801)
The mutexes in PIDControllerRunner are declared after the Notifier, and
when the PIDControllerRunner object is destructed, the member object
destructors are called in the reverse order in which they are declared.
The mutexes are destructed first, then the Notifier destructor is called
which stops the Notifier.

There's a window between those destructor calls during which the
Notifier can run the callable and attempt to lock a mutex that no longer
exists.

Declaring the Notifier after all the variables its callable uses fixes
this issue, as it ensures the Notifier is destructed first.
2019-08-03 14:58:10 -07:00
Redrield
c98ca7310f Add EJML dependency to wpiutil (#1769)
Add EJML as the Java library for linear algebra for use in wpilib. This is equivalent to Eigen for C++.

The EJML dependency is downloaded in cmake and pulled in via maven in the gradle build.
2019-08-03 14:24:14 -07:00
Oblarg
3b12276bc3 SendableBase: remove unnecessary synchronization (#1797)
Also fixes the move constructor to update LiveWindow to follow the move.
2019-08-02 23:47:17 -07:00
Oblarg
e6d348f382 Fix missing default name in Java PIDController (#1792) 2019-08-02 23:38:35 -07:00
Austin Shalit
df12fc2a86 Java cleanups (#1776)
* Remove extra ';'s
* Remove unnecessary conversions to String
* Use StandardCharsets object
* Replace infinite while with check for interrupted thread
* Remove redundant local vars
* Remove redundant throws clause
* Remove redundant primitive wrapping
* Fix malformed Nested class test
* Remove unnecessary unboxing
* Remove unnecessary explicit type argument
* Replace lambdas with method references
* Replace statement lambdas with expression lambdas
* Replace null check with method call
* Replace number comparison with method call
* Fix broken javadoc comments
* Replace Arrays.asList with singletonLists
* Remove excessive lambda usage
* Remove redundant string operation
* Remove redundant type casts
* Remove unnecessary returns
* Remove redundant suppressions
* Fix unresolved file reference
* static analysis fixes
2019-07-31 22:19:48 -07:00
Thad House
39561751fc Update GradleVSCode version (#1786)
Fixes compile_commands
2019-07-31 22:15:48 -07:00
Tyler Veness
37d316aa09 Add C++20 std::math constants shim (#1788)
Based on http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0631r7.pdf
2019-07-31 22:15:22 -07:00
Tyler Veness
dd43109596 Deprecate frc/WPILib.h (#1779)
It drastically increases compile times and is bad style. C++ users
should be including what they use. We don't necessarily have to remove
WPILib.h, but it should at least be deprecated.
2019-07-30 00:41:14 -07:00
Thad House
823174f30a Update native utils to 2020.0.4 (#1783)
Adds -latomic by default to all linux builds
2019-07-30 00:40:23 -07:00
Tyler Veness
37c6952663 Squelch -Wdeprecated-copy for Eigen with GCC >= 9 2019-07-30 00:39:47 -07:00
Tyler Veness
04c9b000ff Revert "Fix build of Eigen 3.3.7 with GCC 9"
-Wextra adds -Wdeprecated-copy, which Eigen emits. We're going to
squelch the warning instead to minimize changes to Eigen's upstream
sources.
2019-07-30 00:39:47 -07:00
Peter Johnson
ca3e71e214 wpiutil: Fix Process::Spawn() (#1778)
Was broken due to removal of ArrayRef initializer_list constructor.
2019-07-26 11:22:23 -07:00
Prateek Machiraju
d946d5a2bb Fix Eigen compilation errors and add tests (#1777) 2019-07-24 20:51:33 -07:00
Tyler Veness
8b1b9ac75a Fix build of Eigen 3.3.7 with GCC 9 2019-07-24 00:03:18 -07:00
Tyler Veness
2f680ba990 Add Eigen linear algebra library
This imports Eigen 3.3.7, which will be used by the wpilibc implementation of
state-space control and mecanum/swerve forward kinematics (the forward
kinematics requires least-squares solutions via a matrix pseudoinverse).

While Eigen has parts licensed under BSD, MINPACK, and MPL2, the files we need
are only MPL2.
2019-07-24 00:03:18 -07:00
Prateek Machiraju
a885db7d48 Make MotorEncoderTest use LinearFilter (#1775)
Closes #1774
This also eliminates the call to the deprecated setPIDSourceType method.
2019-07-23 23:59:06 -07:00
Prateek Machiraju
ee24101696 Add geometry classes (#1766)
These classes introduce ways to represent poses and provide easy ways to transform, rotate, and translate poses across 2d space. This classes will be especially useful for a planned odometry and kinematics suite.

Furthermore, these classes can also be used to simply represent waypoints on a field, do superstructure motion planning, etc.
2019-07-23 23:57:39 -07:00
Thad House
48fe54271a Add HALSIM_SetSendError implementation (#1773) 2019-07-23 23:55:51 -07:00
Peter Johnson
dff58c87f4 Fix unused warning in release build (#1771) 2019-07-21 22:17:42 -07:00
Tyler Veness
dde61aad32 Remove TimerEventHandler typedef from Notifier class (#1767)
Using std::function<void()> directly makes it much clearer to the user
what kind of function Notifier expects. The Doxygen comments already say
what the function is used for, so the typedef just discards useful
information.
2019-07-20 22:57:16 -07:00
Loki
0f6ef80ab2 Add RobotState#IsEStopped and DriverStation#IsEStopped (#952) 2019-07-16 09:18:23 -05:00
Austin Shalit
e488861877 Move unit tests from integration test suite (#1170) 2019-07-16 00:02:52 -05:00
Oblarg
dffa1a5cba Make null checks more descriptive (#1688) 2019-07-15 20:22:36 -05:00
Oblarg
fe59d854d5 Notifier: add null check (#1684) 2019-07-15 20:20:11 -05:00
Peter Johnson
10731f3d6b Update uv Udp wrapper for latest features 2019-07-15 20:15:37 -05:00
Peter Johnson
89f7b72b6e Update libuv to 1.30.1 release 2019-07-15 20:15:37 -05:00
Peter Johnson
85f2f87400 wpiutil: Add unique_function (#1761)
This is a move-only variant of std::function to support move-only captures.

Imported from LLVM with some small tweaks (changed to 4 pointer internal storage, warnings fixes).
2019-07-15 20:13:57 -05:00
Tyler Veness
73ec940786 Remove SampleRobot (#1658)
SampleRobot provides no benefits over RobotBase to advanced teams and
TimedRobot is recommended for everyone else.

A skeleton template for RobotBase was added.
2019-07-15 20:09:47 -05:00
Tyler Veness
62be0392b6 Replace std::lock_guard and std::lock with std::scoped_lock (#1758)
std::scoped_lock was introduced in C++17 and is strictly better than
std::lock_guard as it supports locking any number of mutexes safely.
It's also easier to use than std::lock for locking multiple mutexes at
once.
2019-07-08 22:58:39 -07:00
Tyler Veness
24d31df55a Make sure move constructor is generated for TrapezoidProfile (#1757)
This wasn't necessarily the case before because defining a nondefault
constructor results in no default move constructor.
2019-07-08 22:19:13 -07:00
Tyler Veness
841ef5d739 Remove template types from lock RAII wrapper usages (#1756)
C++17 has template type autodeduction. These wrappers include
std::lock_guard and std::unique_lock.
2019-07-07 19:17:14 -07:00
Tyler Veness
e582518bae Fix some move constructors (#1754)
Timer didn't have working move semantics because mutexes aren't
moveable, meaning the default implementations were ill-formed.
MotorSafety wasn't locking its mutex.
2019-07-07 19:15:59 -07:00
Peter Johnson
8757bc471b Remove pre-C++17 shims (#1752)
Now that all compilers support C++17, remove some old C++14/C++17 shims.
2019-07-07 15:44:43 -07:00
Tyler Veness
ea9512977c Add replacement PIDController class (#1300)
Originally, PIDController used PIDSource with its "PIDSourceType" to
determine whether a class should return position or velocity to the
controller. However, the supported languages have changed a lot over 10
years and now support lambdas. Instead of using PIDSource and PIDOutput,
users can pass in doubles to the Calculate() function synchronously.
This makes the controller much more flexible for team's needs as they no
longer have to make a separate PIDSource-inheriting class just to
provide a custom input.

The built-in feedforward was removed. Since PIDController is synchronous
now, they can add their own feedforward on top of what Calculate()
returns.

To facilitate running the controller asynchronously, there is a
PIDControllerRunner class that handles that. By separating the loop from
the control law, PIDController can now be composed with others and be
used to control a drivetrain (a multiple input, multiple output system
that requires summing the results from two controllers) much easier.
Also, motion profiling can be used to set the reference over time.

All the classes related to the old PIDController are now deprecated. The
new classes are in an experimental namespace to avoid name conflicts.

While this is a large change, I think it is a necessary one for growth.
The old PIDController design was created in a time when languages only
supported OOP, and we have more tools at our disposal now to solve
problems. This more versatile implementation can be used in more places
like as a replacement for Pathfinder's "EncoderFollower" class.

There has been hesitation to add lambda support to WPILib for a while
now out of concerns for requiring teams to learn more features of C++ or
Java. In my opinion, this change makes PIDController easier to use, not
harder. The concept of a function is a building block of OOP and should
be learned before classes. The ability to store functions as first-class
objects and invoke them just like variables is rather natural.

Note that PID constants for the new controller will be different from
the old one. The original controller didn't take the discretization
period into account. To fix this, teams should just have to divide their
Ki gain by 0.05 and multiply their Kd gain by 0.05 where 0.05 is the
original default period.
2019-07-07 15:37:13 -07:00
Tyler Veness
9b798d228f Add TrapezoidProfile class (#1673) 2019-06-30 23:25:11 -07:00
Thad House
804926fb5b Unconditionally skip athena builds for sim (#1748)
They'll pretty much never work
2019-06-30 19:45:33 -07:00
Tyler Veness
118e9d29d5 Add C++14 units library (#1749) 2019-06-30 19:44:51 -07:00
Tyler Veness
c705953d77 Add usage reporting to LinearFilter (#1750) 2019-06-30 19:44:15 -07:00
Thad House
852d1b9cad Don't cross-build gazebo for raspbian (#1747) 2019-06-30 12:42:32 -07:00
Peter Johnson
eedb3a1adc Fix GCC 9 warnings (#1730) 2019-06-30 00:28:32 -07:00
Peter Johnson
60dce66a4f Remove wpi::ArrayRef std::initializer_list constructor (#1745)
This can be dangerous as it refers to a temporary, and GCC 9.0 warns about
its use.  Instead add std::initializer_list overloads to common places it
was used in an initializer_list sense.
2019-06-29 23:54:02 -07:00
Thad House
9e19b29c31 Use base azure image for primary wpilib build (#1744)
This will ensure everything works with no flags, even without a rio or raspbian compiler
2019-06-29 21:37:34 -07:00
Thad House
2994250714 Update jni library, fix cross builds of the jni symbol check (#1742) 2019-06-29 21:31:55 -07:00
Thad House
a6b0e9b856 Only disable execution of cross compile google tests (#1741)
Still build them and link them, just don't execute them.

Google test is still disabled completely for the HAL and wpilibc.
2019-06-29 21:31:27 -07:00
Peter Johnson
3c2093119e Use docker container to run wpiformat (#1740)
Also update raspbian image to use new unified name.
2019-06-29 21:11:17 -07:00
Thad House
5fe2eebceb Revert "Don't build halsim_gazebo on raspbian (#1737)" (#1743)
This reverts commit d9cb57a429.
2019-06-29 21:05:44 -07:00
Peter Johnson
4b1b92bb74 Replace wpi::optional with C++17 std::optional (#1732)
Keep wpi/optional.h as a shim with deprecated warnings.
2019-06-29 11:20:22 -07:00
Peter Johnson
0fbb0d989e Update to 2020 compilers (#1733)
Also link to libatomic in cmake and for Raspbian only in gradle.
2019-06-29 09:28:28 -07:00
Thad House
2dc94e6052 Disable google tests on cross compilers (#1738)
Removes checks for onlyathena and onlyraspbian, and just disables gtest for cross compilers.
2019-06-29 09:27:11 -07:00
Peter Johnson
d9cb57a429 Don't build halsim_gazebo on raspbian (#1737)
Reference shared/config.gradle instead of shared/plugins/setupBuild.gradle.
2019-06-28 22:30:17 -07:00
Austin Shalit
f7cfdd7cee Replace crlf line endings with lf (#1731) 2019-06-28 20:55:14 -07:00
Austin Shalit
b6d5d90d9d Add JaCoCo Support (#1734) 2019-06-28 20:01:02 -07:00
Thad House
c7ab2baa6e Add way to disable the jni check tasks from a property (#1736) 2019-06-28 20:00:35 -07:00
Thad House
0c45c5b7ea Fix skip athena and skip raspbian flags (#1735) 2019-06-28 20:00:09 -07:00
Thad House
3dfb01d45b Update to new Native Utils (#1696)
Also update to azure 2019 windows image
2019-06-28 14:09:10 -07:00
Tyler Veness
30e936837c Clean up LinearDigitalFilter class (#782)
* Renamed LinearDigitalFilter to LinearFilter
* Filter base class removed since it wasn't useful
* C++: std::shared_ptr<> replaced with double parameter
2019-06-28 13:35:57 -07:00
Tyler Veness
311e2de4c1 Remove deprecated Joystick constants (#1715) 2019-06-26 14:17:11 -07:00
Benjamin Ward
c08fd6682f Update CAN manufacturer list (#1706) 2019-06-26 14:16:12 -07:00
Peter Johnson
258bba0c2d ErrorBase and WPIError improvements (#1727)
* ErrorBase: Use magic static singleton for globals
* ErrorBase: Add testability features for global errors
* Make WPIError definitions inline functions
(This works around cross-DLL variable issues on Windows)

Fixes #1726.
2019-06-23 20:36:52 -07:00
Peter Johnson
372ca4f456 cmake: Enable googletest unit tests (#1720)
Also don't inherit compile warnings from wpiutil

There's not a good way to disable inherited compiler flags.
2019-06-23 12:44:28 -07:00
Peter Johnson
223d47af0e HALSIM: support mocking of HAL_SendError() (#1728) 2019-06-23 11:48:04 -07:00
Peter Johnson
55cb683db4 Change compiler flags to C++17 (#1723)
The current versions of the RoboRIO and Raspbian compilers support the flag but have
minimal actual C++17 support.  Changing the flag is the first step.
2019-06-20 22:32:50 -07:00
Peter Johnson
ee8a33c568 wpiutil: SafeThread: Add thread id, support getting shared_ptr (#1722)
Rename base class function from GetThread to GetThreadSharedPtr.
2019-06-20 19:51:09 -07:00
Peter Johnson
61426d08de wpiutil: Signal: make operator() const (#1721)
This enables const-ness in uv::Handle ReportError() and Invoke() as well.
2019-06-20 17:51:32 -07:00
Tyler Veness
b630b63ef0 Remove functions in LiveWindow deprecated since 2018 (#1716)
The Java versions were already accidentally removed in #1059.
2019-06-14 18:52:10 -07:00
Peter Johnson
1d0c05d4f8 Styleguide fixes for #1718 (#1719) 2019-06-14 18:51:49 -07:00
Peter Johnson
f07569df19 Fix newer GCC/clang compiler warnings (#1718) 2019-06-14 18:32:27 -07:00
David Vo
0120f31247 C++ SPI: Fix SetClockRate to take int (#1717)
The Java version takes an int, and HAL_SetSPISpeed takes an int as well.
2019-06-12 06:04:52 -07:00
Thad House
c2829ed98e Configure gradle to ignore unresolved headers (#1711)
Work around Gradle's handling of libraries like eigen and opencv
which use macro includes.  Also completely disable incremental includes.
2019-06-11 21:48:32 -07:00
Thad House
221e66f46d Allow disabling static init of JNI libraries (#1672) 2019-06-10 22:29:32 -07:00
Thad House
738852e119 cmake: Add cross toolchain files for Rio and Pi (#1710) 2019-06-10 22:05:20 -07:00
Tyler Veness
27b697b084 Remove frc directory include shims (#1714) 2019-06-10 22:03:52 -07:00
Tyler Veness
9e45373a74 Remove functions and classes deprecated for 2018 season (#1059) 2019-06-10 22:03:15 -07:00
David Vo
eeb1025ac7 SPI: Report port as instance for usage reporting (#1704) 2019-06-10 20:57:36 -07:00
Thad House
bc6f1e2469 Windows compiler options improvements (#1709)
- Use generators to set options only during build
- Add ZcThrowingNew
- Disable 4996

Fixes #1699
2019-06-10 20:09:39 -07:00
Thad House
bb48ae391e cmake: Move example programs into folders (#1654)
This looks cleaner in VS.
2019-06-10 20:04:34 -07:00
Thad House
221011494d Update for C++17 and fix MSVC warnings (#1694)
* Update MSVC arguments
* Fix json allocator
* Fix simulation diamond
* Bump gtest
* Remove empty varargs in unit tests
* Replace test case with test suite
* Remove deprecation warning in optional
* Remove need for NOMIXMAX to be defined in wpilib headers
2019-05-31 15:43:32 -05:00
Thad House
fb1239a2ad Add raw sources and sinks to cscore (#1670)
In some cases, we don't want the cv requirement to get an image, for instance interop with other versions of opencv

This enables getting a raw image, and handling conversions from the user side.
2019-05-30 21:12:05 -05:00
Thad House
7de9477347 Add lambda overloads for interrupts (#1636) 2019-05-30 19:59:35 -05:00
Thad House
90957aeea4 Move libuv to its own subfolder in build (#1661)
Allows using system libuv

* Fix Gradle Build and include dirs

* Update cmake find to support vcpkg libuv
2019-05-30 15:59:26 -07:00
Thad House
47aae502a7 Styleguide fixes (#1702) 2019-05-30 12:36:36 -07:00
pgfisico
0bff98b5ec Correct DifferentialDrive::ArcadeDrive param docs (#1698) 2019-05-30 11:05:42 -07:00
Sam Carlberg
b52e40b80c Allow widgets to be added by passing value suppliers (#1690) 2019-05-30 09:45:23 -07:00
Sam Carlberg
4a00cd77bb Add usage reporting for the Shuffleboard API (#1685) 2019-05-30 09:36:49 -07:00
Thad House
e25e515f2e Publish artifacts on azure (#1678) 2019-05-25 06:18:49 -07:00
Thad House
322ef9b967 Force Java 11, fix javadoc generation (#1695) 2019-05-19 16:59:44 -07:00
Tyler Veness
d42ef5df02 Fix Watchdog print formatting (#1693) 2019-05-19 12:24:40 -07:00
Tyler Veness
f432f65bef Update copyright year in license to 2019 (#1524)
Also update clang-format to 6.0.
2019-05-17 17:35:09 -07:00
Thad House
1726b77ac5 wpiutil: uv: Remove copy from SimpleBufferPool (#1680) 2019-05-07 20:55:58 -07:00
Thad House
620bec9cae wpiutil: uv: Add LoopClosing status to Handle (#1647)
Useful for EventLoopRunner to know if a stop is requested, or close is happening for another reason.
2019-05-05 17:38:56 -07:00
Thad House
7cd6e2e7fa UsbCamera: Solve race in windows initialization (#1638)
Create message pump during UsbCameraImpl creation.
2019-05-05 16:29:47 -07:00
Thad House
7732836bd5 Completely disable watchdog tests on mac (#1679)
They’re just not reliable.
2019-05-05 15:51:14 -07:00
Thad House
698edfda9d Remove framework load, disable mac timeout test (#1676)
* Remove system includes from all mac builds

* Disable java watchdog on mac
2019-05-05 13:16:47 -07:00
sciencewhiz
1c454b000f Add Shuffleboard calls to IterativeRobotBase in C++ (#1607)
Additionally, add epochs for Shuffleboard, LiveWindow, and
Smartdashboard updates.
2019-04-27 22:23:21 -07:00
David Vo
f42905b32e Include missing headers in HAL.h (#1660)
* Include CANAPI.h and Encoder.h in HAL.h

* Include Threads.h in HAL.h

* Make Threads.h C compatible

Also changes the #define to a typedef.
2019-04-27 21:52:54 -07:00
Thad House
bdc822fad8 Only generate passthrough URLs for RoboRIO (#1624)
Otherwise accidentally, a race could occur between coprocessors and rio.

Java was done in both old and new locations as it's a race.
2019-04-27 20:35:23 -07:00
Tyler Veness
d3affb16bc Make failure of HAL_GetFPGATime() more descriptive (#1633) 2019-04-27 20:34:14 -07:00
Peter Johnson
2de3bf7f58 Update LLVM from stable upstream (#1653)
Replace CheckedMalloc with upstream safe_malloc.
2019-04-27 20:33:08 -07:00
Austin Shalit
3cf4f38f5d Fix build on macos10.14.4 (#1648) 2019-04-27 20:25:27 -07:00
Thad House
4e0c10f488 Fix CAN Clean using wrong ID (#1668) 2019-04-27 20:24:40 -07:00
Thad House
3b06313243 Fix Gray to BGR conversion in CameraServer (#1665) 2019-04-27 20:17:17 -07:00
Thad House
6cd1c73efe Fix GUID comparison creating weird symbol (#1659) 2019-04-27 20:16:52 -07:00
Austin Shalit
063bbab6f5 MavenArtifacts.md: update links to HTTPS (#1674) 2019-04-27 20:16:04 -07:00
sciencewhiz
aab4c494d6 Fix type in build.gradle (#1604) 2019-03-10 18:40:16 -07:00
Peter Johnson
bf46af2600 Disable extraneous data warnings in libjpeg (#1630)
These are common with USB cameras.
2019-03-10 18:39:07 -07:00
Thad House
655763a9a7 Limit length of message sent to DS SendError call (#1618)
If total length is over 65536, the packet will get thrown out.
This can be a problem in stack overflow cases (e.g. infinite recursion).
2019-03-03 15:43:04 -08:00
Tyler Veness
a095ec2d8f Fix linker errors with free functions in Threads.h (#1625)
The functions in Threads.h are in the frc namespace. `using namespace frc;` in
Threads.cpp doesn't put their implementations in the frc namespace, so linker
errors occur when attempting to use them in robot programs.

To fix this, one can either wrap them in a namespace block or prepend
`frc::` to the implementation's signature. Based on past discussion, I
opted for the namespace block.
2019-03-03 15:39:59 -08:00
Thad House
12ab035aad Fix receive side of LabVIEW USB streams (#1621)
LabView only accepts %20 instead of + for parameters, only sends '\n' at the boundaries,
and includes the -- when sending the initial boundary.  This solves those parts.

This is not fully enough to fix shuffleboard and others, as the NT format for paths is not the correct path.
2019-03-03 11:20:43 -08:00
Thad House
99e4f7dd2c Fix SPI CS1 not working correctly (#1614)
It was failing the check when remapping digital sources
2019-02-25 18:48:22 -08:00
2437 changed files with 176820 additions and 27488 deletions

View File

@@ -0,0 +1,10 @@
name: "Validate Gradle Wrapper"
on: [push]
jobs:
validation:
name: "Validation"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1

10
.gitignore vendored
View File

@@ -2,7 +2,8 @@
dependency-reduced-pom.xml
doxygen.log
buildcmake/
build*/
!buildSrc/
# Created by the jenkins test script
test-reports
@@ -214,3 +215,10 @@ ipch/
# Visual Studio 2015 cache/options directory
.vs/
# compile_commands
compile_commands.json
# clang configuration and clangd cache
.clang
.clangd/

View File

@@ -9,16 +9,9 @@ cppSrcFileInclude {
}
generatedFileExclude {
gtest/
ni-libraries/include/
ni-libraries/lib/
FRCNetComm\.java$
simulation/frc_gazebo_plugins/frcgazebo/
simulation/gz_msgs/src/include/simulation/gz_msgs/msgs\.h$
}
modifiableFileExclude {
\.so$
simulation/halsim_gui/src/main/native/include/portable-file-dialogs\.h$
}
repoRootNameOverride {
@@ -29,11 +22,13 @@ includeOtherLibs {
^cameraserver/
^cscore
^hal/
^imgui
^mockdata/
^networktables/
^ntcore
^opencv2/
^support/
^units/
^vision/
^wpi/
}

View File

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

View File

@@ -48,8 +48,14 @@ option(WITHOUT_JAVA "don't include java and JNI in the build" OFF)
option(BUILD_SHARED_LIBS "build with shared libs (needed for JNI)" ON)
option(WITHOUT_CSCORE "Don't build cscore (removes OpenCV requirement)" OFF)
option(WITHOUT_ALLWPILIB "Don't build allwpilib (removes OpenCV requirement)" ON)
option(WITH_TESTS "build unit tests (requires internet connection)" OFF)
option(USE_EXTERNAL_HAL "Use a separately built HAL" OFF)
set(EXTERNAL_HAL_FILE "" CACHE FILEPATH "Location to look for an external HAL CMake File")
option(USE_VCPKG_LIBUV "Use vcpkg libuv" OFF)
option(USE_VCPKG_EIGEN "Use vcpkg eigen" OFF)
option(FLAT_INSTALL_WPILIB "Use a flat install directory" OFF)
option(WITH_SIMULATION_MODULES "build simulation modules" OFF)
set(OPENCV_JAVA_INSTALL_DIR "" CACHE PATH "Location to search for the OpenCV jar file")
if (NOT WITHOUT_JAVA AND NOT BUILD_SHARED_LIBS)
message(FATAL_ERROR "
@@ -59,34 +65,82 @@ FATAL: Cannot build static libs with Java enabled.
")
endif()
if (WITHOUT_JAVA OR WITHOUT_CSCORE)
if(NOT "${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
message(WARNING "
WARNING: OpenCV Java dir set but java is not enabled!
It will be ignored.
")
endif()
endif()
set( wpilib_dest wpilib)
set( include_dest wpilib/include )
set( main_lib_dest wpilib/lib )
set( java_lib_dest wpilib/java )
set( jni_lib_dest wpilib/jni )
if (MSVC)
if (MSVC OR FLAT_INSTALL_WPILIB)
set (wpilib_config_dir ${wpilib_dest})
else()
set (wpilib_config_dir share/wpilib)
endif()
if (USE_VCPKG_LIBUV)
set (LIBUV_VCPKG_REPLACE "find_package(unofficial-libuv CONFIG)")
endif()
if (USE_VCPKG_EIGEN)
set (EIGEN_VCPKG_REPLACE "find_package(Eigen3 CONFIG)")
endif()
if (MSVC OR FLAT_INSTALL_WPILIB)
set(WPIUTIL_DEP_REPLACE "include($\{SELF_DIR\}/wpiutil-config.cmake)")
set(NTCORE_DEP_REPLACE "include($\{SELF_DIR\}/ntcore-config.cmake)")
set(CSCORE_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cscore-config.cmake)")
set(CAMERASERVER_DEP_REPLACE_IMPL "include(\${SELF_DIR}/cameraserver-config.cmake)")
set(HAL_DEP_REPLACE_IMPL "include(\${SELF_DIR}/hal-config.cmake)")
set(WPILIBC_DEP_REPLACE_IMPL "include(\${SELF_DIR}/wpilibc-config.cmake)")
else()
set(WPIUTIL_DEP_REPLACE "find_dependency(wpiutil)")
set(NTCORE_DEP_REPLACE "find_dependency(ntcore)")
set(CSCORE_DEP_REPLACE_IMPL "find_dependency(cscore)")
set(CAMERASERVER_DEP_REPLACE_IMPL "find_dependency(cameraserver)")
set(HAL_DEP_REPLACE_IMPL "find_dependency(hal)")
set(WPILIBC_DEP_REPLACE_IMPL "find_dependency(wpilibc)")
endif()
set(FILENAME_DEP_REPLACE "get_filename_component(SELF_DIR \"$\{CMAKE_CURRENT_LIST_FILE\}\" PATH)")
set(SELF_DIR "$\{SELF_DIR\}")
if (WITH_TESTS)
enable_testing()
add_subdirectory(googletest)
include(GoogleTest)
endif()
add_subdirectory(wpiutil)
add_subdirectory(ntcore)
if (NOT WITHOUT_CSCORE)
set(CSCORE_DEP_REPLACE ${CSCORE_DEP_REPLACE_IMPL})
set(CAMERASERVER_DEP_REPLACE ${CAMERASERVER_DEP_REPLACE_IMPL})
add_subdirectory(cscore)
add_subdirectory(cameraserver)
set (CSCORE_DEP_REPLACE "find_dependency(cscore)")
set (CAMERASERVER_DEP_REPLACE "find_dependency(cameraserver)")
if (NOT WITHOUT_ALLWPILIB)
set(HAL_DEP_REPLACE ${HAL_DEP_REPLACE_IMPL})
set(WPILIBC_DEP_REPLACE ${WPILIBC_DEP_REPLACE_IMPL})
add_subdirectory(hal)
add_subdirectory(wpilibj)
add_subdirectory(wpilibc)
set (HAL_DEP_REPLACE "find_dependency(hal)")
set (WPILIBC_DEP_REPLACE "find_dependency(wpilibc)")
add_subdirectory(myRobot)
endif()
endif()
if (WITH_SIMULATION_MODULES AND NOT USE_EXTERNAL_HAL)
add_subdirectory(imgui)
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})

View File

@@ -20,7 +20,7 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
- Substantial changes often need to have corresponding LabVIEW changes. To do this, we will work with NI on these large changes.
- Changes should have tests.
- Code should be well documented.
- This often involves ScreenSteps. To add content to ScreenSteps, we will work with you to get the appropriate articles written.
- This involves writing tutorials and/or usage guides for your submitted feature. These articles are then hosted on the [WPILib](https://docs.wpilib.org/) documentation website. See the [frc-docs repository](https://github.com/wpilibsuite/frc-docs) for more information.
## What to Contribute
@@ -37,7 +37,7 @@ So you want to contribute your changes back to WPILib. Great! We have a few cont
## Coding Guidelines
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 5.0 with wpiformat.
WPILib uses modified Google style guides for both C++ and Java, which can be found in the [styleguide repository](https://github.com/wpilibsuite/styleguide). Autoformatters are available for many popular editors at https://github.com/google/styleguide. Running wpiformat is required for all contributions and is enforced by our continuous integration system. We currently use clang-format 6.0 with wpiformat.
While the library should be fully formatted according to the styles, additional elements of the style guide were not followed when the library was initially created. All new code should follow the guidelines. If you are looking for some easy ramp-up tasks, finding areas that don't follow the style guide and fixing them is very welcome.
@@ -53,4 +53,4 @@ When you first submit changes, Travis-CI will attempt to run `./gradlew check` o
## Licensing
By contributing to WPILib, you agree that your code will be distributed with WPILib, and licensed under the license for the WPILib project. You should not contribute code that you do not have permission to relicense in this manner. This includes code that is licensed under the GPL that you do not have permission to relicense, as WPILib is not released under a copyleft license. Our license is the 3-clause BSD license, which you can find [here](license.txt).
By contributing to WPILib, you agree that your code will be distributed with WPILib, and licensed under the license for the WPILib project. You should not contribute code that you do not have permission to relicense in this manner. This includes code that is licensed under the GPL that you do not have permission to relicense, as WPILib is not released under a copyleft license. Our license is the 3-clause BSD license, which you can find [here](LICENSE.txt).

15
FasterBuilds.md Normal file
View File

@@ -0,0 +1,15 @@
# Faster Builds for Developers
When you run `./gradlew build`, it builds EVERYTHING. This means debug and release builds for desktop and all installed cross compilers. For many developers, this is way too much, and causes much developer pain.
To help with some of these things, common tasks have shortcuts to only build necessary things for common development and testing tasks.
## Development (Desktop)
For projects `wpiutil`, `ntcore`, `cscore`, `hal` `wpilibOldCommands`, `wpilibNewCommands` and `cameraserver`, a `testDesktopJava` and a `testDesktopCpp` task exists. These can be ran with `./gradlew :projectName:task`, and will only build the minimum things required to run those tests.
For `wpilibc`, a `testDesktopCpp` task exists. For `wpilibj`, a `testDesktopJava` task exists.
For `wpilibcExamples`, a `buildDesktopCpp` task exists (These can't be ran, but they can compile).
For `wpilibjExamples`, a `buildDesktopJava` task exists.

View File

@@ -5,8 +5,8 @@ WPILib publishes its built artifacts to our Maven server for use by downstream p
## Repositories
We provide two repositories. These repositories are:
* (Release) http://first.wpi.edu/FRC/roborio/maven/release/
* (Development) http://first.wpi.edu/FRC/roborio/maven/development/
* (Release) https://frcmaven.wpi.edu/artifactory/release/
* (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.
@@ -72,6 +72,10 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* hal
* wpiutil
* halsim
* imgui
* wpiutil
* ntcore
* wpiutil
@@ -85,7 +89,6 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* opencv
* wpiutil
* wpilibj
* hal
* cameraserver
@@ -93,10 +96,35 @@ All artifacts are based at `edu.wpi.first.artifactname` in the repository.
* cscore
* wpiutil
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
* wpilibNewCommands
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
* wpilibNewCommands
* wpilibc
* hal
* cameraserver
* ntcore
* cscore
* wpiutil
### Third Party Artifacts
This repository provides the builds of the following third party software.
All artifacts are based at `edu.wpi.first.thirdparty.frcYEAR` in the repository.
* googletest
* imgui
* opencv

View File

@@ -34,6 +34,8 @@ The following build options are available:
* TODO
* EXTERNAL_HAL_FILE
* TODO
* OPENCV_JAVA_INSTALL_DIR
* Set this option to the location of the archive of the OpenCV Java bindings (it should be called opencv-xxx.jar, with the x'es being version numbers). NOTE: set it to the LOCATION of the file, not the file itself!
## Build Setup

View File

@@ -25,10 +25,10 @@ Using Gradle makes building WPILib very straightforward. It only has a few depen
- A C++ compiler
- On Linux, GCC works fine
- On Windows, you need Visual Studio 2017 (the free community edition works fine).
- On Windows, you need Visual Studio 2019 (the free community edition works fine).
Make sure to select the C++ Programming Language for installation
- [ARM Compiler Toolchain](https://github.com/wpilibsuite/toolchain-builder/releases)
* Note that for 2019 and beyond, you should use version 6 or greater of GCC
- [ARM Compiler Toolchain](https://github.com/wpilibsuite/roborio-toolchain/releases)
* Note that for 2020 and beyond, you should use version 7 or greater of GCC
- Doxygen (Only required if you want to build the C++ documentation)
## Setup

View File

@@ -31,13 +31,20 @@ 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
Optional wpiutil/src/main/native/include/wpi/optional.h
wpiutil/src/test/native/cpp/test_optional.cpp
Bootstrap wpiutil/src/main/native/resources/bootstrap-*
CoreUI wpiutil/src/main/native/resources/coreui-*
Feather Icons wpiutil/src/main/native/resources/feather-*
jQuery wpiutil/src/main/native/resources/jquery-*
popper.js wpiutil/src/main/native/resources/popper-*
units wpiutil/src/main/native/include/units/units.h
Eigen wpiutil/src/main/native/eigeninclude/
StackWalker wpiutil/src/main/native/windows/StackWalker.*
Team 254 Library wpilibj/src/main/java/edu/wpi/first/wpilibj/spline/SplineParameterizer.java
wpilibj/src/main/java/edu/wpi/first/wpilibj/trajectory/TrajectoryParameterizer.java
wpilibc/src/main/native/include/spline/SplineParameterizer.h
wpilibc/src/main/native/include/trajectory/TrajectoryParameterizer.h
wpilibc/src/main/native/cpp/trajectory/TrajectoryParameterizer.cpp
Portable File Dialogs simulation/halsim_gui/src/main/native/include/portable-file-dialogs.h
==============================================================================
@@ -221,36 +228,6 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================
Optional License
==============================================================================
Copyright (C) 2011 - 2017 Andrzej Krzemienski.
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.
==============================================================================
Bootstrap License
==============================================================================
@@ -371,3 +348,462 @@ 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.
=============
units License
=============
The MIT License (MIT)
Copyright (c) 2016 Nic Holthaus
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.
=============
Eigen license
=============
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
===================
StackWalker License
===================
Copyright (c) 2005-2013, Jochen Kalmbach
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
Neither the name of Jochen Kalmbach nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================
Team 254 Library
================
MIT License
Copyright (c) 2018 Team 254
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

@@ -0,0 +1,91 @@
# Testing steps for real hardware
trigger:
batch: true
branches:
include:
- master
stages:
- stage: Build
jobs:
- job: IntegrationTests
displayName: Integration Tests
pool:
vmImage: 'Ubuntu 16.04'
container:
image: wpilib/roborio-cross-ubuntu:2020-18.04
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'
- 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'
- 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'
- 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: PublishTestResults@2
displayName: Publish Java Test Results
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: '*.xml'
testRunTitle: 'Java Test Report'
searchFolder: '$(System.DefaultWorkingDirectory)/test-reports'

View File

@@ -5,179 +5,413 @@
resources:
containers:
- container: wpilib2019
image: wpilib/roborio-cross-ubuntu:2019-18.04
- container: wpilib2020
image: wpilib/roborio-cross-ubuntu:2020-18.04
- container: raspbian
image: wpilib/raspbian-cross-ubuntu:18.04
image: wpilib/raspbian-cross-ubuntu:10-18.04
- container: aarch64
image: wpilib/aarch64-cross-ubuntu:bionic-18.04
- container: ubuntu
image: wpilib/ubuntu-base:18.04
jobs:
- job: Linux_Arm
pool:
vmImage: 'Ubuntu 16.04'
variables:
- group: Artifactory-Package-Publish
container: wpilib2019
trigger:
batch: true
branches:
include:
- master
steps:
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PonlyAthena'
# checkStyleRunAnalysis: true
# pmdRunAnalysis: true
stages:
- stage: Build
jobs:
- job: Linux_Arm
pool:
vmImage: 'Ubuntu 16.04'
- job: Linux_Raspbian
pool:
vmImage: 'Ubuntu 16.04'
container: wpilib2020
container: raspbian
timeoutInMinutes: 0
steps:
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PonlyRaspbian'
# checkStyleRunAnalysis: true
# pmdRunAnalysis: true
- job: Linux
pool:
vmImage: 'Ubuntu 16.04'
container: wpilib2019
steps:
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PskipAthena'
# checkStyleRunAnalysis: true
# pmdRunAnalysis: true
- job: Styleguide
pool:
vmImage: 'Ubuntu 16.04'
steps:
- script: |
sudo apt-get update -y
sudo apt-get install clang-format-5.0 python3-setuptools -y
sudo pip3 install --upgrade pip
sudo pip3 install wpiformat
git checkout -b master
displayName: 'Install Dependencies'
- script: |
wpiformat -y 2018 -clang 5.0
displayName: 'Run WPIFormat'
failOnStderr: true
- script: |
git --no-pager diff --exit-code HEAD # Ensure formatter made no changes
displayName: 'Check WPIFormat Output'
failOnStderr: true
- job: CMakeBuild
pool:
vmImage: 'Ubuntu 16.04'
container: wpilib2019
steps:
- task: CMake@1
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
cmakeArgs: '-DWITHOUT_ALLWPILIB=OFF ..'
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-Ponlylinuxathena -PbuildServer'
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: false
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-Ponlylinuxathena -PreleaseMode -PbuildServer'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Athena'
targetPath: 'build/allOutputs'
- job: Linux_Raspbian
pool:
vmImage: 'Ubuntu 16.04'
container: raspbian
timeoutInMinutes: 0
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-Ponlylinuxraspbian -PbuildServer'
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-Ponlylinuxraspbian -PreleaseMode -PbuildServer'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Raspbian'
targetPath: 'build/allOutputs'
- job: Linux_Aarch64
pool:
vmImage: 'Ubuntu 16.04'
container: aarch64
timeoutInMinutes: 0
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-Ponlylinuxaarch64bionic -PbuildServer'
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-Ponlylinuxaarch64bionic -PreleaseMode -PbuildServer'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Aarch64'
targetPath: 'build/allOutputs'
- job: Linux
pool:
vmImage: 'Ubuntu 16.04'
container: ubuntu
timeoutInMinutes: 0
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PbuildServer'
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PreleaseMode -PbuildServer'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Linux'
targetPath: 'build/allOutputs'
- job: Styleguide
pool:
vmImage: 'Ubuntu 16.04'
container: ubuntu
timeoutInMinutes: 0
steps:
- script: |
sudo pip3 install wpiformat
displayName: 'Install wpiformat'
- script: |
git checkout -b master
wpiformat -clang 6.0
displayName: 'Run wpiformat'
- script: |
# Ensure formatter made no changes
git --no-pager diff --exit-code HEAD
displayName: 'Check wpiformat Output'
- job: CMakeBuild
pool:
vmImage: 'Ubuntu 16.04'
container: wpilib2020
timeoutInMinutes: 0
steps:
- task: CMake@1
inputs:
cmakeArgs: '-DWITHOUT_ALLWPILIB=OFF ..'
- script: |
make -j3
workingDirectory: 'build'
displayName: 'Build'
- job: Windows_64_Bit
pool:
vmImage: 'windows-2019'
timeoutInMinutes: 0
steps:
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
jdkVersionOption: '1.11'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PskipPMD -PbuildServer'
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
jdkVersionOption: '1.11'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PskipPMD -PreleaseMode -PbuildServer'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Win64'
targetPath: 'build/allOutputs'
- job: Windows_32_Bit
pool:
vmImage: 'windows-2019'
timeoutInMinutes: 0
steps:
- powershell: |
mkdir build
$ProgressPreference = 'SilentlyContinue'
wget "https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.4%2B11/OpenJDK11U-jdk_x86-32_windows_hotspot_11.0.4_11.zip" -O "build\jdk.zip"
displayName: 'Download JDK'
- task: JavaToolInstaller@0
inputs:
jdkSourceOption: localDirectory
jdkFile: 'build/jdk.zip'
jdkDestinationDirectory: 'build/jdkinst'
jdkArchitectureOption: x86
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx1024m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PskipPMD -PbuildServer'
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx1024m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PskipPMD -PreleaseMode -PbuildServer'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Win32'
targetPath: 'build/allOutputs'
- job: Mac
pool:
vmImage: 'macOS-10.14'
timeoutInMinutes: 0
steps:
- script: |
make -j3
workingDirectory: 'build'
displayName: 'Build'
mkdir build
export JAVA_HOME=`/usr/libexec/java_home -v 11`
displayName: 'Setup JDK'
- job: Windows_64_Bit
pool:
vmImage: 'vs2017-win2016'
steps:
- powershell: |
mkdir build
$ProgressPreference = 'SilentlyContinue'
wget "https://download.java.net/java/ga/jdk11/openjdk-11_windows-x64_bin.zip" -O "build\jdk.zip"
displayName: 'Download JDK'
- task: JavaToolInstaller@0
inputs:
jdkSourceOption: localDirectory
jdkFile: 'build/jdk.zip'
jdkDestinationDirectory: 'build/jdkinst'
jdkArchitectureOption: x64
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
# checkStyleRunAnalysis: true
# pmdRunAnalysis: true
- task: Gradle@2
condition: and(succeeded(), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
jdkVersionOption: '1.11'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PbuildServer'
- job: Windows_32_Bit
pool:
vmImage: 'vs2017-win2016'
steps:
- powershell: |
mkdir build
$ProgressPreference = 'SilentlyContinue'
wget "https://github.com/wpilibsuite/frc-openjdk-windows/releases/download/v11.0.0u28-1/jdk-x86-11.0.0u28-1.zip" -O "build\jdk.zip"
displayName: 'Download JDK'
- task: JavaToolInstaller@0
inputs:
jdkSourceOption: localDirectory
jdkFile: 'build/jdk.zip'
jdkDestinationDirectory: 'build/jdkinst'
jdkArchitectureOption: x86
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx1024m'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
# checkStyleRunAnalysis: true
# pmdRunAnalysis: true
- task: Gradle@2
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
gradleOptions: '-Xmx3072m'
jdkVersionOption: '1.11'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
options: '-PreleaseMode -PbuildServer'
- job: Mac
pool:
vmImage: 'xcode9-macos10.13'
steps:
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Mac'
targetPath: 'build/allOutputs'
- stage: Combine
jobs:
- job: CombineJob
pool:
vmImage: 'macOS-10.14'
timeoutInMinutes: 0
steps:
- checkout: none
- script: |
mkdir build
wget "https://download.java.net/java/ga/jdk11/openjdk-11_osx-x64_bin.tar.gz" -O "build/jdk.tar.gz"
sudo tar xvzf build/jdk.tar.gz -C /Library/Java/JavaVirtualMachines/
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/
displayName: 'Setup JDK'
- script: |
rm /Users/vsts/.gradle/init.d/log-gradle-version-plugin.gradle
displayName: 'Delete Version init script'
git clone https://github.com/wpilibsuite/build-tools
displayName: 'Clone Combiner'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Mac'
targetPath: 'build-tools/combiner/products/build/allOutputs'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Win32'
targetPath: 'build-tools/combiner/products/build/allOutputs'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Win64'
targetPath: 'build-tools/combiner/products/build/allOutputs'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Linux'
targetPath: 'build-tools/combiner/products/build/allOutputs'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Raspbian'
targetPath: 'build-tools/combiner/products/build/allOutputs'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Athena'
targetPath: 'build-tools/combiner/products/build/allOutputs'
- task: DownloadPipelineArtifact@0
inputs:
artifactName: 'Aarch64'
targetPath: 'build-tools/combiner/products/build/allOutputs'
# PR Builds
- task: Gradle@2
inputs:
workingDirectory: ''
gradleWrapperFile: 'gradlew'
workingDirectory: 'build-tools/combiner'
gradleWrapperFile: 'build-tools/combiner/gradlew'
gradleOptions: '-Xmx3072m'
javaHomeOption: 'path'
jdkDirectory: '/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home/'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
tasks: 'build'
# checkStyleRunAnalysis: true
# pmdRunAnalysis: true
tasks: 'publish '
options: '-Pallwpilib'
condition: and(succeeded(), and(ne(variables['Build.SourceBranch'], 'refs/heads/master'), not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))))
# Master Builds
- task: Gradle@2
inputs:
workingDirectory: 'build-tools/combiner'
gradleWrapperFile: 'build-tools/combiner/gradlew'
gradleOptions: '-Xmx3072m'
tasks: 'publish '
options: '-Pallwpilib'
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
env:
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
ARTIFACTORY_PUBLISH_USERNAME: $(PublishUserName)
ARTIFACTORY_PUBLISH_PASSWORD: $(PublishPassword)
# Tagged Builds
- task: Gradle@2
inputs:
workingDirectory: 'build-tools/combiner'
gradleWrapperFile: 'build-tools/combiner/gradlew'
gradleOptions: '-Xmx3072m'
tasks: 'publish '
options: '-Pallwpilib -PreleaseRepoPublish'
condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'))
env:
RUN_AZURE_ARTIFACTORY_RELEASE: 'TRUE'
ARTIFACTORY_PUBLISH_USERNAME: $(PublishUserName)
ARTIFACTORY_PUBLISH_PASSWORD: $(PublishPassword)
- script: |
echo "##vso[task.setvariable variable=UserHome]$HOME"
displayName: 'Set Home Variable'
- task: PublishPipelineArtifact@0
inputs:
artifactName: 'Maven'
targetPath: $(UserHome)/releases

View File

@@ -1,18 +1,35 @@
import edu.wpi.first.toolchain.*
plugins {
id 'base'
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '2.3'
id 'edu.wpi.first.NativeUtils' version '2.1.2'
id 'edu.wpi.first.GradleJni' version '0.3.1'
id 'edu.wpi.first.GradleVsCode' version '0.7.1'
id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '4.0.1'
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 'idea'
id 'visual-studio'
id 'com.gradle.build-scan' version '2.0.2'
id 'net.ltgt.errorprone' version '0.6' apply false
id 'com.github.johnrengelman.shadow' version '4.0.3' apply false
id 'net.ltgt.errorprone' version '1.1.1' apply false
id 'com.github.johnrengelman.shadow' version '5.2.0' apply false
}
repositories {
mavenCentral()
if (project.hasProperty('buildServer')) {
wpilibVersioning.buildServerMode = true
}
if (project.hasProperty('releaseMode')) {
wpilibVersioning.releaseMode = true
}
allprojects {
repositories {
mavenCentral()
}
if (project.hasProperty('releaseMode')) {
wpilibRepositories.addAllReleaseRepositories(it)
} else {
wpilibRepositories.addAllDevelopmentRepositories(it)
}
}
buildScan {
@@ -24,20 +41,11 @@ buildScan {
ext.licenseFile = files("$rootDir/LICENSE.txt", "$rootDir/ThirdPartyNotices.txt")
// Ensure that the WPILibVersioningPlugin is setup by setting the release type, if releaseType wasn't
// already specified on the command line
if (!hasProperty('releaseType')) {
WPILibVersion {
releaseType = 'dev'
}
if (project.hasProperty("publishVersion")) {
wpilibVersioning.version.set(project.publishVersion)
}
def pubVersion
if (project.hasProperty("publishVersion")) {
pubVersion = project.publishVersion
} else {
pubVersion = WPILibVersion.version
}
wpilibVersioning.version.finalizeValue()
def outputsFolder = file("$buildDir/allOutputs")
@@ -54,7 +62,7 @@ task outputVersions() {
}
doLast {
versionFile.write pubVersion
versionFile.write wpilibVersioning.version.get()
}
}
@@ -87,18 +95,20 @@ subprojects {
apply from: "${rootDir}/shared/java/javastyle.gradle"
repositories {
mavenCentral()
}
// Disables doclint in java 8.
if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) {
options.addStringOption('Xdoclint:none', '-quiet')
if (project.name != "docs") {
options.addStringOption('Xdoclint:none', '-quiet')
}
}
}
}
wrapper {
gradleVersion = '5.0'
ext.getCurrentArch = {
return NativePlatforms.desktop
}
wrapper {
gradleVersion = '6.0'
}

9
buildSrc/build.gradle Normal file
View File

@@ -0,0 +1,9 @@
repositories {
maven {
url "https://plugins.gradle.org/m2/"
mavenLocal()
}
}
dependencies {
implementation "edu.wpi.first:native-utils:2020.7.2"
}

View File

@@ -0,0 +1,70 @@
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import edu.wpi.first.toolchain.ToolchainExtension
import org.gradle.model.Mutate;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.NativeExecutableBinarySpec
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.BinaryContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import groovy.transform.CompileDynamic
import org.gradle.nativeplatform.BuildTypeContainer
@CompileStatic
class DisableBuildingGTest implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@CompileDynamic
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
binary.buildable = false
}
@Validate
@CompileStatic
// TODO: Move this to tc plugin
void disableCrossTests(BinaryContainer binaries, ExtensionContainer extContainer) {
final ToolchainExtension ext = extContainer.getByType(ToolchainExtension.class);
for (GoogleTestTestSuiteBinarySpec binary : binaries.withType(GoogleTestTestSuiteBinarySpec.class)) {
if (ext.getCrossCompilers().findByName(binary.getTargetPlatform().getName()) != null) {
setBuildableFalseDynamically(binary)
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
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

@@ -1,95 +1,74 @@
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import org.gradle.model.Mutate;
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.NativeExecutableBinarySpec
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.BinaryContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import groovy.transform.CompileDynamic
import org.gradle.nativeplatform.BuildTypeContainer
@CompileStatic
class MultiBuilds implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@Mutate
void setupBuildTypes(BuildTypeContainer buildTypes, ProjectLayout projectLayout) {
def project = (Project) projectLayout.projectIdentifier
if (project.hasProperty('releaseBuild')) {
buildTypes.create('debug')
} else {
buildTypes.create('release')
}
}
@CompileDynamic
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
binary.buildable = false
}
@Mutate
@CompileStatic
void disableReleaseGoogleTest(BinaryContainer binaries, ProjectLayout projectLayout) {
def project = (Project) projectLayout.projectIdentifier
if (project.hasProperty('testRelease')) {
return
}
binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
if (spec.buildType.name == 'release') {
Rules.setBuildableFalseDynamically(spec)
}
}
// def crossCompileConfigs = []
// for (BuildConfig config : configs) {
// if (!BuildConfigRulesBase.isCrossCompile(config)) {
// continue
// }
// crossCompileConfigs << config.architecture
// }
// if (!crossCompileConfigs.empty) {
// binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
// GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
// if (crossCompileConfigs.contains(spec.targetPlatform.architecture.name)) {
// setBuildableFalseDynamically(spec)
// }
// }
// }
}
}
}
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.language.base.internal.ProjectLayout;
import org.gradle.language.base.plugins.ComponentModelBasePlugin;
import org.gradle.language.nativeplatform.tasks.AbstractNativeSourceCompileTask;
import org.gradle.model.ModelMap;
import edu.wpi.first.toolchain.ToolchainExtension
import org.gradle.model.Mutate;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.nativeplatform.test.googletest.GoogleTestTestSuiteBinarySpec;
import org.gradle.model.RuleSource;
import org.gradle.model.Validate;
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
import org.gradle.nativeplatform.NativeExecutableBinarySpec
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeComponentSpec;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.SharedLibraryBinarySpec;
import org.gradle.nativeplatform.StaticLibraryBinarySpec;
import org.gradle.nativeplatform.platform.internal.NativePlatformInternal;
import org.gradle.nativeplatform.toolchain.NativeToolChain;
import org.gradle.nativeplatform.toolchain.NativeToolChainRegistry;
import org.gradle.nativeplatform.toolchain.internal.PlatformToolProvider;
import org.gradle.nativeplatform.toolchain.internal.ToolType;
import org.gradle.nativeplatform.toolchain.internal.gcc.AbstractGccCompatibleToolChain;
import org.gradle.nativeplatform.toolchain.internal.msvcpp.VisualCppToolChain;
import org.gradle.nativeplatform.toolchain.internal.tools.ToolRegistry;
import org.gradle.platform.base.BinarySpec;
import org.gradle.platform.base.ComponentSpec;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.platform.base.BinaryContainer;
import org.gradle.platform.base.ComponentType;
import org.gradle.platform.base.TypeBuilder;
import org.gradle.nativeplatform.tasks.ObjectFilesToBinary;
import groovy.transform.CompileStatic;
import groovy.transform.CompileDynamic
import org.gradle.nativeplatform.BuildTypeContainer
@CompileStatic
class MultiBuilds implements Plugin<Project> {
@CompileStatic
public void apply(Project project) {
}
@CompileStatic
static class Rules extends RuleSource {
@CompileDynamic
private static void setBuildableFalseDynamically(NativeBinarySpec binary) {
binary.buildable = false
}
@Mutate
@CompileStatic
void disableReleaseGoogleTest(BinaryContainer binaries, ProjectLayout projectLayout) {
def project = (Project) projectLayout.projectIdentifier
if (project.hasProperty('testRelease')) {
return
}
binaries.withType(GoogleTestTestSuiteBinarySpec) { oSpec ->
GoogleTestTestSuiteBinarySpec spec = (GoogleTestTestSuiteBinarySpec) oSpec
if (spec.buildType.name == 'release') {
Rules.setBuildableFalseDynamically(spec)
}
}
}
}
}

View File

@@ -40,6 +40,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
@CompileStatic
class SingleNativeBuild implements Plugin<Project> {
@@ -50,6 +51,22 @@ class SingleNativeBuild implements Plugin<Project> {
@CompileStatic
static class Rules extends RuleSource {
@Mutate
@CompileStatic
void removeMacSystemIncludes(ModelMap<Task> tasks, BinaryContainer binaries) {
binaries.each {
if (!(it instanceof NativeBinarySpec)) {
return
}
NativeBinarySpec nativeBin = (NativeBinarySpec)it
if (nativeBin.targetPlatform.operatingSystem.isMacOsX()) {
nativeBin.tasks.withType(AbstractNativeSourceCompileTask) { AbstractNativeSourceCompileTask compileTask->
compileTask.getSystemIncludes().setFrom()
}
}
}
}
@Mutate
@CompileStatic
void setupSingleNativeBuild(ModelMap<Task> tasks, ComponentSpecContainer components, BinaryContainer binaryContainer, ProjectLayout projectLayout) {
@@ -78,8 +95,7 @@ class SingleNativeBuild implements Plugin<Project> {
return
}
def tmpBaseBin = (NativeBinarySpec) oTmpBaseBin
if (tmpBaseBin.targetPlatform.operatingSystem.name == binary.targetPlatform.operatingSystem.name &&
tmpBaseBin.targetPlatform.architecture.name == binary.targetPlatform.architecture.name &&
if (tmpBaseBin.targetPlatform.name == binary.targetPlatform.name &&
tmpBaseBin.buildType == binary.buildType) {
baseBin = tmpBaseBin
}
@@ -89,6 +105,10 @@ class SingleNativeBuild implements Plugin<Project> {
if (binary instanceof SharedLibraryBinarySpec) {
def sBinary = (SharedLibraryBinarySpec) binary
ObjectFilesToBinary link = (ObjectFilesToBinary) sBinary.tasks.link
ExportsGenerationTask exportsTask = binary.tasks.withType(ExportsGenerationTask)[0]
if (exportsTask != null) {
exportsTask.dependsOn compileTask
}
link.dependsOn compileTask
link.inputs.dir compileTask.objectFileDir
def tree = project.fileTree(compileTask.objectFileDir)

View File

@@ -7,16 +7,12 @@ cppSrcFileInclude {
\.cpp$
}
modifiableFileExclude {
\.so$
}
repoRootNameOverride {
cameraserver
}
includeOtherLibs {
^HAL/
^hal/
^networktables/
^opencv2/
^support/

View File

@@ -1,5 +1,8 @@
project(cameraserver)
include(CompileWarnings)
include(AddTest)
find_package( OpenCV REQUIRED )
# Java bindings
@@ -32,6 +35,7 @@ set_target_properties(cameraserver PROPERTIES DEBUG_POSTFIX "d")
target_include_directories(cameraserver PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
$<INSTALL_INTERFACE:${include_dest}/cameraserver>)
wpilib_target_warnings(cameraserver)
target_link_libraries(cameraserver PUBLIC ntcore cscore wpiutil ${OpenCV_LIBS})
set_property(TARGET cameraserver PROPERTY FOLDER "libraries")
@@ -43,15 +47,24 @@ if (NOT WITHOUT_JAVA AND MSVC)
install(TARGETS cameraserver RUNTIME DESTINATION "${jni_lib_dest}" COMPONENT Runtime)
endif()
if (MSVC)
if (MSVC OR FLAT_INSTALL_WPILIB)
set (cameraserver_config_dir ${wpilib_dest})
else()
set (cameraserver_config_dir share/cameraserver)
endif()
install(FILES cameraserver-config.cmake DESTINATION ${cameraserver_config_dir})
configure_file(cameraserver-config.cmake.in ${CMAKE_BINARY_DIR}/cameraserver-config.cmake )
install(FILES ${CMAKE_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)
add_executable(multiCameraServer ${multiCameraServer_src})
wpilib_target_warnings(multiCameraServer)
target_link_libraries(multiCameraServer cameraserver)
set_property(TARGET multiCameraServer PROPERTY FOLDER "examples")
if (WITH_TESTS)
wpilib_add_test(cameraserver src/test/native/cpp)
target_link_libraries(cameraserver_test cameraserver gtest)
endif()

View File

@@ -10,12 +10,12 @@ evaluationDependsOn(':hal')
apply from: "${rootDir}/shared/javacpp/setupBuild.gradle"
dependencies {
compile project(':wpiutil')
compile project(':ntcore')
compile project(':cscore')
devCompile project(':wpiutil')
devCompile project(':ntcore')
devCompile project(':cscore')
implementation project(':wpiutil')
implementation project(':ntcore')
implementation project(':cscore')
devImplementation project(':wpiutil')
devImplementation project(':ntcore')
devImplementation project(':cscore')
}
ext {
@@ -30,23 +30,20 @@ ext {
apply from: "${rootDir}/shared/opencv.gradle"
model {
// Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL.
// This removes the need for DllExport on a library. However, the gradle C++ builder has a bug
// where some extra symbols are added that cannot be resolved at link time. This configuration
// lets you specify specific symbols to exlude from exporting.
exportsConfigs {
cameraserver(ExportsConfig) {
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']
}
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']
}
}
model {
components {}
binaries {
all {
@@ -66,7 +63,7 @@ model {
if (it in NativeExecutableSpec && it.name == "${nativeName}Dev") {
it.binaries.each {
if (!found) {
def arch = it.targetPlatform.architecture.name
def arch = it.targetPlatform.name
if (arch == systemArch) {
def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib'

View File

@@ -1,8 +0,0 @@
include(CMakeFindDependencyMacro)
find_dependency(wpiutil)
find_dependency(ntcore)
find_dependency(cscore)
find_dependency(OpenCV)
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(${SELF_DIR}/cameraserver.cmake)

View File

@@ -0,0 +1,8 @@
include(CMakeFindDependencyMacro)
@FILENAME_DEP_REPLACE@
@WPIUTIL_DEP_REPLACE@
@NTCORE_DEP_REPLACE@
@CSCORE_DEP_REPLACE@
find_dependency(OpenCV)
include(${SELF_DIR}/cameraserver.cmake)

View File

@@ -27,12 +27,12 @@ repositories {
}
dependencies {
compile 'com.google.code.gson:gson:2.8.5'
implementation 'com.google.code.gson:gson:2.8.5'
compile project(':wpiutil')
compile project(':ntcore')
compile project(':cscore')
compile project(':cameraserver')
implementation project(':wpiutil')
implementation project(':ntcore')
implementation project(':cscore')
implementation project(':cameraserver')
}
model {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -9,8 +9,9 @@ package edu.wpi.first.cameraserver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import edu.wpi.cscore.AxisCamera;
@@ -142,17 +143,21 @@ public final class CameraServer {
values[j] = "mjpg:" + values[j];
}
// Look to see if we have a passthrough server for this source
for (VideoSink i : m_sinks.values()) {
int sink = i.getHandle();
int sinkSource = CameraServerJNI.getSinkSource(sink);
if (source == sinkSource
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink)) == VideoSink.Kind.kMjpeg) {
// Add USB-only passthrough
String[] finalValues = Arrays.copyOf(values, values.length + 1);
int port = CameraServerJNI.getMjpegServerPort(sink);
finalValues[values.length] = makeStreamValue("172.22.11.2", port);
return finalValues;
if (CameraServerSharedStore.getCameraServerShared().isRoboRIO()) {
// Look to see if we have a passthrough server for this source
// Only do this on the roboRIO
for (VideoSink i : m_sinks.values()) {
int sink = i.getHandle();
int sinkSource = CameraServerJNI.getSinkSource(sink);
if (source == sinkSource
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink))
== VideoSink.Kind.kMjpeg) {
// Add USB-only passthrough
String[] finalValues = Arrays.copyOf(values, values.length + 1);
int port = CameraServerJNI.getMjpegServerPort(sink);
finalValues[values.length] = makeStreamValue("172.22.11.2", port);
return finalValues;
}
}
}
@@ -166,13 +171,9 @@ public final class CameraServer {
int sink = i.getHandle();
// Get the source's subtable (if none exists, we're done)
int source;
Integer fixedSource = m_fixedSources.get(sink);
if (fixedSource != null) {
source = fixedSource;
} else {
source = CameraServerJNI.getSinkSource(sink);
}
int source = Objects.requireNonNullElseGet(m_fixedSources.get(sink),
() -> CameraServerJNI.getSinkSource(sink));
if (source == 0) {
continue;
}
@@ -301,10 +302,10 @@ public final class CameraServer {
"PMD.NPathComplexity"})
private CameraServer() {
m_defaultUsbDevice = new AtomicInteger();
m_sources = new Hashtable<>();
m_sinks = new Hashtable<>();
m_fixedSources = new Hashtable<>();
m_tables = new Hashtable<>();
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];
@@ -615,7 +616,9 @@ public final class CameraServer {
// create a dummy CvSource
CvSource source = new CvSource(name, VideoMode.PixelFormat.kMJPEG, 160, 120, 30);
MjpegServer server = startAutomaticCapture(source);
m_fixedSources.put(server.getHandle(), source.getHandle());
synchronized (this) {
m_fixedSources.put(server.getHandle(), source.getHandle());
}
return server;
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -43,4 +43,13 @@ public interface CameraServerShared {
* @param id the usage id
*/
void reportAxisCamera(int id);
/**
* Get if running on a roboRIO.
*
* @return true if on roboRIO
*/
default boolean isRoboRIO() {
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -77,7 +77,7 @@ public class VisionRunner<P extends VisionPipeline> {
public void runOnce() {
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
if (id != null && Thread.currentThread().getId() == id.longValue()) {
if (id != null && Thread.currentThread().getId() == id) {
throw new IllegalStateException(
"VisionRunner.runOnce() cannot be called from the main robot thread");
}
@@ -110,7 +110,7 @@ public class VisionRunner<P extends VisionPipeline> {
public void runForever() {
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
if (id != null && Thread.currentThread().getId() == id.longValue()) {
if (id != null && Thread.currentThread().getId() == id) {
throw new IllegalStateException(
"VisionRunner.runForever() cannot be called from the main robot thread");
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -13,6 +13,7 @@
#include <networktables/NetworkTable.h>
#include <networktables/NetworkTableInstance.h>
#include <wpi/DenseMap.h>
#include <wpi/ManagedStatic.h>
#include <wpi/SmallString.h>
#include <wpi/StringMap.h>
#include <wpi/mutex.h>
@@ -47,8 +48,14 @@ struct CameraServer::Impl {
};
CameraServer* CameraServer::GetInstance() {
static CameraServer instance;
return &instance;
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 wpi::StringRef MakeSourceValue(CS_Source source,
@@ -56,21 +63,21 @@ static wpi::StringRef MakeSourceValue(CS_Source source,
CS_Status status = 0;
buf.clear();
switch (cs::GetSourceKind(source, &status)) {
case cs::VideoSource::kUsb: {
case CS_SOURCE_USB: {
wpi::StringRef prefix{"usb:"};
buf.append(prefix.begin(), prefix.end());
auto path = cs::GetUsbCameraPath(source, &status);
buf.append(path.begin(), path.end());
break;
}
case cs::VideoSource::kHttp: {
case CS_SOURCE_HTTP: {
wpi::StringRef 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());
break;
}
case cs::VideoSource::kCv:
case CS_SOURCE_CV:
return "cv:";
default:
return "unknown:";
@@ -87,7 +94,7 @@ static std::string MakeStreamValue(const wpi::Twine& address, int port) {
std::shared_ptr<nt::NetworkTable> CameraServer::Impl::GetSourceTable(
CS_Source source) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
return m_tables.lookup(source);
}
@@ -132,7 +139,9 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
auto values = cs::GetHttpCameraUrls(source, &status);
for (auto& value : values) value = "mjpg:" + value;
#ifdef __FRC_ROBORIO__
// Look to see if we have a passthrough server for this source
// Only do this on the roboRIO
for (const auto& i : m_sinks) {
CS_Sink sink = i.second.GetHandle();
CS_Source sinkSource = cs::GetSinkSource(sink, &status);
@@ -144,13 +153,14 @@ std::vector<std::string> CameraServer::Impl::GetSourceStreamValues(
break;
}
}
#endif
// Set table value
return values;
}
void CameraServer::Impl::UpdateStreamValues() {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
// Over all the sinks...
for (const auto& i : m_sinks) {
CS_Status status = 0;
@@ -239,14 +249,14 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
CS_Status status = 0;
nt::NetworkTableEntry entry = table->GetEntry(name);
switch (event.propertyKind) {
case cs::VideoProperty::kBoolean:
case CS_PROP_BOOLEAN:
if (isNew)
entry.SetDefaultBoolean(event.value != 0);
else
entry.SetBoolean(event.value != 0);
break;
case cs::VideoProperty::kInteger:
case cs::VideoProperty::kEnum:
case CS_PROP_INTEGER:
case CS_PROP_ENUM:
if (isNew) {
entry.SetDefaultDouble(event.value);
table->GetEntry(infoName + "/min")
@@ -261,7 +271,7 @@ static void PutSourcePropertyValue(nt::NetworkTable* table,
entry.SetDouble(event.value);
}
break;
case cs::VideoProperty::kString:
case CS_PROP_STRING:
if (isNew)
entry.SetDefaultString(event.valueStr);
else
@@ -296,7 +306,7 @@ CameraServer::Impl::Impl()
// Create subtable for the camera
auto table = m_publishTable->GetSubTable(event.name);
{
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_tables.insert(std::make_pair(event.sourceHandle, table));
}
wpi::SmallString<64> buf;
@@ -561,7 +571,7 @@ cs::CvSink CameraServer::GetVideo() {
cs::VideoSource source;
{
auto csShared = GetCameraServerShared();
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
csShared->SetCameraServerError("no camera available");
return cs::CvSink{};
@@ -581,7 +591,7 @@ cs::CvSink CameraServer::GetVideo(const cs::VideoSource& camera) {
name += camera.GetName();
{
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sinks.find(name);
if (it != m_impl->m_sinks.end()) {
auto kind = it->second.GetKind();
@@ -606,7 +616,7 @@ cs::CvSink CameraServer::GetVideo(const wpi::Twine& name) {
wpi::StringRef nameStr = name.toStringRef(nameBuf);
cs::VideoSource source;
{
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sources.find(nameStr);
if (it == m_impl->m_sources.end()) {
auto csShared = GetCameraServerShared();
@@ -628,7 +638,7 @@ cs::CvSource CameraServer::PutVideo(const wpi::Twine& name, int width,
cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name) {
int port;
{
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
port = m_impl->m_nextPort++;
}
return AddServer(name, port);
@@ -641,12 +651,12 @@ cs::MjpegServer CameraServer::AddServer(const wpi::Twine& name, int port) {
}
void CameraServer::AddServer(const cs::VideoSink& server) {
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
m_impl->m_sinks.try_emplace(server.GetName(), server);
}
void CameraServer::RemoveServer(const wpi::Twine& name) {
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
wpi::SmallString<64> nameBuf;
m_impl->m_sinks.erase(name.toStringRef(nameBuf));
}
@@ -654,7 +664,7 @@ void CameraServer::RemoveServer(const wpi::Twine& name) {
cs::VideoSink CameraServer::GetServer() {
wpi::SmallString<64> name;
{
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
if (m_impl->m_primarySourceName.empty()) {
auto csShared = GetCameraServerShared();
csShared->SetCameraServerError("no camera available");
@@ -669,7 +679,7 @@ cs::VideoSink CameraServer::GetServer() {
cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
wpi::SmallString<64> nameBuf;
wpi::StringRef nameStr = name.toStringRef(nameBuf);
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
auto it = m_impl->m_sinks.find(nameStr);
if (it == m_impl->m_sinks.end()) {
auto csShared = GetCameraServerShared();
@@ -681,19 +691,19 @@ cs::VideoSink CameraServer::GetServer(const wpi::Twine& name) {
void CameraServer::AddCamera(const cs::VideoSource& camera) {
std::string name = camera.GetName();
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
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);
}
void CameraServer::RemoveCamera(const wpi::Twine& name) {
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
std::scoped_lock lock(m_impl->m_mutex);
wpi::SmallString<64> nameBuf;
m_impl->m_sources.erase(name.toStringRef(nameBuf));
}
void CameraServer::SetSize(int size) {
std::lock_guard<wpi::mutex> lock(m_impl->m_mutex);
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;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -24,20 +24,22 @@ class DefaultCameraServerShared : public frc::CameraServerShared {
};
} // namespace
namespace frc {
static std::unique_ptr<CameraServerShared> cameraServerShared = nullptr;
static std::unique_ptr<frc::CameraServerShared> cameraServerShared = nullptr;
static wpi::mutex setLock;
void SetCameraServerShared(std::unique_ptr<CameraServerShared> shared) {
std::unique_lock<wpi::mutex> lock(setLock);
cameraServerShared = std::move(shared);
}
namespace frc {
CameraServerShared* GetCameraServerShared() {
std::unique_lock<wpi::mutex> lock(setLock);
std::unique_lock lock(setLock);
if (!cameraServerShared) {
cameraServerShared = std::make_unique<DefaultCameraServerShared>();
}
return cameraServerShared.get();
}
} // namespace frc
extern "C" {
void CameraServer_SetCameraServerShared(frc::CameraServerShared* shared) {
std::unique_lock lock(setLock);
cameraServerShared.reset(shared);
}
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2014-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -16,6 +16,7 @@
#include <wpi/Twine.h>
#include "cscore.h"
#include "cscore_cv.h"
namespace frc {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -26,6 +26,10 @@ class CameraServerShared {
virtual std::pair<std::thread::id, bool> GetRobotMainThreadId() const = 0;
};
void SetCameraServerShared(std::unique_ptr<CameraServerShared> shared);
CameraServerShared* GetCameraServerShared();
} // namespace frc
extern "C" {
// Takes ownership
void CameraServer_SetCameraServerShared(frc::CameraServerShared* shared);
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -12,6 +12,7 @@
#include <memory>
#include "cscore.h"
#include "cscore_cv.h"
#include "vision/VisionPipeline.h"
namespace frc {

View File

@@ -0,0 +1,14 @@
include(CompileWarnings)
macro(wpilib_add_test name srcdir)
file(GLOB_RECURSE test_src ${srcdir}/*.cpp)
add_executable(${name}_test ${test_src})
wpilib_target_warnings(${name}_test)
if (BUILD_SHARED_LIBS)
target_compile_definitions(${name}_test PRIVATE -DGTEST_LINKED_AS_SHARED_LIBRARY)
endif()
if (MSVC)
target_compile_options(${name}_test PRIVATE /wd4251 /wd4101)
endif()
add_test(NAME ${name} COMMAND ${name}_test)
endmacro()

View File

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

View File

@@ -1,3 +1,4 @@
set(SCRIPTS_DIR "${CMAKE_CURRENT_LIST_DIR}/../scripts")
MACRO(GENERATE_RESOURCES inputDir outputDir prefix namespace outputFiles)
FILE(GLOB inputFiles ${inputDir}/*)
SET(${outputFiles})
@@ -16,9 +17,9 @@ MACRO(GENERATE_RESOURCES inputDir outputDir prefix namespace outputFiles)
"-Doutput=${output}"
"-Dprefix=${prefix}"
"-Dnamespace=${namespace}"
-P "${CMAKE_SOURCE_DIR}/cmake/scripts/GenResource.cmake"
-P "${SCRIPTS_DIR}/GenResource.cmake"
MAIN_DEPENDENCY ${input}
DEPENDS ${CMAKE_SOURCE_DIR}/cmake/scripts/GenResource.cmake
DEPENDS ${SCRIPTS_DIR}/GenResource.cmake
VERBATIM
)
ENDFOREACH()

View File

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

View File

@@ -0,0 +1,98 @@
set(GCC_COMPILER_VERSION "" CACHE STRING "GCC Compiler version")
set(GNU_MACHINE "arm-raspbian10-linux-gnueabi" CACHE STRING "GNU compiler triple")
if(COMMAND toolchain_save_config)
return() # prevent recursive call
endif()
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR arm)
else()
#message("CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/opencv/platforms/linux/gnu.toolchain.cmake")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm AND NOT ARM_IGNORE_FP)
set(FLOAT_ABI_SUFFIX "")
if(NOT SOFTFP)
set(FLOAT_ABI_SUFFIX "hf")
endif()
endif()
if(NOT "x${GCC_COMPILER_VERSION}" STREQUAL "x")
set(__GCC_VER_SUFFIX "-${GCC_COMPILER_VERSION}")
endif()
if(NOT DEFINED CMAKE_C_COMPILER)
find_program(CMAKE_C_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-gcc${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_C_COMPILER=${CMAKE_C_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER)
find_program(CMAKE_CXX_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-g++${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_LINKER)
find_program(CMAKE_LINKER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld)
else()
#message(WARNING "CMAKE_LINKER=${CMAKE_LINKER} is defined")
endif()
if(NOT DEFINED CMAKE_AR)
find_program(CMAKE_AR NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar)
else()
#message(WARNING "CMAKE_AR=${CMAKE_AR} is defined")
endif()
if(NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE)
set(ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX})
endif()
if(NOT DEFINED CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "")
set(CMAKE_C_FLAGS "" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,nocopyreloc")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(ARM_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
else()
#message(WARNING "CMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS}' is defined")
endif()
if(USE_NEON)
message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." )
set(ENABLE_NEON TRUE)
elseif(USE_VFPV3)
message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." )
set(ENABLE_VFPV3 TRUE)
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT})
if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR})
endif()
set(TOOLCHAIN_CONFIG_VARS ${TOOLCHAIN_CONFIG_VARS}
ARM_LINUX_SYSROOT
ENABLE_NEON
ENABLE_VFPV3
CUDA_TOOLKIT_ROOT_DIR
)
toolchain_save_config()

View File

@@ -0,0 +1,97 @@
if(COMMAND toolchain_save_config)
return() # prevent recursive call
endif()
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR arm)
else()
#message("CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")
endif()
include("${CMAKE_CURRENT_LIST_DIR}/gnu.toolchain.cmake")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm AND NOT ARM_IGNORE_FP)
set(FLOAT_ABI_SUFFIX "")
if(NOT SOFTFP)
set(FLOAT_ABI_SUFFIX "hf")
endif()
endif()
if(NOT "x${GCC_COMPILER_VERSION}" STREQUAL "x")
set(__GCC_VER_SUFFIX "-${GCC_COMPILER_VERSION}")
endif()
if(NOT DEFINED CMAKE_C_COMPILER)
find_program(CMAKE_C_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-gcc${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_C_COMPILER=${CMAKE_C_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_CXX_COMPILER)
find_program(CMAKE_CXX_COMPILER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-g++${__GCC_VER_SUFFIX})
else()
#message(WARNING "CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} is defined")
endif()
if(NOT DEFINED CMAKE_LINKER)
find_program(CMAKE_LINKER NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ld)
else()
#message(WARNING "CMAKE_LINKER=${CMAKE_LINKER} is defined")
endif()
if(NOT DEFINED CMAKE_AR)
find_program(CMAKE_AR NAMES ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar${__GCC_VER_SUFFIX} ${GNU_MACHINE}${FLOAT_ABI_SUFFIX}-ar)
else()
#message(WARNING "CMAKE_AR=${CMAKE_AR} is defined")
endif()
if(NOT DEFINED ARM_LINUX_SYSROOT AND DEFINED GNU_MACHINE)
set(ARM_LINUX_SYSROOT /usr/${GNU_MACHINE}${FLOAT_ABI_SUFFIX})
endif()
if(NOT DEFINED CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "" CACHE INTERNAL "")
set(CMAKE_C_FLAGS "" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdata-sections -Wa,--noexecstack -fsigned-char -Wno-psabi")
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(CMAKE_CXX_FLAGS "-mthumb ${CMAKE_CXX_FLAGS}")
set(CMAKE_C_FLAGS "-mthumb ${CMAKE_C_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,nocopyreloc")
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL arm)
set(ARM_LINKER_FLAGS "-Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
set(ARM_LINKER_FLAGS "-Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now")
endif()
set(CMAKE_SHARED_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${ARM_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
else()
#message(WARNING "CMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS}' is defined")
endif()
if(USE_NEON)
message(WARNING "You use obsolete variable USE_NEON to enable NEON instruction set. Use -DENABLE_NEON=ON instead." )
set(ENABLE_NEON TRUE)
elseif(USE_VFPV3)
message(WARNING "You use obsolete variable USE_VFPV3 to enable VFPV3 instruction set. Use -DENABLE_VFPV3=ON instead." )
set(ENABLE_VFPV3 TRUE)
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${ARM_LINUX_SYSROOT})
if(EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CUDA_TOOLKIT_ROOT_DIR})
endif()
set(TOOLCHAIN_CONFIG_VARS ${TOOLCHAIN_CONFIG_VARS}
ARM_LINUX_SYSROOT
ENABLE_NEON
ENABLE_VFPV3
CUDA_TOOLKIT_ROOT_DIR
)
toolchain_save_config()

View File

@@ -0,0 +1,134 @@
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")
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
macro(toolchain_save_config)
# nothing
endmacro()
else()
macro(toolchain_save_config)
set(__config "#message(\"Load TOOLCHAIN config...\")\n")
get_cmake_property(__variableNames VARIABLES)
set(__vars_list ${ARGN})
list(APPEND __vars_list
${TOOLCHAIN_CONFIG_VARS}
CMAKE_SYSTEM_NAME
CMAKE_SYSTEM_VERSION
CMAKE_SYSTEM_PROCESSOR
CMAKE_C_COMPILER
CMAKE_CXX_COMPILER
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
CMAKE_SHARED_LINKER_FLAGS
CMAKE_MODULE_LINKER_FLAGS
CMAKE_EXE_LINKER_FLAGS
CMAKE_SKIP_RPATH
CMAKE_FIND_ROOT_PATH
GCC_COMPILER_VERSION
)
foreach(__var ${__variableNames})
foreach(_v ${__vars_list})
if("x${__var}" STREQUAL "x${_v}")
if(${__var} MATCHES " ")
set(__config "${__config}set(${__var} \"${${__var}}\")\n")
else()
set(__config "${__config}set(${__var} ${${__var}})\n")
endif()
endif()
endforeach()
endforeach()
if(EXISTS "${TOOLCHAIN_CONFIG_FILE}")
file(READ "${TOOLCHAIN_CONFIG_FILE}" __config_old)
endif()
if("${__config_old}" STREQUAL "${__config}")
# nothing
else()
#message("Update TOOLCHAIN config: ${__config}")
file(WRITE "${TOOLCHAIN_CONFIG_FILE}" "${__config}")
endif()
unset(__config)
unset(__config_old)
unset(__vars_list)
unset(__variableNames)
endmacro()
endif() # IN_TRY_COMPILE
if(NOT CMAKE_FIND_ROOT_PATH_MODE_LIBRARY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_INCLUDE)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PACKAGE)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
endif()
if(NOT CMAKE_FIND_ROOT_PATH_MODE_PROGRAM)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
endif()
macro(__cmake_find_root_save_and_reset)
foreach(v
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
)
set(__save_${v} ${${v}})
set(${v} NEVER)
endforeach()
endmacro()
macro(__cmake_find_root_restore)
foreach(v
CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
)
set(${v} ${__save_${v}})
unset(__save_${v})
endforeach()
endmacro()
# macro to find programs on the host OS
macro(find_host_program)
__cmake_find_root_save_and_reset()
if(CMAKE_HOST_WIN32)
SET(WIN32 1)
SET(UNIX)
elseif(CMAKE_HOST_APPLE)
SET(APPLE 1)
SET(UNIX)
endif()
find_program(${ARGN})
SET(WIN32)
SET(APPLE)
SET(UNIX 1)
__cmake_find_root_restore()
endmacro()
# macro to find packages on the host OS
macro(find_host_package)
__cmake_find_root_save_and_reset()
if(CMAKE_HOST_WIN32)
SET(WIN32 1)
SET(UNIX)
elseif(CMAKE_HOST_APPLE)
SET(APPLE 1)
SET(UNIX)
endif()
find_package(${ARGN})
SET(WIN32)
SET(APPLE)
SET(UNIX 1)
__cmake_find_root_restore()
endmacro()
set(CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries.")

View File

@@ -1,6 +1,8 @@
project(cscore)
include(SubDirList)
include(CompileWarnings)
include(AddTest)
find_package( OpenCV REQUIRED )
@@ -21,14 +23,15 @@ if(NOT MSVC)
endif()
else()
target_sources(cscore PRIVATE ${cscore_windows_src})
target_compile_options(cscore PUBLIC -DNOMINMAX)
target_compile_options(cscore PRIVATE -D_CRT_SECURE_NO_WARNINGS)
target_compile_definitions(cscore PUBLIC -DNOMINMAX)
target_compile_definitions(cscore PRIVATE -D_CRT_SECURE_NO_WARNINGS)
endif()
target_include_directories(cscore PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/main/native/include>
$<INSTALL_INTERFACE:${include_dest}/cscore>)
target_include_directories(cscore PRIVATE src/main/native/cpp)
wpilib_target_warnings(cscore)
target_link_libraries(cscore PUBLIC wpiutil ${OpenCV_LIBS})
set_property(TARGET cscore PROPERTY FOLDER "libraries")
@@ -36,13 +39,14 @@ set_property(TARGET cscore PROPERTY FOLDER "libraries")
install(TARGETS cscore EXPORT cscore DESTINATION "${main_lib_dest}")
install(DIRECTORY src/main/native/include/ DESTINATION "${include_dest}/cscore")
if (MSVC)
if (MSVC OR FLAT_INSTALL_WPILIB)
set (cscore_config_dir ${wpilib_dest})
else()
set (cscore_config_dir share/cscore)
endif()
install(FILES cscore-config.cmake DESTINATION ${cscore_config_dir})
configure_file(cscore-config.cmake.in ${CMAKE_BINARY_DIR}/cscore-config.cmake )
install(FILES ${CMAKE_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")
@@ -50,7 +54,9 @@ foreach(example ${cscore_examples})
file(GLOB cscore_example_src examples/${example}/*.cpp)
if(cscore_example_src)
add_executable(cscore_${example} ${cscore_example_src})
wpilib_target_warnings(cscore_${example})
target_link_libraries(cscore_${example} cscore)
set_property(TARGET cscore_${example} PROPERTY FOLDER "examples")
endif()
endforeach()
@@ -63,7 +69,9 @@ if (NOT WITHOUT_JAVA)
#find java files, copy them locally
set(OPENCV_JAVA_INSTALL_DIR ${OpenCV_INSTALL_PATH}/share/OpenCV/java/)
if("${OPENCV_JAVA_INSTALL_DIR}" STREQUAL "")
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_JNI_FILE NAMES libopencv_java${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}.so
@@ -101,6 +109,7 @@ if (NOT WITHOUT_JAVA)
set_property(TARGET cscore_jar PROPERTY FOLDER "java")
add_library(cscorejni ${cscore_jni_src})
wpilib_target_warnings(cscorejni)
target_link_libraries(cscorejni PUBLIC cscore wpiutil ${OpenCV_LIBS})
set_property(TARGET cscorejni PROPERTY FOLDER "libraries")
@@ -120,3 +129,8 @@ if (NOT WITHOUT_JAVA)
install(TARGETS cscorejni EXPORT cscorejni DESTINATION "${main_lib_dest}")
endif()
if (WITH_TESTS)
wpilib_add_test(cscore src/test/native/cpp)
target_link_libraries(cscore_test cscore gmock)
endif()

View File

@@ -5,9 +5,13 @@ ext {
devMain = 'edu.wpi.cscore.DevMain'
}
if (OperatingSystem.current().isMacOsX()) {
apply plugin: 'objective-cpp'
}
// Removed because having the objective-cpp plugin added breaks
// embedded tools and its toolchain check. It causes an obj-cpp
// source set to be added to all binaries, even cross binaries
// with no support.
// if (OperatingSystem.current().isMacOsX()) {
// apply plugin: 'objective-cpp'
// }
apply from: "${rootDir}/shared/jni/setupBuild.gradle"
@@ -15,23 +19,24 @@ ext {
sharedCvConfigs = [cscore : [],
cscoreBase: [],
cscoreDev : [],
cscoreTest: []]
cscoreTest: [],
cscoreJNIShared: []]
staticCvConfigs = [cscoreJNI: []]
useJava = true
useCpp = true
splitSetup = {
if (it.targetPlatform.operatingSystem.name == 'osx') {
if (it.targetPlatform.operatingSystem.isMacOsX()) {
it.sources {
macObjCpp(ObjectiveCppSourceSet) {
source {
srcDirs = ['src/main/native/objcpp']
include '**/*.mm'
}
exportedHeaders {
srcDirs 'src/main/native/include'
include '**/*.h'
}
}
// macObjCpp(ObjectiveCppSourceSet) {
// source {
// srcDirs = ['src/main/native/objcpp']
// include '**/*.mm'
// }
// exportedHeaders {
// srcDirs 'src/main/native/include'
// include '**/*.h'
// }
// }
cscoreMacCpp(CppSourceSet) {
source {
srcDirs 'src/main/native/osx'
@@ -43,7 +48,7 @@ ext {
}
}
}
} else if (it.targetPlatform.operatingSystem.name == 'linux') {
} else if (it.targetPlatform.operatingSystem.isLinux()) {
it.sources {
cscoreLinuxCpp(CppSourceSet) {
source {
@@ -56,7 +61,7 @@ ext {
}
}
}
} else if (it.targetPlatform.operatingSystem.name == 'windows') {
} else if (it.targetPlatform.operatingSystem.isWindows()) {
it.sources {
cscoreWindowsCpp(CppSourceSet) {
source {
@@ -88,43 +93,28 @@ examplesTree.list(new FilenameFilter() {
apply from: "${rootDir}/shared/opencv.gradle"
model {
// Exports config is a utility to enable exporting all symbols in a C++ library on windows to a DLL.
// This removes the need for DllExport on a library. However, the gradle C++ builder has a bug
// where some extra symbols are added that cannot be resolved at link time. This configuration
// lets you specify specific symbols to exlude from exporting.
exportsConfigs {
cscore(ExportsConfig) {
x86ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVbad_cast',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '==']
x64ExcludeSymbols = ['_CT??_R0?AV_System_error', '_CT??_R0?AVexception', '_CT??_R0?AVfailure',
'_CT??_R0?AVbad_cast',
'_CT??_R0?AVruntime_error', '_CT??_R0?AVsystem_error', '_CTA5?AVfailure',
'_TI5?AVfailure', '==']
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']
}
cscoreJNI {
x86SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
cscoreJNI(ExportsConfig) {
x86SymbolFilter = { symbols ->
def retList = []
symbols.each { symbol ->
if (symbol.startsWith('CS_')) {
retList << symbol
}
}
return retList
}
x64SymbolFilter = { symbols ->
def retList = []
symbols.each { symbol ->
if (symbol.startsWith('CS_')) {
retList << symbol
}
}
return retList
}
x64SymbolFilter = { symbols ->
symbols.removeIf({ !it.startsWith('CS_') })
}
}
}
model {
components {
examplesMap.each { key, value ->
"${key}"(NativeExecutableSpec) {

View File

@@ -1,6 +0,0 @@
include(CMakeFindDependencyMacro)
find_dependency(wpiutil)
find_dependency(OpenCV)
get_filename_component(SELF_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
include(${SELF_DIR}/cscore.cmake)

View File

@@ -0,0 +1,6 @@
include(CMakeFindDependencyMacro)
@FILENAME_DEP_REPLACE@
@WPIUTIL_DEP_REPLACE@
find_dependency(OpenCV)
include(${SELF_DIR}/cscore.cmake)

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,6 +11,7 @@
#include <opencv2/core/core.hpp>
#include "cscore.h"
#include "cscore_cv.h"
int main() {
cs::HttpCamera camera{"httpcam", "http://localhost:8081/?action=stream"};

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,6 +11,7 @@
#include <opencv2/core/core.hpp>
#include "cscore.h"
#include "cscore_cv.h"
int main() {
cs::UsbCamera camera{"usbcam", 0};

View File

@@ -0,0 +1,96 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
import java.nio.ByteBuffer;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import edu.wpi.cscore.VideoMode.PixelFormat;
import edu.wpi.cscore.raw.RawFrame;
public class RawCVMatSink extends ImageSink {
RawFrame frame = new RawFrame();
Mat tmpMat;
ByteBuffer origByteBuffer;
int width;
int height;
int pixelFormat;
int bgrValue = PixelFormat.kBGR.getValue();
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;
}
return type;
}
/**
* Create a sink for accepting OpenCV images.
* WaitForFrame() must be called on the created sink to get each new
* image.
*
* @param name Source name (arbitrary unique identifier)
*/
public RawCVMatSink(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 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message)
*/
public long grabFrame(Mat image) {
return grabFrame(image, 0.225);
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after timeout seconds.
* The provided image will have three 3-bit channels stored in BGR order.
*
* @return Frame time, or 0 on error (call GetError() to obtain the error
* message); the frame time is in 1 us increments.
*/
public long grabFrame(Mat image, double timeout) {
frame.setWidth(0);
frame.setHeight(0);
frame.setPixelFormat(bgrValue);
long rv = CameraServerJNI.grabSinkFrameTimeout(m_handle, frame, timeout);
if (rv <= 0) {
return rv;
}
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.copyTo(image);
return rv;
}
}

View File

@@ -0,0 +1,59 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
import org.opencv.core.Mat;
import edu.wpi.cscore.VideoMode.PixelFormat;
public class RawCVMatSource extends ImageSource {
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @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));
}
/**
* 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 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.
*
* @param image OpenCV image
*/
public void putFrame(Mat image) {
int channels = image.channels();
if (channels != 1 && channels != 3) {
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);
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2017-2018 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -0,0 +1,72 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.opencv.core.Core;
import edu.wpi.first.wpiutil.RuntimeLoader;
public class CameraServerCvJNI {
static boolean libraryLoaded = false;
static RuntimeLoader<Core> loader = null;
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static boolean getExtractOnStaticLoad() {
return extractOnStaticLoad.get();
}
public static void setExtractOnStaticLoad(boolean load) {
extractOnStaticLoad.set(load);
}
}
static {
String opencvName = Core.NATIVE_LIBRARY_NAME;
if (Helper.getExtractOnStaticLoad()) {
try {
CameraServerJNI.forceLoad();
loader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibraryHashed();
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
libraryLoaded = true;
}
}
/**
* Force load the library.
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
CameraServerJNI.forceLoad();
loader = new RuntimeLoader<>(Core.NATIVE_LIBRARY_NAME, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
loader.loadLibrary();
libraryLoaded = true;
}
public static native int createCvSource(String name, int pixelFormat, int width, int height, int fps);
public static native void putSourceFrame(int source, long imageNativeObj);
public static native int createCvSink(String name);
//public static native int createCvSinkCallback(String name,
// void (*processFrame)(long time));
public static native long grabSinkFrame(int sink, long imageNativeObj);
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, double timeout);
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -8,21 +8,32 @@
package edu.wpi.cscore;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import org.opencv.core.Core;
import edu.wpi.cscore.raw.RawFrame;
import edu.wpi.first.wpiutil.RuntimeLoader;
public class CameraServerJNI {
static boolean libraryLoaded = false;
static boolean cvLibraryLoaded = false;
static RuntimeLoader<CameraServerJNI> loader = null;
static RuntimeLoader<Core> cvLoader = null;
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static boolean getExtractOnStaticLoad() {
return extractOnStaticLoad.get();
}
public static void setExtractOnStaticLoad(boolean load) {
extractOnStaticLoad.set(load);
}
}
static {
if (!libraryLoaded) {
if (Helper.getExtractOnStaticLoad()) {
try {
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
@@ -32,21 +43,19 @@ public class CameraServerJNI {
}
libraryLoaded = true;
}
String opencvName = Core.NATIVE_LIBRARY_NAME;
if (!cvLibraryLoaded) {
try {
cvLoader = new RuntimeLoader<>(opencvName, RuntimeLoader.getDefaultExtractionRoot(), Core.class);
cvLoader.loadLibraryHashed();
} catch (IOException ex) {
ex.printStackTrace();
System.exit(1);
}
cvLibraryLoaded = true;
}
}
public static void forceLoad() {}
/**
* Force load the library.
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
loader = new RuntimeLoader<>("cscorejni", RuntimeLoader.getDefaultExtractionRoot(), CameraServerJNI.class);
loader.loadLibrary();
libraryLoaded = true;
}
//
// Property Functions
@@ -70,7 +79,7 @@ public class CameraServerJNI {
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 createCvSource(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
@@ -122,9 +131,13 @@ public class CameraServerJNI {
public static native String[] getHttpCameraUrls(int source);
//
// OpenCV Source Functions
// Image Source Functions
//
public static native void putSourceFrame(int source, long imageNativeObj);
public static native void putRawSourceFrameBB(int source, ByteBuffer data, int width, int height, int pixelFormat, int totalData);
public static native void putRawSourceFrame(int source, long data, int width, int height, int pixelFormat, int totalData);
public static void putRawSourceFrame(int source, RawFrame raw) {
putRawSourceFrame(source, raw.getDataPtr(), raw.getWidth(), raw.getHeight(), raw.getPixelFormat(), raw.getTotalData());
}
public static native void notifySourceError(int source, String msg);
public static native void setSourceConnected(int source, boolean connected);
public static native void setSourceDescription(int source, String description);
@@ -135,9 +148,8 @@ public class CameraServerJNI {
// Sink Creation Functions
//
public static native int createMjpegServer(String name, String listenAddress, int port);
public static native int createCvSink(String name);
//public static native int createCvSinkCallback(String name,
// void (*processFrame)(long time));
public static native int createRawSink(String name);
//
// Sink Functions
@@ -162,11 +174,19 @@ public class CameraServerJNI {
public static native int getMjpegServerPort(int sink);
//
// OpenCV Sink Functions
// Image Sink Functions
//
public static native void setSinkDescription(int sink, String description);
public static native long grabSinkFrame(int sink, long imageNativeObj);
public static native long grabSinkFrameTimeout(int sink, long imageNativeObj, 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());
}
public static long grabSinkFrameTimeout(int sink, RawFrame rawFrame, double timeout) {
return grabRawSinkFrameTimeoutImpl(sink, rawFrame, rawFrame.getFramePtr(), rawFrame.getDataByteBuffer(), rawFrame.getWidth(), rawFrame.getHeight(), rawFrame.getPixelFormat(), timeout);
}
public static native String getSinkError(int sink);
public static native void setSinkEnabled(int sink, boolean enabled);
@@ -228,4 +248,8 @@ public class CameraServerJNI {
public static native String getHostname();
public static native String[] getNetworkInterfaces();
public static native long allocateRawFrame();
public static native void freeRawFrame(long frame);
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,8 +11,11 @@ import org.opencv.core.Mat;
/**
* A sink for user code to accept video frames as OpenCV images.
* These sinks require the WPILib OpenCV builds.
* For an alternate OpenCV, see the documentation how to build your own
* with RawSink.
*/
public class CvSink extends VideoSink {
public class CvSink extends ImageSink {
/**
* Create a sink for accepting OpenCV images.
* WaitForFrame() must be called on the created sink to get each new
@@ -21,7 +24,7 @@ public class CvSink extends VideoSink {
* @param name Source name (arbitrary unique identifier)
*/
public CvSink(String name) {
super(CameraServerJNI.createCvSink(name));
super(CameraServerCvJNI.createCvSink(name));
}
/// Create a sink for accepting OpenCV images in a separate thread.
@@ -37,15 +40,6 @@ public class CvSink extends VideoSink {
// super(CameraServerJNI.createCvSinkCallback(name, processFrame));
//}
/**
* Set sink description.
*
* @param description Description
*/
public void setDescription(String description) {
CameraServerJNI.setSinkDescription(m_handle, description);
}
/**
* Wait for the next frame and get the image.
* Times out (returning 0) after 0.225 seconds.
@@ -67,7 +61,7 @@ public class CvSink extends VideoSink {
* message); the frame time is in 1 us increments.
*/
public long grabFrame(Mat image, double timeout) {
return CameraServerJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
return CameraServerCvJNI.grabSinkFrameTimeout(m_handle, image.nativeObj, timeout);
}
/**
@@ -78,24 +72,6 @@ public class CvSink extends VideoSink {
* message); the frame time is in 1 us increments.
*/
public long grabFrameNoTimeout(Mat image) {
return CameraServerJNI.grabSinkFrame(m_handle, image.nativeObj);
}
/**
* 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);
return CameraServerCvJNI.grabSinkFrame(m_handle, image.nativeObj);
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,8 +11,11 @@ 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 VideoSource {
public class CvSource extends ImageSource {
/**
* Create an OpenCV source.
*
@@ -20,7 +23,7 @@ public class CvSource extends VideoSource {
* @param mode Video mode being generated
*/
public CvSource(String name, VideoMode mode) {
super(CameraServerJNI.createCvSource(name,
super(CameraServerCvJNI.createCvSource(name,
mode.pixelFormat.getValue(),
mode.width,
mode.height,
@@ -37,7 +40,7 @@ public class CvSource extends VideoSource {
* @param fps fps
*/
public CvSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
super(CameraServerCvJNI.createCvSource(name, pixelFormat.getValue(), width, height, fps));
}
/**
@@ -50,154 +53,7 @@ public class CvSource extends VideoSource {
* @param image OpenCV image
*/
public void putFrame(Mat image) {
CameraServerJNI.putSourceFrame(m_handle, image.nativeObj);
CameraServerCvJNI.putSourceFrame(m_handle, image.nativeObj);
}
/**
* Signal sinks that an error has occurred. This should be called instead
* of NotifyFrame when an error occurs.
*/
public void notifyError(String msg) {
CameraServerJNI.notifySourceError(m_handle, msg);
}
/**
* Set source connection status. Defaults to true.
*
* @param connected True for connected, false for disconnected
*/
public void setConnected(boolean connected) {
CameraServerJNI.setSourceConnected(m_handle, connected);
}
/**
* Set source description.
*
* @param description Description
*/
public void setDescription(String description) {
CameraServerJNI.setSourceDescription(m_handle, description);
}
/**
* Create a property.
*
* @param name Property name
* @param kind Property kind
* @param minimum Minimum value
* @param maximum Maximum value
* @param step Step value
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createProperty(String name,
VideoProperty.Kind kind,
int minimum,
int maximum,
int step,
int defaultValue,
int value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
kind.getValue(),
minimum,
maximum,
step,
defaultValue,
value));
}
/**
* Create an integer property.
*
* @param name Property name
* @param minimum Minimum value
* @param maximum Maximum value
* @param step Step value
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createIntegerProperty(String name,
int minimum,
int maximum,
int step,
int defaultValue,
int value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
VideoProperty.Kind.kInteger.getValue(),
minimum,
maximum,
step,
defaultValue,
value));
}
/**
* Create a boolean property.
*
* @param name Property name
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createBooleanProperty(String name, boolean defaultValue, boolean value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
VideoProperty.Kind.kBoolean.getValue(),
0,
1,
1,
defaultValue ? 1 : 0,
value ? 1 : 0));
}
/**
* Create a string property.
*
* @param name Property name
* @param value Current value
* @return Property
*/
public VideoProperty createStringProperty(String name, String value) {
VideoProperty prop = new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
VideoProperty.Kind.kString.getValue(),
0,
0,
0,
0,
0));
prop.setString(value);
return prop;
}
/**
* Configure enum property choices.
*
* @param property Property
* @param choices Choices
*/
public void setEnumPropertyChoices(VideoProperty property, String[] choices) {
CameraServerJNI.setSourceEnumPropertyChoices(m_handle, property.m_handle, choices);
}
/**
* Configure enum property choices.
*
* @param property Property
* @param choices Choices
* @deprecated Use {@code setEnumPropertyChoices} instead.
*/
@Deprecated
@SuppressWarnings("MethodName")
public void SetEnumPropertyChoices(VideoProperty property, String[] choices) {
setEnumPropertyChoices(property, choices);
}
}

View File

@@ -0,0 +1,41 @@
/*----------------------------------------------------------------------------*/
/* 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

@@ -0,0 +1,162 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.cscore;
public abstract class ImageSource extends VideoSource {
protected ImageSource(int handle) {
super(handle);
}
/**
* Signal sinks that an error has occurred. This should be called instead
* of NotifyFrame when an error occurs.
*/
public void notifyError(String msg) {
CameraServerJNI.notifySourceError(m_handle, msg);
}
/**
* Set source connection status. Defaults to true.
*
* @param connected True for connected, false for disconnected
*/
public void setConnected(boolean connected) {
CameraServerJNI.setSourceConnected(m_handle, connected);
}
/**
* Set source description.
*
* @param description Description
*/
public void setDescription(String description) {
CameraServerJNI.setSourceDescription(m_handle, description);
}
/**
* Create a property.
*
* @param name Property name
* @param kind Property kind
* @param minimum Minimum value
* @param maximum Maximum value
* @param step Step value
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createProperty(String name,
VideoProperty.Kind kind,
int minimum,
int maximum,
int step,
int defaultValue,
int value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
kind.getValue(),
minimum,
maximum,
step,
defaultValue,
value));
}
/**
* Create an integer property.
*
* @param name Property name
* @param minimum Minimum value
* @param maximum Maximum value
* @param step Step value
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createIntegerProperty(String name,
int minimum,
int maximum,
int step,
int defaultValue,
int value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
VideoProperty.Kind.kInteger.getValue(),
minimum,
maximum,
step,
defaultValue,
value));
}
/**
* Create a boolean property.
*
* @param name Property name
* @param defaultValue Default value
* @param value Current value
* @return Property
*/
public VideoProperty createBooleanProperty(String name, boolean defaultValue, boolean value) {
return new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
VideoProperty.Kind.kBoolean.getValue(),
0,
1,
1,
defaultValue ? 1 : 0,
value ? 1 : 0));
}
/**
* Create a string property.
*
* @param name Property name
* @param value Current value
* @return Property
*/
public VideoProperty createStringProperty(String name, String value) {
VideoProperty prop = new VideoProperty(
CameraServerJNI.createSourceProperty(m_handle,
name,
VideoProperty.Kind.kString.getValue(),
0,
0,
0,
0,
0));
prop.setString(value);
return prop;
}
/**
* Configure enum property choices.
*
* @param property Property
* @param choices Choices
*/
public void setEnumPropertyChoices(VideoProperty property, String[] choices) {
CameraServerJNI.setSourceEnumPropertyChoices(m_handle, property.m_handle, choices);
}
/**
* Configure enum property choices.
*
* @param property Property
* @param choices Choices
* @deprecated Use {@code setEnumPropertyChoices} instead.
*/
@Deprecated
@SuppressWarnings("MethodName")
public void SetEnumPropertyChoices(VideoProperty property, String[] choices) {
setEnumPropertyChoices(property, choices);
}
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -18,13 +18,18 @@ public class UsbCameraInfo {
* @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) {
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;
}
/**
@@ -50,4 +55,16 @@ public class UsbCameraInfo {
*/
@SuppressWarnings("MemberName")
public String[] otherPaths;
/**
* USB vendor id.
*/
@SuppressWarnings("MemberName")
public int vendorId;
/**
* USB product id.
*/
@SuppressWarnings("MemberName")
public int productId;
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -27,11 +27,6 @@ public class VideoListener implements AutoCloseable {
m_handle = CameraServerJNI.addListener(listener, eventMask, immediateNotify);
}
@Deprecated
public void free() {
close();
}
@Override
public synchronized void close() {
if (m_handle != 0) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -14,7 +14,7 @@ package edu.wpi.cscore;
*/
public class VideoSink implements AutoCloseable {
public enum Kind {
kUnknown(0), kMjpeg(2), kCv(4);
kUnknown(0), kMjpeg(2), kCv(4), kRaw(8);
@SuppressWarnings("MemberName")
private final int value;
@@ -46,11 +46,6 @@ public class VideoSink implements AutoCloseable {
m_handle = handle;
}
@Deprecated
public void free() {
close();
}
@Override
public synchronized void close() {
if (m_handle != 0) {
@@ -186,7 +181,7 @@ public class VideoSink implements AutoCloseable {
* @return Connected source; nullptr if no source connected.
*/
public VideoSource getSource() {
// While VideoSource.free() will call releaseSource(), getSinkSource()
// While VideoSource.close() will call releaseSource(), getSinkSource()
// increments the internal reference count so this is okay to do.
return new VideoSource(CameraServerJNI.getSinkSource(m_handle));
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -14,7 +14,7 @@ package edu.wpi.cscore;
*/
public class VideoSource implements AutoCloseable {
public enum Kind {
kUnknown(0), kUsb(1), kHttp(2), kCv(4);
kUnknown(0), kUsb(1), kHttp(2), kCv(4), kRaw(8);
@SuppressWarnings("MemberName")
private final int value;
@@ -81,11 +81,6 @@ public class VideoSource implements AutoCloseable {
m_handle = handle;
}
@Deprecated
public void free() {
close();
}
@Override
public synchronized void close() {
if (m_handle != 0) {

View File

@@ -0,0 +1,130 @@
/*----------------------------------------------------------------------------*/
/* 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 java.nio.ByteBuffer;
import edu.wpi.cscore.CameraServerJNI;
/**
* Class for storing raw frame data between image read call.
*
* <p>Data is reused for each frame read, rather then reallocating every frame.
*/
public class RawFrame implements AutoCloseable {
private final long m_framePtr;
private ByteBuffer m_dataByteBuffer;
private long m_dataPtr;
private int m_totalData;
private int m_width;
private int m_height;
private int m_pixelFormat;
/**
* Construct a new RawFrame.
*/
public RawFrame() {
m_framePtr = CameraServerJNI.allocateRawFrame();
}
/**
* Close the RawFrame, releasing native resources.
* Any images currently using the data will be invalidated.
*/
@Override
public void close() {
CameraServerJNI.freeRawFrame(m_framePtr);
}
/**
* Called from JNI to set data in class.
*/
public void setData(ByteBuffer dataByteBuffer, long dataPtr, int totalData,
int width, int height, int pixelFormat) {
m_dataByteBuffer = dataByteBuffer;
m_dataPtr = dataPtr;
m_totalData = totalData;
m_width = width;
m_height = height;
m_pixelFormat = pixelFormat;
}
/**
* Get the pointer to native representation of this frame.
*/
public long getFramePtr() {
return m_framePtr;
}
/**
* Get a ByteBuffer pointing to the frame data.
* This ByteBuffer is backed by the frame directly. Its lifetime is controlled by
* the frame. If a new frame gets read, it will overwrite the current one.
*/
public ByteBuffer getDataByteBuffer() {
return m_dataByteBuffer;
}
/**
* Get a long (is a char* in native code) pointing to the frame data.
* This pointer is backed by the frame directly. Its lifetime is controlled by
* the frame. If a new frame gets read, it will overwrite the current one.
*/
public long getDataPtr() {
return m_dataPtr;
}
/**
* Get the total length of the data stored in the frame.
*/
public int getTotalData() {
return m_totalData;
}
/**
* Get the width of the frame.
*/
public int getWidth() {
return m_width;
}
/**
* Set the width of the frame.
*/
public void setWidth(int width) {
this.m_width = width;
}
/**
* Get the height of the frame.
*/
public int getHeight() {
return m_height;
}
/**
* Set the height of the frame.
*/
public void setHeight(int height) {
this.m_height = height;
}
/**
* Get the PixelFormat of the frame.
*/
public int getPixelFormat() {
return m_pixelFormat;
}
/**
* Set the PixelFormat of the frame.
*/
public void setPixelFormat(int pixelFormat) {
this.m_pixelFormat = pixelFormat;
}
}

View File

@@ -0,0 +1,68 @@
/*----------------------------------------------------------------------------*/
/* 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

@@ -0,0 +1,85 @@
/*----------------------------------------------------------------------------*/
/* 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.ImageSource;
import edu.wpi.cscore.VideoMode;
/**
* A source for user code to provide video frames as raw bytes.
*
* <p>This is a complex API, most cases should use CvSource.
*/
public class RawSource extends ImageSource {
/**
* Create a raw frame source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
public RawSource(String name, VideoMode mode) {
super(CameraServerJNI.createRawSource(name,
mode.pixelFormat.getValue(),
mode.width, mode.height,
mode.fps));
}
/**
* Create a raw frame source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
public RawSource(String name, VideoMode.PixelFormat pixelFormat, int width, int height, int fps) {
super(CameraServerJNI.createRawSource(name,
pixelFormat.getValue(),
width, height,
fps));
}
/**
* Put a raw image and notify sinks.
*
* @param image raw frame image
*/
protected void putFrame(RawFrame image) {
CameraServerJNI.putRawSourceFrame(m_handle, image);
}
/**
* Put a raw image and notify sinks.
*
* @param data raw frame data pointer
* @param width frame width
* @param height frame height
* @param pixelFormat pixel format
* @param totalData length of data in total
*/
protected void putFrame(long data, int width, int height, int pixelFormat, int totalData) {
CameraServerJNI.putRawSourceFrame(m_handle, data, width, height, pixelFormat, totalData);
}
/**
* Put a raw image and notify sinks.
*
* @param data raw frame data pointer
* @param width frame width
* @param height frame height
* @param pixelFormat pixel format
* @param totalData length of data in total
*/
protected void putFrame(long data, int width, int height, VideoMode.PixelFormat pixelFormat,
int totalData) {
CameraServerJNI.putRawSourceFrame(m_handle, data, width, height, pixelFormat.getValue(),
totalData);
}
}

View File

@@ -0,0 +1,109 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#include "ConfigurableSourceImpl.h"
#include <wpi/timestamp.h>
#include "Handle.h"
#include "Instance.h"
#include "Log.h"
#include "Notifier.h"
using namespace cs;
ConfigurableSourceImpl::ConfigurableSourceImpl(const wpi::Twine& name,
wpi::Logger& logger,
Notifier& notifier,
Telemetry& telemetry,
const VideoMode& mode)
: SourceImpl{name, logger, notifier, telemetry} {
m_mode = mode;
m_videoModes.push_back(m_mode);
}
ConfigurableSourceImpl::~ConfigurableSourceImpl() {}
void ConfigurableSourceImpl::Start() {
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
m_notifier.NotifySource(*this, CS_SOURCE_VIDEOMODES_UPDATED);
m_notifier.NotifySourceVideoMode(*this, m_mode);
}
bool ConfigurableSourceImpl::SetVideoMode(const VideoMode& mode,
CS_Status* status) {
{
std::scoped_lock lock(m_mutex);
m_mode = mode;
m_videoModes[0] = mode;
}
m_notifier.NotifySourceVideoMode(*this, mode);
return true;
}
void ConfigurableSourceImpl::NumSinksChanged() {
// ignore
}
void ConfigurableSourceImpl::NumSinksEnabledChanged() {
// ignore
}
void ConfigurableSourceImpl::NotifyError(const wpi::Twine& msg) {
PutError(msg, wpi::Now());
}
int ConfigurableSourceImpl::CreateProperty(const wpi::Twine& name,
CS_PropertyKind kind, int minimum,
int maximum, int step,
int defaultValue, int value) {
std::scoped_lock lock(m_mutex);
int ndx = CreateOrUpdateProperty(name,
[=] {
return std::make_unique<PropertyImpl>(
name, kind, minimum, maximum, step,
defaultValue, value);
},
[&](PropertyImpl& prop) {
// update all but value
prop.propKind = kind;
prop.minimum = minimum;
prop.maximum = maximum;
prop.step = step;
prop.defaultValue = defaultValue;
value = prop.value;
});
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name, ndx,
kind, value, wpi::Twine{});
return ndx;
}
int ConfigurableSourceImpl::CreateProperty(
const wpi::Twine& name, CS_PropertyKind kind, int minimum, int maximum,
int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange) {
// TODO
return 0;
}
void ConfigurableSourceImpl::SetEnumPropertyChoices(
int property, wpi::ArrayRef<std::string> choices, CS_Status* status) {
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
return;
}
if (prop->propKind != CS_PROP_ENUM) {
*status = CS_WRONG_PROPERTY_TYPE;
return;
}
prop->enumChoices = choices;
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
prop->name, property, CS_PROP_ENUM,
prop->value, wpi::Twine{});
}

View File

@@ -0,0 +1,56 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#ifndef CSCORE_CONFIGURABLESOURCEIMPL_H_
#define CSCORE_CONFIGURABLESOURCEIMPL_H_
#include <atomic>
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include <wpi/ArrayRef.h>
#include <wpi/Twine.h>
#include "SourceImpl.h"
namespace cs {
class ConfigurableSourceImpl : public SourceImpl {
protected:
ConfigurableSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const VideoMode& mode);
public:
~ConfigurableSourceImpl() override;
void Start() override;
bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
void NumSinksChanged() override;
void NumSinksEnabledChanged() override;
// OpenCV-specific functions
void NotifyError(const wpi::Twine& msg);
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
int maximum, int step, int defaultValue, int value);
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
int maximum, int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange);
void SetEnumPropertyChoices(int property, wpi::ArrayRef<std::string> choices,
CS_Status* status);
private:
std::atomic_bool m_connected{true};
};
} // namespace cs
#endif // CSCORE_CONFIGURABLESOURCEIMPL_H_

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -138,10 +138,12 @@ CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
inst.telemetry, processFrame));
}
static constexpr unsigned SinkMask = CS_SINK_CV | CS_SINK_RAW;
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || data->kind != CS_SINK_CV) {
if (!data || (data->kind & SinkMask) == 0) {
*status = CS_INVALID_HANDLE;
return;
}
@@ -169,7 +171,7 @@ uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
std::string GetSinkError(CS_Sink sink, CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || data->kind != CS_SINK_CV) {
if (!data || (data->kind & SinkMask) == 0) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
@@ -179,7 +181,7 @@ std::string GetSinkError(CS_Sink sink, CS_Status* status) {
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || data->kind != CS_SINK_CV) {
if (!data || (data->kind & SinkMask) == 0) {
*status = CS_INVALID_HANDLE;
return wpi::StringRef{};
}
@@ -188,7 +190,7 @@ wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || data->kind != CS_SINK_CV) {
if (!data || (data->kind & SinkMask) == 0) {
*status = CS_INVALID_HANDLE;
return;
}
@@ -215,6 +217,7 @@ void CS_SetSinkDescription(CS_Sink sink, const char* description,
return cs::SetSinkDescription(sink, description, status);
}
#if CV_VERSION_MAJOR < 4
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image,
CS_Status* status) {
auto mat = cv::cvarrToMat(image);
@@ -226,6 +229,7 @@ uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
auto mat = cv::cvarrToMat(image);
return cs::GrabSinkFrameTimeout(sink, mat, timeout, status);
}
#endif // CV_VERSION_MAJOR < 4
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status) {
return cs::GrabSinkFrame(sink, *image, status);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -25,37 +25,10 @@ using namespace cs;
CvSourceImpl::CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const VideoMode& mode)
: SourceImpl{name, logger, notifier, telemetry} {
m_mode = mode;
m_videoModes.push_back(m_mode);
}
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
CvSourceImpl::~CvSourceImpl() {}
void CvSourceImpl::Start() {
m_notifier.NotifySource(*this, CS_SOURCE_CONNECTED);
m_notifier.NotifySource(*this, CS_SOURCE_VIDEOMODES_UPDATED);
m_notifier.NotifySourceVideoMode(*this, m_mode);
}
bool CvSourceImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) {
{
std::lock_guard<wpi::mutex> lock(m_mutex);
m_mode = mode;
m_videoModes[0] = mode;
}
m_notifier.NotifySourceVideoMode(*this, mode);
return true;
}
void CvSourceImpl::NumSinksChanged() {
// ignore
}
void CvSourceImpl::NumSinksEnabledChanged() {
// ignore
}
void CvSourceImpl::PutFrame(cv::Mat& image) {
// We only support 8-bit images; convert if necessary.
cv::Mat finalImage;
@@ -89,61 +62,6 @@ void CvSourceImpl::PutFrame(cv::Mat& image) {
SourceImpl::PutFrame(std::move(dest), wpi::Now());
}
void CvSourceImpl::NotifyError(const wpi::Twine& msg) {
PutError(msg, wpi::Now());
}
int CvSourceImpl::CreateProperty(const wpi::Twine& name, CS_PropertyKind kind,
int minimum, int maximum, int step,
int defaultValue, int value) {
std::lock_guard<wpi::mutex> lock(m_mutex);
int ndx = CreateOrUpdateProperty(name,
[=] {
return wpi::make_unique<PropertyImpl>(
name, kind, minimum, maximum, step,
defaultValue, value);
},
[&](PropertyImpl& prop) {
// update all but value
prop.propKind = kind;
prop.minimum = minimum;
prop.maximum = maximum;
prop.step = step;
prop.defaultValue = defaultValue;
value = prop.value;
});
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CREATED, name, ndx,
kind, value, wpi::Twine{});
return ndx;
}
int CvSourceImpl::CreateProperty(
const wpi::Twine& name, CS_PropertyKind kind, int minimum, int maximum,
int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange) {
// TODO
return 0;
}
void CvSourceImpl::SetEnumPropertyChoices(int property,
wpi::ArrayRef<std::string> choices,
CS_Status* status) {
std::lock_guard<wpi::mutex> lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
return;
}
if (prop->propKind != CS_PROP_ENUM) {
*status = CS_WRONG_PROPERTY_TYPE;
return;
}
prop->enumChoices = choices;
m_notifier.NotifySourceProperty(*this, CS_SOURCE_PROPERTY_CHOICES_UPDATED,
prop->name, property, CS_PROP_ENUM,
prop->value, wpi::Twine{});
}
namespace cs {
CS_Source CreateCvSource(const wpi::Twine& name, const VideoMode& mode,
@@ -163,10 +81,12 @@ void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status) {
static_cast<CvSourceImpl&>(*data->source).PutFrame(image);
}
static constexpr unsigned SourceMask = CS_SINK_CV | CS_SINK_RAW;
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_CV) {
if (!data || (data->kind & SourceMask) == 0) {
*status = CS_INVALID_HANDLE;
return;
}
@@ -175,7 +95,7 @@ void NotifySourceError(CS_Source source, const wpi::Twine& msg,
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_CV) {
if (!data || (data->kind & SourceMask) == 0) {
*status = CS_INVALID_HANDLE;
return;
}
@@ -185,7 +105,7 @@ void SetSourceConnected(CS_Source source, bool connected, CS_Status* status) {
void SetSourceDescription(CS_Source source, const wpi::Twine& description,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_CV) {
if (!data || (data->kind & SourceMask) == 0) {
*status = CS_INVALID_HANDLE;
return;
}
@@ -197,7 +117,7 @@ CS_Property CreateSourceProperty(CS_Source source, const wpi::Twine& name,
int step, int defaultValue, int value,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_CV) {
if (!data || (data->kind & SourceMask) == 0) {
*status = CS_INVALID_HANDLE;
return -1;
}
@@ -212,7 +132,7 @@ CS_Property CreateSourcePropertyCallback(
int maximum, int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange, CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_CV) {
if (!data || (data->kind & SourceMask) == 0) {
*status = CS_INVALID_HANDLE;
return -1;
}
@@ -226,7 +146,7 @@ void SetSourceEnumPropertyChoices(CS_Source source, CS_Property property,
wpi::ArrayRef<std::string> choices,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_CV) {
if (!data || (data->kind & SourceMask) == 0) {
*status = CS_INVALID_HANDLE;
return;
}
@@ -258,11 +178,13 @@ CS_Source CS_CreateCvSource(const char* name, const CS_VideoMode* mode,
status);
}
#if CV_VERSION_MAJOR < 4
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
CS_Status* status) {
auto mat = cv::cvarrToMat(image);
return cs::PutSourceFrame(source, mat, status);
}
#endif // CV_VERSION_MAJOR < 4
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status) {
return cs::PutSourceFrame(source, *image, status);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -18,33 +18,19 @@
#include <wpi/ArrayRef.h>
#include <wpi/Twine.h>
#include "ConfigurableSourceImpl.h"
#include "SourceImpl.h"
namespace cs {
class CvSourceImpl : public SourceImpl {
class CvSourceImpl : public ConfigurableSourceImpl {
public:
CvSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, const VideoMode& mode);
~CvSourceImpl() override;
void Start() override;
bool SetVideoMode(const VideoMode& mode, CS_Status* status) override;
void NumSinksChanged() override;
void NumSinksEnabledChanged() override;
// OpenCV-specific functions
void PutFrame(cv::Mat& image);
void NotifyError(const wpi::Twine& msg);
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
int maximum, int step, int defaultValue, int value);
int CreateProperty(const wpi::Twine& name, CS_PropertyKind kind, int minimum,
int maximum, int step, int defaultValue, int value,
std::function<void(CS_Property property)> onChange);
void SetEnumPropertyChoices(int property, wpi::ArrayRef<std::string> choices,
CS_Status* status);
private:
std::atomic_bool m_connected{true};

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -36,7 +36,7 @@ Frame::Frame(SourceImpl& source, std::unique_ptr<Image> image, Time time)
Image* Frame::GetNearestImage(int width, int height) const {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
Image* found = nullptr;
// Ideally we want the smallest image at least width/height in size
@@ -60,7 +60,7 @@ Image* Frame::GetNearestImage(int width, int height,
VideoMode::PixelFormat pixelFormat,
int jpegQuality) const {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
Image* found = nullptr;
// We want the smallest image at least width/height (or the next largest),
@@ -253,7 +253,7 @@ Image* Frame::ConvertMJPEGToBGR(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
@@ -274,7 +274,7 @@ Image* Frame::ConvertMJPEGToGray(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
@@ -294,7 +294,7 @@ Image* Frame::ConvertYUYVToBGR(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
@@ -314,7 +314,7 @@ Image* Frame::ConvertBGRToRGB565(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
@@ -334,7 +334,7 @@ Image* Frame::ConvertRGB565ToBGR(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
@@ -354,14 +354,14 @@ Image* Frame::ConvertBGRToGray(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
}
Image* Frame::ConvertGrayToBGR(Image* image) {
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
// Allocate a BGR image
auto newImage =
@@ -374,7 +374,7 @@ Image* Frame::ConvertGrayToBGR(Image* image) {
// Save the result
Image* rv = newImage.release();
if (m_impl) {
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
m_impl->images.push_back(rv);
}
return rv;
@@ -383,7 +383,7 @@ Image* Frame::ConvertGrayToBGR(Image* image) {
Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
if (!image || image->pixelFormat != VideoMode::kBGR) return nullptr;
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
// Allocate a JPEG image. We don't actually know what the resulting size
// will be; while the destination will automatically grow, doing so will
@@ -397,7 +397,7 @@ Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
// Compress
if (m_impl->compressionParams.empty()) {
m_impl->compressionParams.push_back(CV_IMWRITE_JPEG_QUALITY);
m_impl->compressionParams.push_back(cv::IMWRITE_JPEG_QUALITY);
m_impl->compressionParams.push_back(quality);
} else {
m_impl->compressionParams[1] = quality;
@@ -414,7 +414,7 @@ Image* Frame::ConvertBGRToMJPEG(Image* image, int quality) {
Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
if (!image || image->pixelFormat != VideoMode::kGray) return nullptr;
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
// Allocate a JPEG image. We don't actually know what the resulting size
// will be; while the destination will automatically grow, doing so will
@@ -428,7 +428,7 @@ Image* Frame::ConvertGrayToMJPEG(Image* image, int quality) {
// Compress
if (m_impl->compressionParams.empty()) {
m_impl->compressionParams.push_back(CV_IMWRITE_JPEG_QUALITY);
m_impl->compressionParams.push_back(cv::IMWRITE_JPEG_QUALITY);
m_impl->compressionParams.push_back(quality);
} else {
m_impl->compressionParams[1] = quality;
@@ -446,7 +446,7 @@ Image* Frame::GetImageImpl(int width, int height,
VideoMode::PixelFormat pixelFormat,
int requiredJpegQuality, int defaultJpegQuality) {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
Image* cur = GetNearestImage(width, height, pixelFormat, requiredJpegQuality);
if (!cur || cur->Is(width, height, pixelFormat, requiredJpegQuality))
return cur;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -80,42 +80,42 @@ class Frame {
int GetOriginalWidth() const {
if (!m_impl) return 0;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
return m_impl->images[0]->width;
}
int GetOriginalHeight() const {
if (!m_impl) return 0;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
return m_impl->images[0]->height;
}
int GetOriginalPixelFormat() const {
if (!m_impl) return 0;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
return m_impl->images[0]->pixelFormat;
}
int GetOriginalJpegQuality() const {
if (!m_impl) return 0;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
if (m_impl->images.empty()) return 0;
return m_impl->images[0]->jpegQuality;
}
Image* GetExistingImage(size_t i = 0) const {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
if (i >= m_impl->images.size()) return nullptr;
return m_impl->images[i];
}
Image* GetExistingImage(int width, int height) const {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
if (i->Is(width, height)) return i;
}
@@ -125,7 +125,7 @@ class Frame {
Image* GetExistingImage(int width, int height,
VideoMode::PixelFormat pixelFormat) const {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
if (i->Is(width, height, pixelFormat)) return i;
}
@@ -136,7 +136,7 @@ class Frame {
VideoMode::PixelFormat pixelFormat,
int jpegQuality) const {
if (!m_impl) return nullptr;
std::lock_guard<wpi::recursive_mutex> lock(m_impl->mutex);
std::scoped_lock lock(m_impl->mutex);
for (auto i : m_impl->images) {
if (i->Is(width, height, pixelFormat, jpegQuality)) return i;
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -7,9 +7,8 @@
#include "HttpCameraImpl.h"
#include <wpi/STLExtras.h>
#include <wpi/MemAlloc.h>
#include <wpi/TCPConnector.h>
#include <wpi/memory.h>
#include <wpi/timestamp.h>
#include "Handle.h"
@@ -38,7 +37,7 @@ HttpCameraImpl::~HttpCameraImpl() {
// Close file if it's open
{
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (m_streamConn) m_streamConn->stream->close();
if (m_settingsConn) m_settingsConn->stream->close();
}
@@ -65,7 +64,7 @@ void HttpCameraImpl::Start() {
void HttpCameraImpl::MonitorThreadMain() {
while (m_active) {
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
// sleep for 1 second between checks
m_monitorCond.wait_for(lock, std::chrono::seconds(1),
[=] { return !m_active; });
@@ -96,7 +95,7 @@ void HttpCameraImpl::StreamThreadMain() {
// disconnect if not enabled
if (!IsEnabled()) {
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
if (m_streamConn) m_streamConn->stream->close();
// Wait for enable
m_sinkEnabledCond.wait(lock, [=] { return !m_active || IsEnabled(); });
@@ -118,7 +117,7 @@ void HttpCameraImpl::StreamThreadMain() {
// stream
DeviceStream(conn->is, boundary);
{
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
m_streamConn = nullptr;
}
}
@@ -132,7 +131,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
// Build the request
wpi::HttpRequest req;
{
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (m_locations.empty()) {
SERROR("locations array is empty!?");
std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -149,12 +148,12 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
if (!m_active || !stream) return nullptr;
auto connPtr = wpi::make_unique<wpi::HttpConnection>(std::move(stream), 1);
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
wpi::HttpConnection* conn = connPtr.get();
// update m_streamConn
{
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_frameCount = 1; // avoid a race with monitor thread
m_streamConn = std::move(connPtr);
}
@@ -162,7 +161,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
std::string warn;
if (!conn->Handshake(req, &warn)) {
SWARNING(GetName() << ": " << warn);
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_streamConn = nullptr;
return nullptr;
}
@@ -174,7 +173,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
if (mediaType != "multipart/x-mixed-replace") {
SWARNING("\"" << req.host << "\": unrecognized Content-Type \"" << mediaType
<< "\"");
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_streamConn = nullptr;
return nullptr;
}
@@ -189,6 +188,9 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
std::tie(key, value) = keyvalue.split('=');
if (key.trim() == "boundary") {
value = value.trim().trim('"'); // value may be quoted
if (value.startswith("--")) {
value = value.substr(2);
}
boundary.append(value.begin(), value.end());
}
}
@@ -196,7 +198,7 @@ wpi::HttpConnection* HttpCameraImpl::DeviceStreamConnect(
if (boundary.empty()) {
SWARNING("\"" << req.host
<< "\": empty multi-part boundary or no Content-Type");
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_streamConn = nullptr;
return nullptr;
}
@@ -219,11 +221,16 @@ void HttpCameraImpl::DeviceStream(wpi::raw_istream& is,
if (!FindMultipartBoundary(is, boundary, nullptr)) break;
// Read the next two characters after the boundary (normally \r\n)
// Handle just \n for LabVIEW however
char eol[2];
is.read(eol, 2);
is.read(eol, 1);
if (!m_active || is.has_error()) break;
// End-of-stream is indicated with trailing --
if (eol[0] == '-' && eol[1] == '-') break;
if (eol[0] != '\n') {
is.read(eol + 1, 1);
if (!m_active || is.has_error()) break;
// End-of-stream is indicated with trailing --
if (eol[0] == '-' && eol[1] == '-') break;
}
if (!DeviceStreamFrame(is, imageBuf))
++numErrors;
@@ -291,7 +298,7 @@ void HttpCameraImpl::SettingsThreadMain() {
for (;;) {
wpi::HttpRequest req;
{
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
m_settingsCond.wait(lock, [=] {
return !m_active || (m_prefLocation != -1 && !m_settings.empty());
});
@@ -314,12 +321,12 @@ void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
if (!m_active || !stream) return;
auto connPtr = wpi::make_unique<wpi::HttpConnection>(std::move(stream), 1);
auto connPtr = std::make_unique<wpi::HttpConnection>(std::move(stream), 1);
wpi::HttpConnection* conn = connPtr.get();
// update m_settingsConn
{
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_settingsConn = std::move(connPtr);
}
@@ -331,7 +338,7 @@ void HttpCameraImpl::DeviceSendSettings(wpi::HttpRequest& req) {
}
CS_HttpCameraKind HttpCameraImpl::GetKind() const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
return m_kind;
}
@@ -349,7 +356,7 @@ bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
}
}
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_locations.swap(locations);
m_nextLocation = 0;
m_streamSettingsUpdated = true;
@@ -357,7 +364,7 @@ bool HttpCameraImpl::SetUrls(wpi::ArrayRef<std::string> urls,
}
std::vector<std::string> HttpCameraImpl::GetUrls() const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
std::vector<std::string> urls;
for (const auto& loc : m_locations) urls.push_back(loc.url);
return urls;
@@ -368,8 +375,8 @@ void HttpCameraImpl::CreateProperty(const wpi::Twine& name,
bool viaSettings, CS_PropertyKind kind,
int minimum, int maximum, int step,
int defaultValue, int value) const {
std::lock_guard<wpi::mutex> lock(m_mutex);
m_propertyData.emplace_back(wpi::make_unique<PropertyData>(
std::scoped_lock lock(m_mutex);
m_propertyData.emplace_back(std::make_unique<PropertyData>(
name, httpParam, viaSettings, kind, minimum, maximum, step, defaultValue,
value));
@@ -382,8 +389,8 @@ template <typename T>
void HttpCameraImpl::CreateEnumProperty(
const wpi::Twine& name, const wpi::Twine& httpParam, bool viaSettings,
int defaultValue, int value, std::initializer_list<T> choices) const {
std::lock_guard<wpi::mutex> lock(m_mutex);
m_propertyData.emplace_back(wpi::make_unique<PropertyData>(
std::scoped_lock lock(m_mutex);
m_propertyData.emplace_back(std::make_unique<PropertyData>(
name, httpParam, viaSettings, CS_PROP_ENUM, 0, choices.size() - 1, 1,
defaultValue, value));
@@ -401,11 +408,15 @@ void HttpCameraImpl::CreateEnumProperty(
std::unique_ptr<PropertyImpl> HttpCameraImpl::CreateEmptyProperty(
const wpi::Twine& name) const {
return wpi::make_unique<PropertyData>(name);
return std::make_unique<PropertyData>(name);
}
bool HttpCameraImpl::CacheProperties(CS_Status* status) const {
std::lock_guard<wpi::mutex> lock(m_mutex);
#ifdef _MSC_VER // work around VS2019 16.4.0 bug
std::scoped_lock<wpi::mutex> lock(m_mutex);
#else
std::scoped_lock lock(m_mutex);
#endif
// Pretty typical set of video modes
m_videoModes.clear();
@@ -461,7 +472,7 @@ void HttpCameraImpl::SetExposureManual(int value, CS_Status* status) {
bool HttpCameraImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) {
if (mode.pixelFormat != VideoMode::kMJPEG) return false;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_mode = mode;
m_streamSettingsUpdated = true;
return true;
@@ -490,7 +501,7 @@ bool AxisCameraImpl::CacheProperties(CS_Status* status) const {
true, CS_PROP_INTEGER, 0, 100, 1, 50, 50);
// TODO: get video modes from device
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_videoModes.clear();
m_videoModes.emplace_back(VideoMode::kMJPEG, 640, 480, 30);
m_videoModes.emplace_back(VideoMode::kMJPEG, 480, 360, 30);
@@ -603,7 +614,7 @@ void CS_SetHttpCameraUrls(CS_Source source, const char** urls, int count,
char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status) {
auto urls = cs::GetHttpCameraUrls(source, status);
char** out =
static_cast<char**>(wpi::CheckedMalloc(urls.size() * sizeof(char*)));
static_cast<char**>(wpi::safe_malloc(urls.size() * sizeof(char*)));
*count = urls.size();
for (size_t i = 0; i < urls.size(); ++i) out[i] = cs::ConvertToC(urls[i]);
return out;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -17,7 +17,7 @@
#define WARNING(x) WPI_WARNING(m_logger, x)
#define INFO(x) WPI_INFO(m_logger, x)
#define DEBUG(x) WPI_DEBUG(m_logger, x)
#define DEBUG0(x) WPI_DEBUG(m_logger, x)
#define DEBUG1(x) WPI_DEBUG1(m_logger, x)
#define DEBUG2(x) WPI_DEBUG2(m_logger, x)
#define DEBUG3(x) WPI_DEBUG3(m_logger, x)
@@ -27,7 +27,7 @@
#define SWARNING(x) WARNING(GetName() << ": " << x)
#define SINFO(x) INFO(GetName() << ": " << x)
#define SDEBUG(x) DEBUG(GetName() << ": " << x)
#define SDEBUG(x) DEBUG0(GetName() << ": " << x)
#define SDEBUG1(x) DEBUG1(GetName() << ": " << x)
#define SDEBUG2(x) DEBUG2(GetName() << ": " << x)
#define SDEBUG3(x) DEBUG3(GetName() << ": " << x)

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -105,18 +105,18 @@ class MjpegServerImpl::ConnThread : public wpi::SafeThread {
wpi::StringRef GetName() { return m_name; }
std::shared_ptr<SourceImpl> GetSource() {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
return m_source;
}
void StartStream() {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (m_source) m_source->EnableSink();
m_streaming = true;
}
void StopStream() {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (m_source) m_source->DisableSink();
m_streaming = false;
}
@@ -865,7 +865,7 @@ void MjpegServerImpl::ConnThread::ProcessRequest() {
// worker thread for clients that connected to this server
void MjpegServerImpl::ConnThread::Main() {
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
while (m_active) {
while (!m_stream) {
m_cond.wait(lock);
@@ -898,7 +898,7 @@ void MjpegServerImpl::ServerThreadMain() {
auto source = GetSource();
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
// Find unoccupied worker thread, or create one if necessary
auto it = std::find_if(m_connThreads.begin(), m_connThreads.end(),
[](const wpi::SafeThreadOwner<ConnThread>& owner) {
@@ -937,7 +937,7 @@ void MjpegServerImpl::ServerThreadMain() {
}
void MjpegServerImpl::SetSourceImpl(std::shared_ptr<SourceImpl> source) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
for (auto& connThread : m_connThreads) {
if (auto thr = connThread.GetThread()) {
if (thr->m_source != source) {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2015-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. */
@@ -102,7 +102,7 @@ void Notifier::Stop() { m_owner.Stop(); }
void Notifier::Thread::Main() {
if (m_on_start) m_on_start();
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
while (m_active) {
while (m_notifications.empty()) {
m_cond.wait(lock);

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -18,7 +18,7 @@ int PropertyContainer::GetPropertyIndex(const wpi::Twine& name) const {
// We can't fail, so instead we create a new index if caching fails.
CS_Status status = 0;
if (!m_properties_cached) CacheProperties(&status);
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
wpi::SmallVector<char, 64> nameBuf;
int& ndx = m_properties[name.toStringRef(nameBuf)];
if (ndx == 0) {
@@ -33,7 +33,7 @@ wpi::ArrayRef<int> PropertyContainer::EnumerateProperties(
wpi::SmallVectorImpl<int>& vec, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status))
return wpi::ArrayRef<int>{};
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
for (int i = 0; i < static_cast<int>(m_propertyData.size()); ++i) {
if (m_propertyData[i]) vec.push_back(i + 1);
}
@@ -43,7 +43,7 @@ wpi::ArrayRef<int> PropertyContainer::EnumerateProperties(
CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
CS_Status status = 0;
if (!m_properties_cached && !CacheProperties(&status)) return CS_PROP_NONE;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) return CS_PROP_NONE;
return prop->propKind;
@@ -52,7 +52,7 @@ CS_PropertyKind PropertyContainer::GetPropertyKind(int property) const {
wpi::StringRef PropertyContainer::GetPropertyName(
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -64,7 +64,7 @@ wpi::StringRef PropertyContainer::GetPropertyName(
int PropertyContainer::GetProperty(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -80,7 +80,7 @@ int PropertyContainer::GetProperty(int property, CS_Status* status) const {
void PropertyContainer::SetProperty(int property, int value,
CS_Status* status) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -101,7 +101,7 @@ void PropertyContainer::SetProperty(int property, int value,
int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -112,7 +112,7 @@ int PropertyContainer::GetPropertyMin(int property, CS_Status* status) const {
int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -123,7 +123,7 @@ int PropertyContainer::GetPropertyMax(int property, CS_Status* status) const {
int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -135,7 +135,7 @@ int PropertyContainer::GetPropertyStep(int property, CS_Status* status) const {
int PropertyContainer::GetPropertyDefault(int property,
CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return 0;
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -147,7 +147,7 @@ int PropertyContainer::GetPropertyDefault(int property,
wpi::StringRef PropertyContainer::GetStringProperty(
int property, wpi::SmallVectorImpl<char>& buf, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return wpi::StringRef{};
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -164,7 +164,7 @@ wpi::StringRef PropertyContainer::GetStringProperty(
void PropertyContainer::SetStringProperty(int property, const wpi::Twine& value,
CS_Status* status) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -186,7 +186,7 @@ std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
int property, CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status))
return std::vector<std::string>{};
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
auto prop = GetProperty(property);
if (!prop) {
*status = CS_INVALID_PROPERTY;
@@ -201,7 +201,7 @@ std::vector<std::string> PropertyContainer::GetEnumPropertyChoices(
std::unique_ptr<PropertyImpl> PropertyContainer::CreateEmptyProperty(
const wpi::Twine& name) const {
return wpi::make_unique<PropertyImpl>(name);
return std::make_unique<PropertyImpl>(name);
}
bool PropertyContainer::CacheProperties(CS_Status* status) const {

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -0,0 +1,199 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#include "RawSinkImpl.h"
#include "Instance.h"
#include "cscore.h"
#include "cscore_raw.h"
using namespace cs;
RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry)
: SinkImpl{name, logger, notifier, telemetry} {
m_active = true;
// m_thread = std::thread(&RawSinkImpl::ThreadMain, this);
}
RawSinkImpl::RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
std::function<void(uint64_t time)> processFrame)
: SinkImpl{name, logger, notifier, telemetry} {}
RawSinkImpl::~RawSinkImpl() { Stop(); }
void RawSinkImpl::Stop() {
m_active = false;
// wake up any waiters by forcing an empty frame to be sent
if (auto source = GetSource()) source->Wakeup();
// join thread
if (m_thread.joinable()) m_thread.join();
}
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image) {
SetEnabled(true);
auto source = GetSource();
if (!source) {
// Source disconnected; sleep for one second
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
auto frame = source->GetNextFrame(); // blocks
if (!frame) {
// Bad frame; sleep for 20 ms so we don't consume all processor time.
std::this_thread::sleep_for(std::chrono::milliseconds(20));
return 0; // signal error
}
return GrabFrameImpl(image, frame);
}
uint64_t RawSinkImpl::GrabFrame(CS_RawFrame& image, double timeout) {
SetEnabled(true);
auto source = GetSource();
if (!source) {
// Source disconnected; sleep for one second
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
auto frame = source->GetNextFrame(timeout); // blocks
if (!frame) {
// Bad frame; sleep for 20 ms so we don't consume all processor time.
std::this_thread::sleep_for(std::chrono::milliseconds(20));
return 0; // signal error
}
return GrabFrameImpl(image, frame);
}
uint64_t RawSinkImpl::GrabFrameImpl(CS_RawFrame& rawFrame,
Frame& incomingFrame) {
Image* newImage = nullptr;
if (rawFrame.pixelFormat == CS_PixelFormat::CS_PIXFMT_UNKNOWN) {
// Always get incoming image directly on unknown
newImage = incomingFrame.GetExistingImage(0);
} else {
// Format is known, ask for it
auto width = rawFrame.width;
auto height = rawFrame.height;
auto pixelFormat =
static_cast<VideoMode::PixelFormat>(rawFrame.pixelFormat);
if (width <= 0 || height <= 0) {
width = incomingFrame.GetOriginalWidth();
height = incomingFrame.GetOriginalHeight();
}
newImage = incomingFrame.GetImage(width, height, pixelFormat);
}
if (!newImage) {
// Shouldn't happen, but just in case...
std::this_thread::sleep_for(std::chrono::milliseconds(20));
return 0;
}
CS_AllocateRawFrameData(&rawFrame, newImage->size());
rawFrame.height = newImage->height;
rawFrame.width = newImage->width;
rawFrame.pixelFormat = newImage->pixelFormat;
rawFrame.totalData = newImage->size();
std::copy(newImage->data(), newImage->data() + rawFrame.totalData,
rawFrame.data);
return incomingFrame.GetTime();
}
// Send HTTP response and a stream of JPG-frames
void RawSinkImpl::ThreadMain() {
Enable();
while (m_active) {
auto source = GetSource();
if (!source) {
// Source disconnected; sleep for one second
std::this_thread::sleep_for(std::chrono::seconds(1));
continue;
}
SDEBUG4("waiting for frame");
Frame frame = source->GetNextFrame(); // blocks
if (!m_active) break;
if (!frame) {
// Bad frame; sleep for 10 ms so we don't consume all processor time.
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
// TODO m_processFrame();
}
Disable();
}
namespace cs {
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSink(CS_SINK_RAW,
std::make_shared<RawSinkImpl>(
name, inst.logger, inst.notifier, inst.telemetry));
}
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSink(CS_SINK_RAW, std::make_shared<RawSinkImpl>(
name, inst.logger, inst.notifier,
inst.telemetry, processFrame));
}
uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || data->kind != CS_SINK_RAW) {
*status = CS_INVALID_HANDLE;
return 0;
}
return static_cast<RawSinkImpl&>(*data->sink).GrabFrame(image);
}
uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout,
CS_Status* status) {
auto data = Instance::GetInstance().GetSink(sink);
if (!data || data->kind != CS_SINK_RAW) {
*status = CS_INVALID_HANDLE;
return 0;
}
return static_cast<RawSinkImpl&>(*data->sink).GrabFrame(image, timeout);
}
} // namespace cs
extern "C" {
CS_Sink CS_CreateRawSink(const char* name, CS_Status* status) {
return cs::CreateRawSink(name, status);
}
CS_Sink CS_CreateRawSinkCallback(const char* name, void* data,
void (*processFrame)(void* data,
uint64_t time),
CS_Status* status) {
return cs::CreateRawSinkCallback(
name, [=](uint64_t time) { processFrame(data, time); }, status);
}
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* image,
CS_Status* status) {
return cs::GrabSinkFrame(sink, *image, status);
}
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* image,
double timeout, CS_Status* status) {
return cs::GrabSinkFrameTimeout(sink, *image, timeout, status);
}
} // extern "C"

View File

@@ -0,0 +1,52 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#ifndef CSCORE_RAWSINKIMPL_H_
#define CSCORE_RAWSINKIMPL_H_
#include <stdint.h>
#include <atomic>
#include <functional>
#include <thread>
#include <wpi/Twine.h>
#include <wpi/condition_variable.h>
#include "Frame.h"
#include "SinkImpl.h"
#include "cscore_raw.h"
namespace cs {
class SourceImpl;
class RawSinkImpl : public SinkImpl {
public:
RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry);
RawSinkImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry,
std::function<void(uint64_t time)> processFrame);
~RawSinkImpl() override;
void Stop();
uint64_t GrabFrame(CS_RawFrame& frame);
uint64_t GrabFrame(CS_RawFrame& frame, double timeout);
private:
void ThreadMain();
uint64_t GrabFrameImpl(CS_RawFrame& rawFrame, Frame& incomingFrame);
std::atomic_bool m_active; // set to false to terminate threads
std::thread m_thread;
std::function<void(uint64_t time)> m_processFrame;
};
} // namespace cs
#endif // CSCORE_RAWSINKIMPL_H_

View File

@@ -0,0 +1,83 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#include "RawSourceImpl.h"
#include <wpi/timestamp.h>
#include "Handle.h"
#include "Instance.h"
#include "Log.h"
#include "Notifier.h"
#include "cscore_raw.h"
using namespace cs;
RawSourceImpl::RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger,
Notifier& notifier, Telemetry& telemetry,
const VideoMode& mode)
: ConfigurableSourceImpl{name, logger, notifier, telemetry, mode} {}
RawSourceImpl::~RawSourceImpl() {}
void RawSourceImpl::PutFrame(const CS_RawFrame& image) {
int type;
switch (image.pixelFormat) {
case VideoMode::kYUYV:
case VideoMode::kRGB565:
type = CV_8UC2;
break;
case VideoMode::kBGR:
type = CV_8UC3;
break;
case VideoMode::kGray:
case VideoMode::kMJPEG:
default:
type = CV_8UC1;
break;
}
cv::Mat finalImage{image.height, image.width, type, image.data};
std::unique_ptr<Image> dest =
AllocImage(static_cast<VideoMode::PixelFormat>(image.pixelFormat),
image.width, image.height, image.totalData);
finalImage.copyTo(dest->AsMat());
SourceImpl::PutFrame(std::move(dest), wpi::Now());
}
namespace cs {
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
CS_Status* status) {
auto& inst = Instance::GetInstance();
return inst.CreateSource(CS_SOURCE_RAW, std::make_shared<RawSourceImpl>(
name, inst.logger, inst.notifier,
inst.telemetry, mode));
}
void PutSourceFrame(CS_Source source, const CS_RawFrame& image,
CS_Status* status) {
auto data = Instance::GetInstance().GetSource(source);
if (!data || data->kind != CS_SOURCE_RAW) {
*status = CS_INVALID_HANDLE;
return;
}
static_cast<RawSourceImpl&>(*data->source).PutFrame(image);
}
} // namespace cs
extern "C" {
CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode,
CS_Status* status) {
return cs::CreateRawSource(name, static_cast<const cs::VideoMode&>(*mode),
status);
}
void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image,
CS_Status* status) {
return cs::PutSourceFrame(source, *image, status);
}
} // extern "C"

View File

@@ -0,0 +1,41 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#ifndef CSCORE_RAWSOURCEIMPL_H_
#define CSCORE_RAWSOURCEIMPL_H_
#include <atomic>
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include <wpi/ArrayRef.h>
#include <wpi/Twine.h>
#include "ConfigurableSourceImpl.h"
#include "SourceImpl.h"
#include "cscore_raw.h"
namespace cs {
class RawSourceImpl : public ConfigurableSourceImpl {
public:
RawSourceImpl(const wpi::Twine& name, wpi::Logger& logger, Notifier& notifier,
Telemetry& telemetry, const VideoMode& mode);
~RawSourceImpl() override;
// Raw-specific functions
void PutFrame(const CS_RawFrame& image);
private:
std::atomic_bool m_connected{true};
};
} // namespace cs
#endif // CSCORE_RAWSOURCEIMPL_H_

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -30,18 +30,18 @@ SinkImpl::~SinkImpl() {
}
void SinkImpl::SetDescription(const wpi::Twine& description) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_description = description.str();
}
wpi::StringRef SinkImpl::GetDescription(wpi::SmallVectorImpl<char>& buf) const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
buf.append(m_description.begin(), m_description.end());
return wpi::StringRef{buf.data(), buf.size()};
}
void SinkImpl::Enable() {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
++m_enabledCount;
if (m_enabledCount == 1) {
if (m_source) m_source->EnableSink();
@@ -50,7 +50,7 @@ void SinkImpl::Enable() {
}
void SinkImpl::Disable() {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
--m_enabledCount;
if (m_enabledCount == 0) {
if (m_source) m_source->DisableSink();
@@ -59,7 +59,7 @@ void SinkImpl::Disable() {
}
void SinkImpl::SetEnabled(bool enabled) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (enabled && m_enabledCount == 0) {
if (m_source) m_source->EnableSink();
m_enabledCount = 1;
@@ -73,7 +73,7 @@ void SinkImpl::SetEnabled(bool enabled) {
void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
{
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (m_source == source) return;
if (m_source) {
if (m_enabledCount > 0) m_source->DisableSink();
@@ -89,13 +89,13 @@ void SinkImpl::SetSource(std::shared_ptr<SourceImpl> source) {
}
std::string SinkImpl::GetError() const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (!m_source) return "no source connected";
return m_source->GetCurFrame().GetError();
}
wpi::StringRef SinkImpl::GetError(wpi::SmallVectorImpl<char>& buf) const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
if (!m_source) return "no source connected";
// Make a copy as it's shared data
wpi::StringRef error = m_source->GetCurFrame().GetError();

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -48,7 +48,7 @@ class SinkImpl : public PropertyContainer {
void SetSource(std::shared_ptr<SourceImpl> source);
std::shared_ptr<SourceImpl> GetSource() const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
return m_source;
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -10,7 +10,6 @@
#include <algorithm>
#include <cstring>
#include <wpi/STLExtras.h>
#include <wpi/json.h>
#include <wpi/timestamp.h>
@@ -45,13 +44,13 @@ SourceImpl::~SourceImpl() {
}
void SourceImpl::SetDescription(const wpi::Twine& description) {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
m_description = description.str();
}
wpi::StringRef SourceImpl::GetDescription(
wpi::SmallVectorImpl<char>& buf) const {
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
buf.append(m_description.begin(), m_description.end());
return wpi::StringRef{buf.data(), buf.size()};
}
@@ -65,24 +64,24 @@ void SourceImpl::SetConnected(bool connected) {
}
uint64_t SourceImpl::GetCurFrameTime() {
std::unique_lock<wpi::mutex> lock{m_frameMutex};
std::unique_lock lock{m_frameMutex};
return m_frame.GetTime();
}
Frame SourceImpl::GetCurFrame() {
std::unique_lock<wpi::mutex> lock{m_frameMutex};
std::unique_lock lock{m_frameMutex};
return m_frame;
}
Frame SourceImpl::GetNextFrame() {
std::unique_lock<wpi::mutex> lock{m_frameMutex};
std::unique_lock lock{m_frameMutex};
auto oldTime = m_frame.GetTime();
m_frameCv.wait(lock, [=] { return m_frame.GetTime() != oldTime; });
return m_frame;
}
Frame SourceImpl::GetNextFrame(double timeout) {
std::unique_lock<wpi::mutex> lock{m_frameMutex};
std::unique_lock lock{m_frameMutex};
auto oldTime = m_frame.GetTime();
if (!m_frameCv.wait_for(
lock, std::chrono::milliseconds(static_cast<int>(timeout * 1000)),
@@ -94,7 +93,7 @@ Frame SourceImpl::GetNextFrame(double timeout) {
void SourceImpl::Wakeup() {
{
std::lock_guard<wpi::mutex> lock{m_frameMutex};
std::scoped_lock lock{m_frameMutex};
m_frame = Frame{*this, wpi::StringRef{}, 0};
}
m_frameCv.notify_all();
@@ -135,7 +134,7 @@ void SourceImpl::SetExposureManual(int value, CS_Status* status) {
VideoMode SourceImpl::GetVideoMode(CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status)) return VideoMode{};
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
return m_mode;
}
@@ -381,7 +380,7 @@ std::vector<VideoMode> SourceImpl::EnumerateVideoModes(
CS_Status* status) const {
if (!m_properties_cached && !CacheProperties(status))
return std::vector<VideoMode>{};
std::lock_guard<wpi::mutex> lock(m_mutex);
std::scoped_lock lock(m_mutex);
return m_videoModes;
}
@@ -389,7 +388,7 @@ std::unique_ptr<Image> SourceImpl::AllocImage(
VideoMode::PixelFormat pixelFormat, int width, int height, size_t size) {
std::unique_ptr<Image> image;
{
std::lock_guard<wpi::mutex> lock{m_poolMutex};
std::scoped_lock lock{m_poolMutex};
// find the smallest existing frame that is at least big enough.
int found = -1;
for (size_t i = 0; i < m_imagesAvail.size(); ++i) {
@@ -441,7 +440,7 @@ void SourceImpl::PutFrame(std::unique_ptr<Image> image, Frame::Time time) {
// Update frame
{
std::lock_guard<wpi::mutex> lock{m_frameMutex};
std::scoped_lock lock{m_frameMutex};
m_frame = Frame{*this, std::move(image), time};
}
@@ -452,7 +451,7 @@ void SourceImpl::PutFrame(std::unique_ptr<Image> image, Frame::Time time) {
void SourceImpl::PutError(const wpi::Twine& msg, Frame::Time time) {
// Update frame
{
std::lock_guard<wpi::mutex> lock{m_frameMutex};
std::scoped_lock lock{m_frameMutex};
m_frame = Frame{*this, msg, time};
}
@@ -490,7 +489,7 @@ void SourceImpl::UpdatePropertyValue(int property, bool setString, int value,
}
void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
std::lock_guard<wpi::mutex> lock{m_poolMutex};
std::scoped_lock lock{m_poolMutex};
if (m_destroyFrames) return;
// Return the frame to the pool. First try to find an empty slot, otherwise
// add it to the end.
@@ -512,9 +511,9 @@ void SourceImpl::ReleaseImage(std::unique_ptr<Image> image) {
}
std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
std::lock_guard<wpi::mutex> lock{m_poolMutex};
std::scoped_lock lock{m_poolMutex};
if (m_framesAvail.empty()) return wpi::make_unique<Frame::Impl>(*this);
if (m_framesAvail.empty()) return std::make_unique<Frame::Impl>(*this);
auto impl = std::move(m_framesAvail.back());
m_framesAvail.pop_back();
@@ -522,7 +521,7 @@ std::unique_ptr<Frame::Impl> SourceImpl::AllocFrameImpl() {
}
void SourceImpl::ReleaseFrameImpl(std::unique_ptr<Frame::Impl> impl) {
std::lock_guard<wpi::mutex> lock{m_poolMutex};
std::scoped_lock lock{m_poolMutex};
if (m_destroyFrames) return;
m_framesAvail.push_back(std::move(impl));
}

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2015-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. */
@@ -53,7 +53,7 @@ void Telemetry::Start() { m_owner.Start(m_notifier); }
void Telemetry::Stop() { m_owner.Stop(); }
void Telemetry::Thread::Main() {
std::unique_lock<wpi::mutex> lock(m_mutex);
std::unique_lock lock(m_mutex);
auto prevTime = std::chrono::steady_clock::now();
while (m_active) {
double period = m_period;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -78,7 +78,11 @@ template <typename THandle, typename TStruct, int typeValue, typename TMutex>
template <typename... Args>
THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
Args&&... args) {
std::lock_guard<TMutex> sync(m_handleMutex);
#ifdef _MSC_VER // work around VS2019 16.4.0 bug
std::scoped_lock<TMutex> lock(m_handleMutex);
#else
std::scoped_lock sync(m_handleMutex);
#endif
size_t i;
for (i = 0; i < m_structures.size(); i++) {
if (m_structures[i] == nullptr) {
@@ -96,7 +100,7 @@ THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
std::shared_ptr<THandle> structure) {
std::lock_guard<TMutex> sync(m_handleMutex);
std::scoped_lock sync(m_handleMutex);
size_t i;
for (i = 0; i < m_structures.size(); i++) {
if (m_structures[i] == nullptr) {
@@ -117,7 +121,7 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Get(
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
if (index < 0) return nullptr;
std::lock_guard<TMutex> sync(m_handleMutex);
std::scoped_lock sync(m_handleMutex);
if (index >= static_cast<int>(m_structures.size())) return nullptr;
return m_structures[index];
}
@@ -129,7 +133,7 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Free(
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
if (index < 0) return nullptr;
std::lock_guard<TMutex> sync(m_handleMutex);
std::scoped_lock sync(m_handleMutex);
if (index >= static_cast<int>(m_structures.size())) return nullptr;
auto rv = std::move(m_structures[index]);
m_structures[index].reset();
@@ -148,7 +152,7 @@ UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::GetAll(
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
inline std::vector<std::shared_ptr<TStruct>>
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::FreeAll() {
std::lock_guard<TMutex> sync(m_handleMutex);
std::scoped_lock sync(m_handleMutex);
auto rv = std::move(m_structures);
m_structures.clear();
return rv;
@@ -158,7 +162,7 @@ template <typename THandle, typename TStruct, int typeValue, typename TMutex>
template <typename F>
inline void
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::ForEach(F func) {
std::lock_guard<TMutex> sync(m_handleMutex);
std::scoped_lock sync(m_handleMutex);
for (size_t i = 0; i < m_structures.size(); i++) {
if (m_structures[i] != nullptr) func(MakeHandle(i), *(m_structures[i]));
}
@@ -168,7 +172,7 @@ template <typename THandle, typename TStruct, int typeValue, typename TMutex>
template <typename F>
inline std::pair<THandle, std::shared_ptr<TStruct>>
UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::FindIf(F func) {
std::lock_guard<TMutex> sync(m_handleMutex);
std::scoped_lock sync(m_handleMutex);
for (size_t i = 0; i < m_structures.size(); i++) {
auto& structure = m_structures[i];
if (structure != nullptr && func(*structure))

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -17,10 +17,12 @@ static void ConvertToC(CS_UsbCameraInfo* out, const UsbCameraInfo& in) {
out->path = ConvertToC(in.path);
out->name = ConvertToC(in.name);
out->otherPaths = static_cast<char**>(
wpi::CheckedMalloc(in.otherPaths.size() * sizeof(char*)));
wpi::safe_malloc(in.otherPaths.size() * sizeof(char*)));
out->otherPathsCount = in.otherPaths.size();
for (size_t i = 0; i < in.otherPaths.size(); ++i)
out->otherPaths[i] = cs::ConvertToC(in.otherPaths[i]);
out->vendorId = in.vendorId;
out->productId = in.productId;
}
static void FreeUsbCameraInfo(CS_UsbCameraInfo* info) {
@@ -50,7 +52,7 @@ CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) {
auto info = cs::GetUsbCameraInfo(source, status);
if (*status != CS_OK) return nullptr;
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::CheckedMalloc(sizeof(CS_UsbCameraInfo)));
wpi::safe_malloc(sizeof(CS_UsbCameraInfo)));
ConvertToC(out, info);
return out;
}
@@ -58,7 +60,7 @@ CS_UsbCameraInfo* CS_GetUsbCameraInfo(CS_Source source, CS_Status* status) {
CS_UsbCameraInfo* CS_EnumerateUsbCameras(int* count, CS_Status* status) {
auto cameras = cs::EnumerateUsbCameras(status);
CS_UsbCameraInfo* out = static_cast<CS_UsbCameraInfo*>(
wpi::CheckedMalloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
wpi::safe_malloc(cameras.size() * sizeof(CS_UsbCameraInfo)));
*count = cameras.size();
for (size_t i = 0; i < cameras.size(); ++i) ConvertToC(&out[i], cameras[i]);
return out;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,13 +11,13 @@
#include <cstdlib>
#include <cstring>
#include <wpi/MemAlloc.h>
#include <wpi/StringRef.h>
#include <wpi/memory.h>
namespace cs {
inline char* ConvertToC(wpi::StringRef in) {
char* out = static_cast<char*>(wpi::CheckedMalloc(in.size() + 1));
char* out = static_cast<char*>(wpi::safe_malloc(in.size() + 1));
std::memmove(out, in.data(), in.size());
out[in.size()] = '\0';
return out;

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -11,11 +11,12 @@
#include <cstdlib>
#include <opencv2/core/core.hpp>
#include <wpi/MemAlloc.h>
#include <wpi/SmallString.h>
#include <wpi/memory.h>
#include "c_util.h"
#include "cscore_cpp.h"
#include "cscore_raw.h"
extern "C" {
@@ -70,7 +71,7 @@ char** CS_GetEnumPropertyChoices(CS_Property property, int* count,
CS_Status* status) {
auto choices = cs::GetEnumPropertyChoices(property, status);
char** out =
static_cast<char**>(wpi::CheckedMalloc(choices.size() * sizeof(char*)));
static_cast<char**>(wpi::safe_malloc(choices.size() * sizeof(char*)));
*count = choices.size();
for (size_t i = 0; i < choices.size(); ++i)
out[i] = cs::ConvertToC(choices[i]);
@@ -123,7 +124,7 @@ CS_Property* CS_EnumerateSourceProperties(CS_Source source, int* count,
wpi::SmallVector<CS_Property, 32> buf;
auto vec = cs::EnumerateSourceProperties(source, buf, status);
CS_Property* out = static_cast<CS_Property*>(
wpi::CheckedMalloc(vec.size() * sizeof(CS_Property)));
wpi::safe_malloc(vec.size() * sizeof(CS_Property)));
*count = vec.size();
std::copy(vec.begin(), vec.end(), out);
return out;
@@ -183,7 +184,7 @@ CS_VideoMode* CS_EnumerateSourceVideoModes(CS_Source source, int* count,
CS_Status* status) {
auto vec = cs::EnumerateSourceVideoModes(source, status);
CS_VideoMode* out = static_cast<CS_VideoMode*>(
wpi::CheckedMalloc(vec.size() * sizeof(CS_VideoMode)));
wpi::safe_malloc(vec.size() * sizeof(CS_VideoMode)));
*count = vec.size();
std::copy(vec.begin(), vec.end(), out);
return out;
@@ -193,8 +194,8 @@ CS_Sink* CS_EnumerateSourceSinks(CS_Source source, int* count,
CS_Status* status) {
wpi::SmallVector<CS_Sink, 32> buf;
auto handles = cs::EnumerateSourceSinks(source, buf, status);
CS_Sink* sinks = static_cast<CS_Sink*>(
wpi::CheckedMalloc(handles.size() * sizeof(CS_Sink)));
CS_Sink* sinks =
static_cast<CS_Sink*>(wpi::safe_malloc(handles.size() * sizeof(CS_Sink)));
*count = handles.size();
std::copy(handles.begin(), handles.end(), sinks);
return sinks;
@@ -271,7 +272,7 @@ CS_Property* CS_EnumerateSinkProperties(CS_Sink sink, int* count,
wpi::SmallVector<CS_Property, 32> buf;
auto vec = cs::EnumerateSinkProperties(sink, buf, status);
CS_Property* out = static_cast<CS_Property*>(
wpi::CheckedMalloc(vec.size() * sizeof(CS_Property)));
wpi::safe_malloc(vec.size() * sizeof(CS_Property)));
*count = vec.size();
std::copy(vec.begin(), vec.end(), out);
return out;
@@ -372,7 +373,7 @@ CS_Source* CS_EnumerateSources(int* count, CS_Status* status) {
wpi::SmallVector<CS_Source, 32> buf;
auto handles = cs::EnumerateSourceHandles(buf, status);
CS_Source* sources = static_cast<CS_Source*>(
wpi::CheckedMalloc(handles.size() * sizeof(CS_Source)));
wpi::safe_malloc(handles.size() * sizeof(CS_Source)));
*count = handles.size();
std::copy(handles.begin(), handles.end(), sources);
return sources;
@@ -390,8 +391,8 @@ void CS_ReleaseEnumeratedSources(CS_Source* sources, int count) {
CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status) {
wpi::SmallVector<CS_Sink, 32> buf;
auto handles = cs::EnumerateSinkHandles(buf, status);
CS_Sink* sinks = static_cast<CS_Sink*>(
wpi::CheckedMalloc(handles.size() * sizeof(CS_Sink)));
CS_Sink* sinks =
static_cast<CS_Sink*>(wpi::safe_malloc(handles.size() * sizeof(CS_Sink)));
*count = handles.size();
std::copy(handles.begin(), handles.end(), sinks);
return sinks;
@@ -426,8 +427,8 @@ char* CS_GetHostname() { return cs::ConvertToC(cs::GetHostname()); }
char** CS_GetNetworkInterfaces(int* count) {
auto interfaces = cs::GetNetworkInterfaces();
char** out = static_cast<char**>(
wpi::CheckedMalloc(interfaces.size() * sizeof(char*)));
char** out =
static_cast<char**>(wpi::safe_malloc(interfaces.size() * sizeof(char*)));
*count = interfaces.size();
for (size_t i = 0; i < interfaces.size(); ++i)
out[i] = cs::ConvertToC(interfaces[i]);
@@ -440,4 +441,23 @@ void CS_FreeNetworkInterfaces(char** interfaces, int count) {
std::free(interfaces);
}
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize) {
if (frame->dataLength >= requestedSize) return;
if (frame->data) {
frame->data =
static_cast<char*>(wpi::safe_realloc(frame->data, requestedSize));
} else {
frame->data = static_cast<char*>(wpi::safe_malloc(requestedSize));
}
frame->dataLength = requestedSize;
}
void CS_FreeRawFrameData(CS_RawFrame* frame) {
if (frame->data) {
std::free(frame->data);
frame->data = nullptr;
frame->dataLength = 0;
}
}
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */

View File

@@ -1,17 +1,26 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
/*----------------------------------------------------------------------------*/
#include <exception>
#include <opencv2/core/core.hpp>
#include <wpi/SmallString.h>
#include <wpi/jni_util.h>
#include <wpi/raw_ostream.h>
#include "cscore_cpp.h"
#include "cscore_cv.h"
#include "cscore_raw.h"
#include "edu_wpi_cscore_CameraServerJNI.h"
namespace cv {
class Mat;
} // namespace cv
using namespace wpi::java;
//
@@ -23,21 +32,25 @@ static JavaVM* jvm = nullptr;
static JClass usbCameraInfoCls;
static JClass videoModeCls;
static JClass videoEventCls;
static JClass rawFrameCls;
static JException videoEx;
static JException nullPointerEx;
static JException unsupportedEx;
static JException exceptionEx;
// Thread-attached environment for listener callbacks.
static JNIEnv* listenerEnv = nullptr;
static const JClassInit classes[] = {
{"edu/wpi/cscore/UsbCameraInfo", &usbCameraInfoCls},
{"edu/wpi/cscore/VideoMode", &videoModeCls},
{"edu/wpi/cscore/VideoEvent", &videoEventCls}};
{"edu/wpi/cscore/VideoEvent", &videoEventCls},
{"edu/wpi/cscore/raw/RawFrame", &rawFrameCls}};
static const JExceptionInit exceptions[] = {
{"edu/wpi/cscore/VideoException", &videoEx},
{"java/lang/NullPointerException", &nullPointerEx},
{"java/lang/UnsupportedOperationException", &unsupportedEx}};
{"java/lang/UnsupportedOperationException", &unsupportedEx},
{"java/lang/Exception", &exceptionEx}};
static void ListenerOnStart() {
if (!jvm) return;
@@ -59,6 +72,30 @@ static void ListenerOnExit() {
jvm->DetachCurrentThread();
}
/// throw java exception
static void ThrowJavaException(JNIEnv* env, const std::exception* e) {
wpi::SmallString<128> what;
jclass je = 0;
if (e) {
const char* exception_type = "std::exception";
if (dynamic_cast<const cv::Exception*>(e)) {
exception_type = "cv::Exception";
je = env->FindClass("org/opencv/core/CvException");
}
what = exception_type;
what += ": ";
what += e->what();
} else {
what = "unknown exception";
}
if (!je) je = exceptionEx;
env->ThrowNew(je, what.c_str());
}
extern "C" {
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
@@ -186,13 +223,14 @@ static inline bool CheckStatus(JNIEnv* env, CS_Status status) {
static jobject MakeJObject(JNIEnv* env, const cs::UsbCameraInfo& info) {
static jmethodID constructor = env->GetMethodID(
usbCameraInfoCls, "<init>",
"(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V");
"(ILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;II)V");
JLocal<jstring> path(env, MakeJString(env, info.path));
JLocal<jstring> name(env, MakeJString(env, info.name));
JLocal<jobjectArray> otherPaths(env, MakeJStringArray(env, info.otherPaths));
return env->NewObject(usbCameraInfoCls, constructor,
static_cast<jint>(info.dev), path.obj(), name.obj(),
otherPaths.obj());
otherPaths.obj(), static_cast<jint>(info.vendorId),
static_cast<jint>(info.productId));
}
static jobject MakeJObject(JNIEnv* env, const cs::VideoMode& videoMode) {
@@ -506,12 +544,12 @@ Java_edu_wpi_cscore_CameraServerJNI_createHttpCameraMulti
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: createCvSource
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createCvSource
Java_edu_wpi_cscore_CameraServerCvJNI_createCvSource
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
jint fps)
{
@@ -530,6 +568,31 @@ Java_edu_wpi_cscore_CameraServerJNI_createCvSource
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: createRawSource
* Signature: (Ljava/lang/String;IIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createRawSource
(JNIEnv* env, jclass, jstring name, jint pixelFormat, jint width, jint height,
jint fps)
{
if (!name) {
nullPointerEx.Throw(env, "name cannot be null");
return 0;
}
CS_Status status = 0;
auto val = cs::CreateRawSource(
JStringRef{env, name}.str(),
cs::VideoMode{static_cast<cs::VideoMode::PixelFormat>(pixelFormat),
static_cast<int>(width), static_cast<int>(height),
static_cast<int>(fps)},
&status);
CheckStatus(env, status);
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: getSourceKind
@@ -1054,17 +1117,68 @@ Java_edu_wpi_cscore_CameraServerJNI_getHttpCameraUrls
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: putSourceFrame
* Signature: (IJ)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_putSourceFrame
Java_edu_wpi_cscore_CameraServerCvJNI_putSourceFrame
(JNIEnv* env, jclass, jint source, jlong imageNativeObj)
{
cv::Mat& image = *((cv::Mat*)imageNativeObj);
try {
cv::Mat& image = *((cv::Mat*)imageNativeObj);
CS_Status status = 0;
cs::PutSourceFrame(source, image, &status);
CheckStatus(env, status);
} catch (const std::exception& e) {
ThrowJavaException(env, &e);
} catch (...) {
ThrowJavaException(env, 0);
}
}
// int width, int height, int pixelFormat, int totalData
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: putRawSourceFrameBB
* Signature: (ILjava/lang/Object;IIII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrameBB
(JNIEnv* env, jclass, jint source, jobject byteBuffer, jint width,
jint height, jint pixelFormat, jint totalData)
{
CS_RawFrame rawFrame;
rawFrame.data =
reinterpret_cast<char*>(env->GetDirectBufferAddress(byteBuffer));
rawFrame.totalData = totalData;
rawFrame.pixelFormat = pixelFormat;
rawFrame.width = width;
rawFrame.height = height;
CS_Status status = 0;
cs::PutSourceFrame(source, image, &status);
cs::PutSourceFrame(source, rawFrame, &status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: putRawSourceFrame
* Signature: (IJIIII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_putRawSourceFrame
(JNIEnv* env, jclass, jint source, jlong ptr, jint width, jint height,
jint pixelFormat, jint totalData)
{
CS_RawFrame rawFrame;
rawFrame.data = reinterpret_cast<char*>(static_cast<intptr_t>(ptr));
rawFrame.totalData = totalData;
rawFrame.pixelFormat = pixelFormat;
rawFrame.width = width;
rawFrame.height = height;
CS_Status status = 0;
cs::PutSourceFrame(source, rawFrame, &status);
CheckStatus(env, status);
}
@@ -1192,12 +1306,12 @@ Java_edu_wpi_cscore_CameraServerJNI_createMjpegServer
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: createCvSink
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createCvSink
Java_edu_wpi_cscore_CameraServerCvJNI_createCvSink
(JNIEnv* env, jclass, jstring name)
{
if (!name) {
@@ -1210,6 +1324,25 @@ Java_edu_wpi_cscore_CameraServerJNI_createCvSink
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: createRawSink
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_cscore_CameraServerJNI_createRawSink
(JNIEnv* env, jclass, jstring name)
{
if (!name) {
nullPointerEx.Throw(env, "name cannot be null");
return 0;
}
CS_Status status = 0;
auto val = cs::CreateRawSink(JStringRef{env, name}.str(), &status);
CheckStatus(env, status);
return val;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: getSinkKind
@@ -1449,34 +1582,119 @@ Java_edu_wpi_cscore_CameraServerJNI_setSinkDescription
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: grabSinkFrame
* Signature: (IJ)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrame
Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrame
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj)
{
cv::Mat& image = *((cv::Mat*)imageNativeObj);
try {
cv::Mat& image = *((cv::Mat*)imageNativeObj);
CS_Status status = 0;
auto rv = cs::GrabSinkFrame(sink, image, &status);
CheckStatus(env, status);
return rv;
} catch (const std::exception& e) {
ThrowJavaException(env, &e);
return 0;
} catch (...) {
ThrowJavaException(env, 0);
return 0;
}
}
/*
* Class: edu_wpi_cscore_CameraServerCvJNI
* Method: grabSinkFrameTimeout
* Signature: (IJD)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerCvJNI_grabSinkFrameTimeout
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj, jdouble timeout)
{
try {
cv::Mat& image = *((cv::Mat*)imageNativeObj);
CS_Status status = 0;
auto rv = cs::GrabSinkFrameTimeout(sink, image, timeout, &status);
CheckStatus(env, status);
return rv;
} catch (const std::exception& e) {
ThrowJavaException(env, &e);
return 0;
} catch (...) {
ThrowJavaException(env, 0);
return 0;
}
}
static void SetRawFrameData(JNIEnv* env, jobject rawFrameObj,
jobject byteBuffer, bool didChangeDataPtr,
const CS_RawFrame& frame) {
static jmethodID setMethod =
env->GetMethodID(rawFrameCls, "setData", "(Ljava/nio/ByteBuffer;JIIII)V");
jlong framePtr = static_cast<jlong>(reinterpret_cast<intptr_t>(frame.data));
if (didChangeDataPtr) {
byteBuffer = env->NewDirectByteBuffer(frame.data, frame.dataLength);
}
env->CallVoidMethod(
rawFrameObj, setMethod, byteBuffer, framePtr,
static_cast<jint>(frame.totalData), static_cast<jint>(frame.width),
static_cast<jint>(frame.height), static_cast<jint>(frame.pixelFormat));
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: grabRawSinkFrameImpl
* Signature: (ILjava/lang/Object;JLjava/lang/Object;III)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameImpl
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
jobject byteBuffer, jint width, jint height, jint pixelFormat)
{
CS_RawFrame* ptr =
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
auto origDataPtr = ptr->data;
ptr->width = width;
ptr->height = height;
ptr->pixelFormat = pixelFormat;
CS_Status status = 0;
auto rv = cs::GrabSinkFrame(sink, image, &status);
CheckStatus(env, status);
auto rv = cs::GrabSinkFrame(static_cast<CS_Sink>(sink), *ptr, &status);
if (!CheckStatus(env, status)) {
return 0;
}
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
return rv;
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: grabSinkFrameTimeout
* Signature: (IJD)J
* Method: grabRawSinkFrameTimeoutImpl
* Signature: (ILjava/lang/Object;JLjava/lang/Object;IIID)J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_grabSinkFrameTimeout
(JNIEnv* env, jclass, jint sink, jlong imageNativeObj, jdouble timeout)
Java_edu_wpi_cscore_CameraServerJNI_grabRawSinkFrameTimeoutImpl
(JNIEnv* env, jclass, jint sink, jobject rawFrameObj, jlong rawFramePtr,
jobject byteBuffer, jint width, jint height, jint pixelFormat,
jdouble timeout)
{
cv::Mat& image = *((cv::Mat*)imageNativeObj);
CS_RawFrame* ptr =
reinterpret_cast<CS_RawFrame*>(static_cast<intptr_t>(rawFramePtr));
auto origDataPtr = ptr->data;
ptr->width = width;
ptr->height = height;
ptr->pixelFormat = pixelFormat;
CS_Status status = 0;
auto rv = cs::GrabSinkFrameTimeout(sink, image, timeout, &status);
CheckStatus(env, status);
auto rv = cs::GrabSinkFrameTimeout(static_cast<CS_Sink>(sink), *ptr, timeout,
&status);
if (!CheckStatus(env, status)) {
return 0;
}
SetRawFrameData(env, rawFrameObj, byteBuffer, origDataPtr != ptr->data, *ptr);
return rv;
}
@@ -1781,4 +1999,32 @@ Java_edu_wpi_cscore_CameraServerJNI_setLogger
minLevel);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: allocateRawFrame
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_cscore_CameraServerJNI_allocateRawFrame
(JNIEnv*, jclass)
{
cs::RawFrame* rawFrame = new cs::RawFrame{};
intptr_t rawFrameIntPtr = reinterpret_cast<intptr_t>(rawFrame);
return static_cast<jlong>(rawFrameIntPtr);
}
/*
* Class: edu_wpi_cscore_CameraServerJNI
* Method: freeRawFrame
* Signature: (J)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_cscore_CameraServerJNI_freeRawFrame
(JNIEnv*, jclass, jlong rawFrame)
{
cs::RawFrame* ptr =
reinterpret_cast<cs::RawFrame*>(static_cast<intptr_t>(rawFrame));
delete ptr;
}
} // extern "C"

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2016-2018 FIRST. All Rights Reserved. */
/* 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. */
@@ -20,8 +20,6 @@
extern "C" {
#endif
struct CvMat;
/**
* @defgroup cscore_c_api cscore C API
*
@@ -128,7 +126,8 @@ enum CS_SourceKind {
CS_SOURCE_UNKNOWN = 0,
CS_SOURCE_USB = 1,
CS_SOURCE_HTTP = 2,
CS_SOURCE_CV = 4
CS_SOURCE_CV = 4,
CS_SOURCE_RAW = 8,
};
/**
@@ -144,7 +143,12 @@ enum CS_HttpCameraKind {
/**
* Sink kinds
*/
enum CS_SinkKind { CS_SINK_UNKNOWN = 0, CS_SINK_MJPEG = 2, CS_SINK_CV = 4 };
enum CS_SinkKind {
CS_SINK_UNKNOWN = 0,
CS_SINK_MJPEG = 2,
CS_SINK_CV = 4,
CS_SINK_RAW = 8
};
/**
* Listener event kinds
@@ -232,6 +236,8 @@ typedef struct CS_UsbCameraInfo {
char* name;
int otherPathsCount;
char** otherPaths;
int vendorId;
int productId;
} CS_UsbCameraInfo;
/**
@@ -351,8 +357,6 @@ char** CS_GetHttpCameraUrls(CS_Source source, int* count, CS_Status* status);
* @defgroup cscore_opencv_source_cfunc OpenCV Source Functions
* @{
*/
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
CS_Status* status);
void CS_NotifySourceError(CS_Source source, const char* msg, CS_Status* status);
void CS_SetSourceConnected(CS_Source source, CS_Bool connected,
CS_Status* status);
@@ -415,9 +419,6 @@ int CS_GetMjpegServerPort(CS_Sink sink, CS_Status* status);
*/
void CS_SetSinkDescription(CS_Sink sink, const char* description,
CS_Status* status);
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, CS_Status* status);
uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
double timeout, CS_Status* status);
char* CS_GetSinkError(CS_Sink sink, CS_Status* status);
void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status);
/** @} */

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2015-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. */
@@ -21,9 +21,11 @@
#include "cscore_c.h"
namespace cv {
class Mat;
} // namespace cv
#ifdef _WIN32
// Disable uninitialized variable warnings
#pragma warning(push)
#pragma warning(disable : 26495)
#endif
namespace wpi {
class json;
@@ -54,6 +56,10 @@ struct UsbCameraInfo {
std::string name;
/** Other path aliases to device (e.g. '/dev/v4l/by-id/...' etc on Linux) */
std::vector<std::string> otherPaths;
/** USB Vendor Id */
int vendorId = -1;
/** USB Product Id */
int productId = -1;
};
/**
@@ -286,7 +292,6 @@ std::vector<std::string> GetHttpCameraUrls(CS_Source source, CS_Status* status);
* @defgroup cscore_opencv_source_func OpenCV Source Functions
* @{
*/
void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status);
void NotifySourceError(CS_Source source, const wpi::Twine& msg,
CS_Status* status);
void SetSourceConnected(CS_Source source, bool connected, CS_Status* status);
@@ -312,6 +317,7 @@ CS_Sink CreateCvSink(const wpi::Twine& name, CS_Status* status);
CS_Sink CreateCvSinkCallback(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status);
/** @} */
/**
@@ -356,9 +362,6 @@ int GetMjpegServerPort(CS_Sink sink, CS_Status* status);
*/
void SetSinkDescription(CS_Sink sink, const wpi::Twine& description,
CS_Status* status);
uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat& image, CS_Status* status);
uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
CS_Status* status);
std::string GetSinkError(CS_Sink sink, CS_Status* status);
wpi::StringRef GetSinkError(CS_Sink sink, wpi::SmallVectorImpl<char>& buf,
CS_Status* status);
@@ -429,18 +432,9 @@ std::vector<std::string> GetNetworkInterfaces();
} // namespace cs
/**
* @defgroup cscore_cpp_opencv_special cscore C functions taking a cv::Mat*
*
* These are needed for specific interop implementations.
* @{
*/
extern "C" {
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status);
uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
double timeout, CS_Status* status);
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status);
} // extern "C"
/** @} */
#ifdef _WIN32
// Disable uninitialized variable warnings
#pragma warning(pop)
#endif
#endif // CSCORE_CSCORE_CPP_H_

View File

@@ -0,0 +1,209 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-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. */
/*----------------------------------------------------------------------------*/
#ifndef CSCORE_CSCORE_CV_H_
#define CSCORE_CSCORE_CV_H_
#include "cscore_c.h"
#ifdef CSCORE_CSCORE_RAW_CV_H_
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
#endif
#ifdef __cplusplus
#include "cscore_oo.h" // NOLINT(build/include_order)
#endif
#if CV_VERSION_MAJOR < 4
#ifdef __cplusplus
extern "C" { // NOLINT(build/include_order)
#endif
struct CvMat;
void CS_PutSourceFrame(CS_Source source, struct CvMat* image,
CS_Status* status);
uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, CS_Status* status);
uint64_t CS_GrabSinkFrameTimeout(CS_Sink sink, struct CvMat* image,
double timeout, CS_Status* status);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // CV_VERSION_MAJOR < 4
#ifdef __cplusplus
#include "cscore_oo.h"
namespace cv {
class Mat;
} // namespace cv
namespace cs {
/**
* @defgroup cscore_cpp_opencv_special cscore C functions taking a cv::Mat*
*
* These are needed for specific interop implementations.
* @{
*/
extern "C" {
uint64_t CS_GrabSinkFrameCpp(CS_Sink sink, cv::Mat* image, CS_Status* status);
uint64_t CS_GrabSinkFrameTimeoutCpp(CS_Sink sink, cv::Mat* image,
double timeout, CS_Status* status);
void CS_PutSourceFrameCpp(CS_Source source, cv::Mat* image, CS_Status* status);
} // extern "C"
/** @} */
void PutSourceFrame(CS_Source source, cv::Mat& image, CS_Status* status);
uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat& image, CS_Status* status);
uint64_t GrabSinkFrameTimeout(CS_Sink sink, cv::Mat& image, double timeout,
CS_Status* status);
/**
* A source for user code to provide OpenCV images as video frames.
* These sources require the WPILib OpenCV builds.
* For an alternate OpenCV, include "cscore_raw_cv.h" instead, and
* include your Mat header before that header.
*/
class CvSource : public ImageSource {
public:
CvSource() = default;
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
CvSource(const wpi::Twine& name, const VideoMode& mode);
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
int width, int height, int 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
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
*
* @param image OpenCV image
*/
void PutFrame(cv::Mat& image);
};
/**
* A sink for user code to accept video frames as OpenCV images.
* These sinks require the WPILib OpenCV builds.
* For an alternate OpenCV, include "cscore_raw_cv.h" instead, and
* include your Mat header before that header.
*/
class CvSink : public ImageSink {
public:
CvSink() = default;
/**
* Create a sink for accepting OpenCV images.
*
* <p>WaitForFrame() must be called on the created sink to get each new
* image.
*
* @param name Source name (arbitrary unique identifier)
*/
explicit CvSink(const wpi::Twine& name);
/**
* Create a sink for accepting OpenCV images in a separate thread.
*
* <p>A thread will be created that calls WaitForFrame() and calls the
* processFrame() callback each time a new frame arrives.
*
* @param name Source name (arbitrary unique identifier)
* @param processFrame Frame processing function; will be called with a
* time=0 if an error occurred. processFrame should call GetImage()
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
CvSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame);
/**
* 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.
*/
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) const;
/**
* 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.
*/
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
};
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
m_handle = CreateCvSource(name, mode, &m_status);
}
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
int width, int height, int fps) {
m_handle =
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
}
inline void CvSource::PutFrame(cv::Mat& image) {
m_status = 0;
PutSourceFrame(m_handle, image, &m_status);
}
inline CvSink::CvSink(const wpi::Twine& name) {
m_handle = CreateCvSink(name, &m_status);
}
inline CvSink::CvSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame) {
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
}
inline uint64_t CvSink::GrabFrame(cv::Mat& image, double timeout) const {
m_status = 0;
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
}
inline uint64_t CvSink::GrabFrameNoTimeout(cv::Mat& image) const {
m_status = 0;
return GrabSinkFrame(m_handle, image, &m_status);
}
} // namespace cs
#endif
#endif // CSCORE_CSCORE_CV_H_

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2015-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. */
@@ -28,7 +28,7 @@ namespace cs {
*/
// Forward declarations so friend declarations work correctly
class CvSource;
class ImageSource;
class VideoEvent;
class VideoSink;
class VideoSource;
@@ -37,7 +37,7 @@ class VideoSource;
* A source or sink property.
*/
class VideoProperty {
friend class CvSource;
friend class ImageSource;
friend class VideoEvent;
friend class VideoSink;
friend class VideoSource;
@@ -51,7 +51,7 @@ class VideoProperty {
kEnum = CS_PROP_ENUM
};
VideoProperty() : m_handle(0), m_kind(kNone) {}
VideoProperty() : m_status(0), m_handle(0), m_kind(kNone) {}
std::string GetName() const;
@@ -617,43 +617,13 @@ class AxisCamera : public HttpCamera {
};
/**
* A source for user code to provide OpenCV images as video frames.
* A base class for single image providing sources.
*/
class CvSource : public VideoSource {
class ImageSource : public VideoSource {
protected:
ImageSource() = default;
public:
CvSource() = default;
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
CvSource(const wpi::Twine& name, const VideoMode& mode);
/**
* Create an OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
CvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
int width, int height, int 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
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
*
* @param image OpenCV image
*/
void PutFrame(cv::Mat& image);
/**
* Signal sinks that an error has occurred. This should be called instead
* of NotifyFrame when an error occurs.
@@ -979,37 +949,13 @@ class MjpegServer : public VideoSink {
};
/**
* A sink for user code to accept video frames as OpenCV images.
* A base class for single image reading sinks.
*/
class CvSink : public VideoSink {
class ImageSink : public VideoSink {
protected:
ImageSink() = default;
public:
CvSink() = default;
/**
* Create a sink for accepting OpenCV images.
*
* <p>WaitForFrame() must be called on the created sink to get each new
* image.
*
* @param name Source name (arbitrary unique identifier)
*/
explicit CvSink(const wpi::Twine& name);
/**
* Create a sink for accepting OpenCV images in a separate thread.
*
* <p>A thread will be created that calls WaitForFrame() and calls the
* processFrame() callback each time a new frame arrives.
*
* @param name Source name (arbitrary unique identifier)
* @param processFrame Frame processing function; will be called with a
* time=0 if an error occurred. processFrame should call GetImage()
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
CvSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame);
/**
* Set sink description.
*
@@ -1017,27 +963,6 @@ class CvSink : public VideoSink {
*/
void SetDescription(const wpi::Twine& description);
/**
* 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.
*/
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225) const;
/**
* 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.
*/
uint64_t GrabFrameNoTimeout(cv::Mat& image) const;
/**
* Get error string. Call this if WaitForFrame() returns 0 to determine
* what the error is.

View File

@@ -76,7 +76,7 @@ inline VideoProperty::VideoProperty(CS_Property handle) : m_handle(handle) {
}
inline VideoProperty::VideoProperty(CS_Property handle, Kind kind)
: m_handle(handle), m_kind(kind) {}
: m_status(0), m_handle(handle), m_kind(kind) {}
inline VideoSource::VideoSource(const VideoSource& source)
: m_handle(source.m_handle == 0 ? 0
@@ -378,37 +378,22 @@ inline AxisCamera::AxisCamera(const wpi::Twine& name,
std::initializer_list<T> hosts)
: HttpCamera(name, HostToUrl(hosts), kAxis) {}
inline CvSource::CvSource(const wpi::Twine& name, const VideoMode& mode) {
m_handle = CreateCvSource(name, mode, &m_status);
}
inline CvSource::CvSource(const wpi::Twine& name, VideoMode::PixelFormat format,
int width, int height, int fps) {
m_handle =
CreateCvSource(name, VideoMode{format, width, height, fps}, &m_status);
}
inline void CvSource::PutFrame(cv::Mat& image) {
m_status = 0;
PutSourceFrame(m_handle, image, &m_status);
}
inline void CvSource::NotifyError(const wpi::Twine& msg) {
inline void ImageSource::NotifyError(const wpi::Twine& msg) {
m_status = 0;
NotifySourceError(m_handle, msg, &m_status);
}
inline void CvSource::SetConnected(bool connected) {
inline void ImageSource::SetConnected(bool connected) {
m_status = 0;
SetSourceConnected(m_handle, connected, &m_status);
}
inline void CvSource::SetDescription(const wpi::Twine& description) {
inline void ImageSource::SetDescription(const wpi::Twine& description) {
m_status = 0;
SetSourceDescription(m_handle, description, &m_status);
}
inline VideoProperty CvSource::CreateProperty(const wpi::Twine& name,
inline VideoProperty ImageSource::CreateProperty(const wpi::Twine& name,
VideoProperty::Kind kind,
int minimum, int maximum,
int step, int defaultValue,
@@ -419,7 +404,7 @@ inline VideoProperty CvSource::CreateProperty(const wpi::Twine& name,
minimum, maximum, step, defaultValue, value, &m_status)};
}
inline VideoProperty CvSource::CreateIntegerProperty(const wpi::Twine& name,
inline VideoProperty ImageSource::CreateIntegerProperty(const wpi::Twine& name,
int minimum, int maximum,
int step, int defaultValue,
int value) {
@@ -429,7 +414,7 @@ inline VideoProperty CvSource::CreateIntegerProperty(const wpi::Twine& name,
minimum, maximum, step, defaultValue, value, &m_status)};
}
inline VideoProperty CvSource::CreateBooleanProperty(const wpi::Twine& name,
inline VideoProperty ImageSource::CreateBooleanProperty(const wpi::Twine& name,
bool defaultValue,
bool value) {
m_status = 0;
@@ -438,7 +423,7 @@ inline VideoProperty CvSource::CreateBooleanProperty(const wpi::Twine& name,
0, 1, 1, defaultValue ? 1 : 0, value ? 1 : 0, &m_status)};
}
inline VideoProperty CvSource::CreateStringProperty(const wpi::Twine& name,
inline VideoProperty ImageSource::CreateStringProperty(const wpi::Twine& name,
const wpi::Twine& value) {
m_status = 0;
auto prop = VideoProperty{CreateSourceProperty(
@@ -449,14 +434,14 @@ inline VideoProperty CvSource::CreateStringProperty(const wpi::Twine& name,
}
inline void CvSource::SetEnumPropertyChoices(
inline void ImageSource::SetEnumPropertyChoices(
const VideoProperty& property, wpi::ArrayRef<std::string> choices) {
m_status = 0;
SetSourceEnumPropertyChoices(m_handle, property.m_handle, choices, &m_status);
}
template <typename T>
inline void CvSource::SetEnumPropertyChoices(const VideoProperty& property,
inline void ImageSource::SetEnumPropertyChoices(const VideoProperty& property,
std::initializer_list<T> choices) {
std::vector<std::string> vec;
vec.reserve(choices.size());
@@ -575,36 +560,17 @@ inline void MjpegServer::SetDefaultCompression(int quality) {
quality, &m_status);
}
inline CvSink::CvSink(const wpi::Twine& name) {
m_handle = CreateCvSink(name, &m_status);
}
inline CvSink::CvSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame) {
m_handle = CreateCvSinkCallback(name, processFrame, &m_status);
}
inline void CvSink::SetDescription(const wpi::Twine& description) {
inline void ImageSink::SetDescription(const wpi::Twine& description) {
m_status = 0;
SetSinkDescription(m_handle, description, &m_status);
}
inline uint64_t CvSink::GrabFrame(cv::Mat& image, double timeout) const {
m_status = 0;
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
}
inline uint64_t CvSink::GrabFrameNoTimeout(cv::Mat& image) const {
m_status = 0;
return GrabSinkFrame(m_handle, image, &m_status);
}
inline std::string CvSink::GetError() const {
inline std::string ImageSink::GetError() const {
m_status = 0;
return GetSinkError(m_handle, &m_status);
}
inline void CvSink::SetEnabled(bool enabled) {
inline void ImageSink::SetEnabled(bool enabled) {
m_status = 0;
SetSinkEnabled(m_handle, enabled, &m_status);
}

View File

@@ -0,0 +1,234 @@
/*----------------------------------------------------------------------------*/
/* 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. */
/*----------------------------------------------------------------------------*/
#ifndef CSCORE_CSCORE_RAW_H_
#define CSCORE_CSCORE_RAW_H_
#include "cscore_c.h"
#ifdef __cplusplus
#include "cscore_oo.h"
#endif
/**
* Raw Frame
*/
typedef struct CS_RawFrame {
char* data;
int dataLength;
int pixelFormat;
int width;
int height;
int totalData;
} CS_RawFrame;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup cscore_raw_cfunc Raw Image Functions
* @{
*/
void CS_AllocateRawFrameData(CS_RawFrame* frame, int requestedSize);
void CS_FreeRawFrameData(CS_RawFrame* frame);
uint64_t CS_GrabRawSinkFrame(CS_Sink sink, struct CS_RawFrame* rawImage,
CS_Status* status);
uint64_t CS_GrabRawSinkFrameTimeout(CS_Sink sink, struct CS_RawFrame* rawImage,
double timeout, CS_Status* status);
CS_Sink CS_CreateRawSink(const char* name, CS_Status* status);
CS_Sink CS_CreateRawSinkCallback(const char* name, void* data,
void (*processFrame)(void* data,
uint64_t time),
CS_Status* status);
void CS_PutRawSourceFrame(CS_Source source, const struct CS_RawFrame* image,
CS_Status* status);
CS_Source CS_CreateRawSource(const char* name, const CS_VideoMode* mode,
CS_Status* status);
/** @} */
#ifdef __cplusplus
} // extern "C"
#endif
#ifdef __cplusplus
namespace cs {
struct RawFrame : public CS_RawFrame {
RawFrame() {
data = nullptr;
dataLength = 0;
pixelFormat = CS_PIXFMT_UNKNOWN;
width = 0;
height = 0;
totalData = 0;
}
~RawFrame() { CS_FreeRawFrameData(this); }
};
/**
* @defgroup cscore_raw_func Raw Image Functions
* @{
*/
CS_Source CreateRawSource(const wpi::Twine& name, const VideoMode& mode,
CS_Status* status);
CS_Sink CreateRawSink(const wpi::Twine& name, CS_Status* status);
CS_Sink CreateRawSinkCallback(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame,
CS_Status* status);
void PutSourceFrame(CS_Source source, const CS_RawFrame& image,
CS_Status* status);
uint64_t GrabSinkFrame(CS_Sink sink, CS_RawFrame& image, CS_Status* status);
uint64_t GrabSinkFrameTimeout(CS_Sink sink, CS_RawFrame& image, double timeout,
CS_Status* status);
/**
* A source for user code to provide video frames as raw bytes.
*
* This is a complex API, most cases should use CvSource.
*/
class RawSource : public ImageSource {
public:
RawSource() = default;
/**
* Create a raw frame source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
RawSource(const wpi::Twine& name, const VideoMode& mode);
/**
* Create a raw frame source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
RawSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
int width, int height, int fps);
protected:
/**
* Put a raw image and notify sinks.
*
* @param image raw frame image
*/
void PutFrame(RawFrame& image);
};
/**
* A sink for user code to accept video frames as raw bytes.
*
* This is a complex API, most cases should use CvSource.
*/
class RawSink : public ImageSink {
public:
RawSink() = default;
/**
* 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)
*/
explicit RawSink(const wpi::Twine& name);
/**
* Create a sink for accepting raws images in a separate thread.
*
* <p>A thread will be created that calls WaitForFrame() and calls the
* processFrame() callback each time a new frame arrives.
*
* @param name Source name (arbitrary unique identifier)
* @param processFrame Frame processing function; will be called with a
* time=0 if an error occurred. processFrame should call GetImage()
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
RawSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame);
protected:
/**
* 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.
*/
uint64_t GrabFrame(RawFrame& image, double timeout = 0.225) const;
/**
* 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.
*/
uint64_t GrabFrameNoTimeout(RawFrame& image) const;
};
inline RawSource::RawSource(const wpi::Twine& name, const VideoMode& mode) {
m_handle = CreateRawSource(name, mode, &m_status);
}
inline RawSource::RawSource(const wpi::Twine& name,
VideoMode::PixelFormat format, int width,
int height, int fps) {
m_handle =
CreateRawSource(name, VideoMode{format, width, height, fps}, &m_status);
}
inline void RawSource::PutFrame(RawFrame& image) {
m_status = 0;
PutSourceFrame(m_handle, image, &m_status);
}
inline RawSink::RawSink(const wpi::Twine& name) {
m_handle = CreateRawSink(name, &m_status);
}
inline RawSink::RawSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame) {
m_handle = CreateRawSinkCallback(name, processFrame, &m_status);
}
inline uint64_t RawSink::GrabFrame(RawFrame& image, double timeout) const {
m_status = 0;
return GrabSinkFrameTimeout(m_handle, image, timeout, &m_status);
}
inline uint64_t RawSink::GrabFrameNoTimeout(RawFrame& image) const {
m_status = 0;
return GrabSinkFrame(m_handle, image, &m_status);
}
} // namespace cs
/** @} */
#endif
#endif // CSCORE_CSCORE_RAW_H_

View File

@@ -0,0 +1,218 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-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. */
/*----------------------------------------------------------------------------*/
#ifndef CSCORE_CSCORE_RAW_CV_H_
#define CSCORE_CSCORE_RAW_CV_H_
#ifdef CSCORE_CSCORE_CV_H_
#error "Cannot include both cscore_cv.h and cscore_raw_cv.h in the same file"
#endif
#include "cscore_raw.h"
namespace cs {
/**
* A source for using the raw frame API to provide opencv images.
*
* If you are using the WPILib OpenCV builds, do not use this, and
* instead include "cscore_cv.h" to get a more performant version.
*
* This is not dependent on any opencv binary ABI, and can be used
* with versions of OpenCV that are not 3. If using OpenCV 3, use
* CvSource.
*/
class RawCvSource : public RawSource {
public:
RawCvSource() = default;
/**
* Create a Raw OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param mode Video mode being generated
*/
RawCvSource(const wpi::Twine& name, const VideoMode& mode);
/**
* Create a Raw OpenCV source.
*
* @param name Source name (arbitrary unique identifier)
* @param pixelFormat Pixel format
* @param width width
* @param height height
* @param fps fps
*/
RawCvSource(const wpi::Twine& name, VideoMode::PixelFormat pixelFormat,
int width, int height, int 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
* cv::Mat::convertTo() and/or cv::cvtColor() to convert it first.
*
* @param image OpenCV image
*/
void PutFrame(cv::Mat& image);
private:
RawFrame rawFrame;
};
/**
* A sink for user code to accept raw video frames as OpenCV images.
*
* If you are using the WPILib OpenCV builds, do not use this, and
* instead include "cscore_cv.h" to get a more performant version.
*
* This is not dependent on any opencv binary ABI, and can be used
* with versions of OpenCV that are not 3. If using OpenCV 3, use
* CvSink.
*/
class RawCvSink : public RawSink {
public:
RawCvSink() = default;
/**
* Create a sink for accepting OpenCV images.
*
* <p>WaitForFrame() must be called on the created sink to get each new
* image.
*
* @param name Source name (arbitrary unique identifier)
*/
explicit RawCvSink(const wpi::Twine& name);
/**
* Create a sink for accepting OpenCV images in a separate thread.
*
* <p>A thread will be created that calls WaitForFrame() and calls the
* processFrame() callback each time a new frame arrives.
*
* @param name Source name (arbitrary unique identifier)
* @param processFrame Frame processing function; will be called with a
* time=0 if an error occurred. processFrame should call GetImage()
* or GetError() as needed, but should not call (except in very
* unusual circumstances) WaitForImage().
*/
RawCvSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame);
/**
* 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.
*/
uint64_t GrabFrame(cv::Mat& image, double timeout = 0.225);
/**
* 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.
*/
uint64_t GrabFrameNoTimeout(cv::Mat& image);
/**
* 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.
*/
uint64_t GrabFrameDirect(cv::Mat& image, double timeout = 0.225);
/**
* 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.
*/
uint64_t GrabFrameNoTimeoutDirect(cv::Mat& image);
private:
RawFrame rawFrame;
};
inline RawCvSource::RawCvSource(const wpi::Twine& name, const VideoMode& mode)
: RawSource{name, mode} {}
inline RawCvSource::RawCvSource(const wpi::Twine& name,
VideoMode::PixelFormat format, int width,
int height, int fps)
: RawSource{name, format, width, height, fps} {}
inline void RawCvSource::PutFrame(cv::Mat& image) {
m_status = 0;
rawFrame.data = reinterpret_cast<char*>(image.data);
rawFrame.width = image.cols;
rawFrame.height = image.rows;
rawFrame.totalData = image.total() * image.channels;
rawFrame.pixelFormat = image.channels == 3 ? CS_PIXFMT_BGR : CS_PIXFMT_GRAY;
PutSourceFrame(m_handle, rawFrame, &m_status);
}
inline RawCvSink::RawCvSink(const wpi::Twine& name) : RawSink{name} {}
inline RawCvSink::RawCvSink(const wpi::Twine& name,
std::function<void(uint64_t time)> processFrame)
: RawSink{name, processFrame} {}
inline uint64_t RawCvSink::GrabFrame(cv::Mat& image, double timeout) {
cv::Mat tmpMat;
auto retVal = GrabFrameDirect(tmpMat);
if (retVal <= 0) {
return retVal;
}
tmpMat.copyTo(image);
return retVal;
}
inline uint64_t RawCvSink::GrabFrameNoTimeout(cv::Mat& image) {
cv::Mat tmpMat;
auto retVal = GrabFrameNoTimeoutDirect(tmpMat);
if (retVal <= 0) {
return retVal;
}
tmpMat.copyTo(image);
return retVal;
}
inline uint64_t RawCvSink::GrabFrameDirect(cv::Mat& image, double timeout) {
rawFrame.height = 0;
rawFrame.width = 0;
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
m_status = RawSink::GrabFrame(rawFrame, timeout);
if (m_status <= 0) return m_status;
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
return m_status;
}
inline uint64_t RawCvSink::GrabFrameNoTimeoutDirect(cv::Mat& image) {
rawFrame.height = 0;
rawFrame.width = 0;
rawFrame.pixelFormat = CS_PixelFormat::CS_PIXFMT_BGR;
m_status = RawSink::GrabFrameNoTimeout(rawFrame);
if (m_status <= 0) return m_status;
image = cv::Mat{rawFrame.height, rawFrame.width, CV_8UC3, rawFrame.data};
return m_status;
}
} // namespace cs
#endif // CSCORE_CSCORE_RAW_CV_H_

View File

@@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) 2015-2018 FIRST. All Rights Reserved. */
/* Copyright (c) 2015-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. */
@@ -132,8 +132,9 @@ void NetworkListener::Impl::Thread::Main() {
break; // XXX: is this the right thing to do here?
}
if (len == 0) continue; // EOF?
unsigned int ulen = static_cast<unsigned int>(len);
for (struct nlmsghdr* nh = reinterpret_cast<struct nlmsghdr*>(buf);
NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
NLMSG_OK(nh, ulen); nh = NLMSG_NEXT(nh, ulen)) {
if (nh->nlmsg_type == NLMSG_DONE) break;
if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK ||
nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) {

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